Skip to content

Commit

Permalink
apollo-server-lambda: Test against a mock ALB; upgrade to fix it (#5291)
Browse files Browse the repository at this point in the history
We want ASL to work behind ALB, not just API Gateway, so let's test
against both.

Upgrading `@vendia/serverless-express` gives us better support for ALB
query strings.

Based on #5290 by @kamaz.

Co-authored-by: Kamaz <kamaz@xsimple.org>
  • Loading branch information
glasser and kamaz authored Jun 9, 2021
1 parent e5198c4 commit fd93b76
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 38 deletions.
39 changes: 10 additions & 29 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
"@types/test-listen": "1.1.0",
"@types/type-is": "1.6.3",
"@types/uuid": "8.3.0",
"@vendia/serverless-express": "4.3.7",
"@vendia/serverless-express": "4.3.9",
"apollo-link": "1.2.14",
"apollo-link-http": "1.5.17",
"apollo-link-persisted-queries": "0.2.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/apollo-server-lambda/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
},
"dependencies": {
"@types/aws-lambda": "^8.10.76",
"@vendia/serverless-express": "^4.3.7",
"@vendia/serverless-express": "^4.3.9",
"apollo-server-core": "file:../apollo-server-core",
"apollo-server-express": "file:../apollo-server-express",
"express": "^4.17.1"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import http from 'http';
import request from 'supertest';
import express from 'express';
import { createMockServer } from './mockServer';
import { createMockServer } from './mockAPIGatewayServer';
import { Config, gql } from 'apollo-server-core';
import { ApolloServer, CreateHandlerOptions } from '../ApolloServer';
import {
Expand Down
27 changes: 21 additions & 6 deletions packages/apollo-server-lambda/src/__tests__/lambdaApollo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,33 @@ import testSuite, {
CreateAppOptions,
} from 'apollo-server-integration-testsuite';
import { Config } from 'apollo-server-core';
import {createMockServer} from './mockServer';
import { createMockServer as createAPIGatewayMockServer } from './mockAPIGatewayServer';
import { createMockServer as createALBMockServer } from './mockALBServer';

const createLambda = async (options: CreateAppOptions = {}) => {
const createAPIGatewayLambda = async (options: CreateAppOptions = {}) => {
const server = new ApolloServer(
(options.graphqlOptions as Config) || { schema: Schema },
);

const handler = server.createHandler();

return createMockServer(handler);
}
return createAPIGatewayMockServer(handler);
};

describe('integration:Lambda', () => {
testSuite({createApp: createLambda, serverlessFramework: true});
const createALBLambda = async (options: CreateAppOptions = {}) => {
const server = new ApolloServer(
(options.graphqlOptions as Config) || { schema: Schema },
);

const handler = server.createHandler();

return createALBMockServer(handler);
};

describe('integration:APIGateway:Lambda', () => {
testSuite({ createApp: createAPIGatewayLambda, serverlessFramework: true });
});

describe('integration:ALB:Lambda', () => {
testSuite({ createApp: createALBLambda, serverlessFramework: true });
});
53 changes: 53 additions & 0 deletions packages/apollo-server-lambda/src/__tests__/mockALBServer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import url from 'url';
import { IncomingMessage, ServerResponse } from 'http';
import {
Context as LambdaContext,
ALBHandler,
ALBEvent,
ALBResult,
} from 'aws-lambda';

export function createMockServer(handler: ALBHandler) {
return (req: IncomingMessage, res: ServerResponse) => {
let body = '';
req.on('data', (chunk) => (body += chunk));
// this is an unawaited async function, but anything that causes it to
// reject should cause a test to fail
req.on('end', async () => {
const urlObject = url.parse(req.url || '', true);
const queryStringParameters = Object.entries(urlObject.query)
.map(([key, value]) => {
return [key, encodeURIComponent(value as string)];
})
.reduce((acc, [key, value]) => ({ [key]: value, ...acc }), {});
const event = {
httpMethod: req.method,
body: body,
path: urlObject.pathname,
queryStringParameters,
requestContext: {
elb: {},
},
headers: req.headers,
};
const result = (await handler(
event as unknown as ALBEvent,
{} as LambdaContext, // the fields aren't actually used now
() => {
throw Error("we don't use callback");
},
)) as ALBResult;
res.statusCode = result.statusCode!;
Object.entries(result.multiValueHeaders ?? {}).forEach(
([key, values]) => {
res.setHeader(
key,
values.map((v) => v.toString()),
);
},
);
res.write(result.body);
res.end();
});
};
}

0 comments on commit fd93b76

Please sign in to comment.