sending GetApiKeyCommand with v3 APIGatewayClient from canary does not return the value
Checkboxes for prior research
- [X] I've gone through Developer Guide and API reference
- [X] I've checked AWS Forums and StackOverflow.
- [X] I've searched for previous similar issues and didn't find any solution.
Describe the bug
Hello
I am trying to get api key with v3 APIGatewayClient from a canary. The problem is that there is no value in the response. When using v2-version, this works as expected.
The canary runtime is Runtime.SYNTHETICS_NODEJS_PUPPETEER_6_2
SDK version number
@aws-sdk/[email protected]
Which JavaScript Runtime is this issue in?
Node.js
Details of the browser/Node.js/ReactNative version
node 18, the version that is used in canaries
Reproduction Steps
import { MediaType } from "@digitraffic/common/dist/aws/types/mediatypes";
import { APIGatewayClient, GetApiKeyCommand } from "@aws-sdk/client-api-gateway";
export const handler = async (): Promise<void> => {
const client = new APIGatewayClient();
const command = new GetApiKeyCommand({
apiKey: "<keyId>",
includeValue: true,
});
const response = await client.send(command);
console.info("response " + JSON.stringify(response));
}
Observed Behavior
The response that gets printed, does not contain the actual key.
> {
"$metadata": {
"httpStatusCode": 200,
"requestId": "<requestId>",
"attempts": 1,
"totalRetryDelay": 0
}
}
Also, this gets printed:
Request: http://apigateway.eu-west-1.amazonaws.com/apikeys/<keyId>?includeValue=true
When using the v2, it's the same request but with https://
Expected Behavior
I expected this to work as in v2 and actually get the value of the api key.
Possible Solution
No response
Additional Information/Context
This looks like a similar problem: https://github.com/aws/aws-sdk-js-v3/issues/2352
Hi @teijosol ,
Thanks for the reproduction steps.
I'm able to confirm that this is an issue. The part I'm also very curious about is that the request is sent via http when the SDK is actually sending the request as https.
I was able to confirm that the request sent by the SDK is actually https by doing the following:
Reproduction:
- Using a request middleware to intercept the request before its being sent:
const client = new APIGatewayClient({
region: "us-east-1",
});
client.middlewareStack.add(next => async (args) => {
console.info(args.request);
const response = await next(args);
return response;
}, { step: 'finalizeRequest' });
This will log the raw request as it being sent from the SDK, and will result in the following log:
INFO HttpRequest {
method: 'GET',
hostname: 'apigateway.us-east-1.amazonaws.com',
port: undefined,
query: { includeValue: 'true' },
headers: {
accept: 'application/json',
host: 'apigateway.us-east-1.amazonaws.com',
'X-Amzn-Trace-Id': 'REDACTED,
'x-amz-user-agent': 'aws-sdk-js/3.515.0',
'user-agent': 'aws-sdk-js/3.515.0 ua/2.0 os/linux#4.14.255-336-277.563.amzn2.x86_64 lang/js md/nodejs#18.19.1 api/api-gateway#3.515.0 exec-env/AWS_Lambda_nodejs18.x',
'amz-sdk-invocation-id': 'cff37ee7-94d8-4b35-8492-67eaf633f34f',
'amz-sdk-request': 'attempt=1; max=3',
'x-amz-date': '20240319T220336Z',
'x-amz-security-token': 'REDACTED',
'x-amz-content-sha256': 'REDACTED',
authorization: 'AWS4-HMAC-SHA256 Credential=REDACTED/20240319/us-east-1/apigateway/aws4_request, SignedHeaders=accept;amz-sdk-invocation-id;amz-sdk-request;host;x-amz-content-sha256;x-amz-date;x-amz-security-token;x-amz-user-agent, Signature=REDACTED'
},
body: undefined,
protocol: 'https:', <--------
path: '/apikeys/1cwlcueire',
username: undefined,
password: undefined,
fragment: undefined
}
- Forcing the SDK to use a specific endpoint: in certain cases, the SDK endpoint resolution will result in some unexpected behavior, in those cases we can force the SDk to use an explicitly provided endpoint to ensure https:
const client = new APIGatewayClient({
region: "us-east-1",
endpoint: "https://apigateway.us-east-1.amazonaws.com"
});
But unfortunately this results in the same problem where the Canary sends the request using http, even though the request is sent by the SDK clearly as https.
More observations:
Sending this request locally, from a Node.JS application, results in the correct behavior without the need for any customization:
{
'$metadata': {
httpStatusCode: 200,
requestId: 'REDACTED',
extendedRequestId: undefined,
cfId: undefined,
attempts: 1,
totalRetryDelay: 0
},
createdDate: 2024-03-19T19:19:17.000Z,
enabled: true,
id: '1cwlcueire',
lastUpdatedDate: 2024-03-19T19:19:17.000Z,
name: 'foo-apigw-key',
stageKeys: [],
tags: {},
value: 'AVqfPdBADH3REDACTED'
}
Whereas forcing my local Node.JS application use an http endpoint, results in the application hanging until times out.
import { APIGatewayClient, GetApiKeyCommand } from "@aws-sdk/client-api-gateway";
const client = new APIGatewayClient({
region: "us-east-1",
endpoint: "http://apigateway.us-east-1.amazonaws.com" // explicitly setting http protocol
});
const command = new GetApiKeyCommand({
apiKey: "1cwlcueire",
includeValue: true,
});
const response = await client.send(command);
console.info(response)
Conclusion: It seems to me that this is an issue with the Canary runtime itself, and not with the SDK because in isolation the SDK works fine.
Assigning to queue for further investigation.
Thanks, Ran~
For what its worth, I'm seeing something similar for a call to cognito via the v3 sdk within a node canary runtime (7.0) - the reply indicates success (200 - OK) but the contents of the reply are missing - even though the cognito service does have the required changes applied indicating the command succeeded.
I have also seen evidence that this may have been around a long time : https://github.com/aws/aws-sdk-js-v3/issues/2352 which implies there is some other factor at play which is less obvious - otherwise more people between now and 2021 would have seen this issue.
See also: https://github.com/aws/aws-sdk-js-v3/discussions/5299
This work-around worked for me:
import { FetchHttpHandler } from '@smithy/fetch-http-handler'
// other code
const cognitoIdentity = new CognitoIdentity({
requestHandler: new FetchHttpHandler({})
})
Basically: explicity forcing the SDK to use the web browser fetch handler rather than the http one. The underlying bug seems to be in an interaction between the AWS v3 SDK and Bun (specifically Bun's implementation of node:HTTP). This works around the issue by forcing use of fetch rather than node:http.
I think I will have to try the work-around. It would be nice that this would be fixed, as V2 version is about to enter maintenance mode: https://aws.amazon.com/blogs/developer/announcing-end-of-support-for-aws-sdk-for-javascript-v2/