apollo-server-integrations / apollo-server-integration-aws-lambda

An integration to use AWS Lambda as a hosting service with Apollo Server
MIT License
46 stars 9 forks source link

Remove search params duplication #81

Closed 0x6368656174 closed 1 year ago

0x6368656174 commented 1 year ago

The AWS API Gateway V1 has two sources of query search params:

These sources contain the same parameters, but the last one supports parameters with equal names: ?a=...&a=....

Example of AWS API v1 event ``` { resource: '/', path: '/', httpMethod: 'GET', headers: { Accept: '*/*', 'CloudFront-Forwarded-Proto': 'https', 'CloudFront-Is-Desktop-Viewer': 'true', 'CloudFront-Is-Mobile-Viewer': 'false', 'CloudFront-Is-SmartTV-Viewer': 'false', 'CloudFront-Is-Tablet-Viewer': 'false', 'CloudFront-Viewer-ASN': '9422', 'CloudFront-Viewer-Country': 'ID', 'content-type': 'application/json', Host: '...', 'User-Agent': 'curl/7.85.0', Via: '2.0 a9cfec72cfc71c81978b7bbf79189fdc.cloudfront.net (CloudFront)', 'X-Amz-Cf-Id': 'zpPgbS1-Al5p_t9vhZGYi-8944KbT1VZJB3fPxjL-iwYp3sR0yYJeg==', 'X-Amzn-Trace-Id': 'Root=1-63edd5d2-576b61c53d416be4759dc1ac', 'X-Forwarded-For': '..., ...', 'X-Forwarded-Port': '443', 'X-Forwarded-Proto': 'https' }, multiValueHeaders: { Accept: [ '*/*' ], 'CloudFront-Forwarded-Proto': [ 'https' ], 'CloudFront-Is-Desktop-Viewer': [ 'true' ], 'CloudFront-Is-Mobile-Viewer': [ 'false' ], 'CloudFront-Is-SmartTV-Viewer': [ 'false' ], 'CloudFront-Is-Tablet-Viewer': [ 'false' ], 'CloudFront-Viewer-ASN': [ '9422' ], 'CloudFront-Viewer-Country': [ 'ID' ], 'content-type': [ 'application/json' ], Host: [ '...' ], 'User-Agent': [ 'curl/7.85.0' ], Via: [ '2.0 ....cloudfront.net (CloudFront)' ], 'X-Amz-Cf-Id': [ 'zpPgbS1-Al5p_t9vhZGYi-8944KbT1VZJB3fPxjL-iwYp3sR0yYJeg==' ], 'X-Amzn-Trace-Id': [ 'Root=1-63edd5d2-576b61c53d416be4759dc1ac' ], 'X-Forwarded-For': [ '..., ...' ], 'X-Forwarded-Port': [ '443' ], 'X-Forwarded-Proto': [ 'https' ] }, queryStringParameters: { extensions: '{"persistedQuery":{"version":1,"sha256Hash":"ecf4edb46db40b5132295c0291d62fb65d6759a9eedfa4d5d612dd5ec54a6b38"}}' }, multiValueQueryStringParameters: { extensions: [ '{"persistedQuery":{"version":1,"sha256Hash":"ecf4edb46db40b5132295c0291d62fb65d6759a9eedfa4d5d612dd5ec54a6b38"}}' ] }, pathParameters: null, stageVariables: null, requestContext: { resourceId: '...', resourcePath: '/', httpMethod: 'GET', extendedRequestId: 'Aa5Y9G7-ywMFVYw=', requestTime: '16/Feb/2023:07:05:54 +0000', path: '/prod/', accountId: '...', protocol: 'HTTP/1.1', stage: 'prod', domainPrefix: 'xxxuw5r50g', requestTimeEpoch: 1676531154670, requestId: '7d30c334-54c0-4302-945e-a3e46382f211', identity: { cognitoIdentityPoolId: null, accountId: null, cognitoIdentityId: null, caller: null, sourceIp: '...', principalOrgId: null, accessKey: null, cognitoAuthenticationType: null, cognitoAuthenticationProvider: null, userArn: null, userAgent: 'curl/7.85.0', user: null }, domainName: '...', apiId: '...' }, body: null, isBase64Encoded: false } ```

The APIGatewayProxyEventRequestHandler.ts tried to collect query parameters from both sources, that was the reason on such an error:

{"errors":
[{"message":"The 'extensions' search parameter may only be specified once.","extensions":{"code":"BAD_REQUEST","stacktrace":
["BadRequestError: The 'extensions' search parameter may only be specified once.","    
at new GraphQLErrorWithCode (/var/task/node_modules/@apollo/server/dist/cjs/internalErrorClasses.js:10:9)","    
at new BadRequestError (/var/task/node_modules/@apollo/server/dist/cjs/internalErrorClasses.js:84:9)","    
at searchParamIfSpecifiedOnce (/var/task/node_modules/@apollo/server/dist/cjs/runHttpQuery.js:27:19)","    
at jsonParsedSearchParamIfSpecifiedOnce (/var/task/node_modules/@apollo/server/dist/cjs/runHttpQuery.js:31:19)","    
at runHttpQuery (/var/task/node_modules/@apollo/server/dist/cjs/runHttpQuery.js:120:29)","    
at runPotentiallyBatchedHttpQuery (/var/task/node_modules/@apollo/server/dist/cjs/httpBatching.js:37:57)","    
at ApolloServer.executeHTTPGraphQLRequest (/var/task/node_modules/@apollo/server/dist/cjs/ApolloServer.js:525:79)","
at async Runtime.handler (/var/task/node_modules/@as-integrations/aws-lambda/dist/lambdaHandler.js:18:30)"
]}}]}

It was happened because extensions param was set twice: from queryStringParameters and from multiValueQueryStringParameters.

This PR removes queryStringParameters supporting to avoid query params duplication.

changeset-bot[bot] commented 1 year ago

🦋 Changeset detected

Latest commit: 4a98c0deb80e90d0f8006c38cd6c4fa401278557

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package | Name | Type | | --------------------------- | ----- | | @as-integrations/aws-lambda | Patch |

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

codesandbox-ci[bot] commented 1 year ago

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 4a98c0deb80e90d0f8006c38cd6c4fa401278557:

Sandbox Source
apollo-server-integration-aws-lambda Configuration
0x6368656174 commented 1 year ago

By the way. Looks like the ALBEventRequestHandler.ts has the same problem, but I'm not sure, because I don't use ALB.

BlenderDude commented 1 year ago

Thanks for the PR! I'll go ahead and get this merged. Looks like ALB is actually a bit more tricky and is based on the listener config as outlined here. I'll get back to the drawing board on that one to conditionally implement your fix.