Skip to content

Commit 26122aa

Browse files
committed
fix: Correctly assign response headers from httpGraphQLResponse (#34)
Response headers from Apollo Server weren't being assigned to the final response object.
1 parent d26c456 commit 26122aa

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed

src/__tests__/integration.test.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { ApolloServer, type ApolloServerOptions, type BaseContext } from '@apollo/server';
2+
import {
3+
defineIntegrationTestSuite,
4+
type CreateServerForIntegrationTestsOptions,
5+
} from '@apollo/server-integration-testsuite';
6+
import type { Server } from 'http';
7+
import type { AddressInfo } from 'net';
8+
import { format } from 'url';
9+
import { startServerAndCreateGoogleCloudFunctionsHandler } from '..';
10+
11+
const { getTestServer } = require('@google-cloud/functions-framework/testing');
12+
13+
describe('cloud functions handler', () => {
14+
defineIntegrationTestSuite(
15+
async function (
16+
serverOptions: ApolloServerOptions<BaseContext>,
17+
testOptions?: CreateServerForIntegrationTestsOptions,
18+
) {
19+
const apolloServer = new ApolloServer({
20+
...serverOptions,
21+
});
22+
23+
startServerAndCreateGoogleCloudFunctionsHandler(apolloServer, {
24+
functionTarget: 'apolloServer',
25+
context: testOptions?.context,
26+
});
27+
28+
const testServer = getTestServer('apolloServer');
29+
await new Promise<void>((resolve) => {
30+
testServer.listen({ port: 0 }, resolve);
31+
});
32+
33+
return {
34+
server: apolloServer,
35+
url: urlForHttpServer(testServer),
36+
async extraCleanup() {
37+
await new Promise<void>((resolve) => {
38+
testServer.close(() => resolve());
39+
});
40+
},
41+
};
42+
},
43+
{
44+
serverIsStartedInBackground: true,
45+
noIncrementalDelivery: true,
46+
},
47+
);
48+
});
49+
50+
// Stolen from apollo server integration tests
51+
export function urlForHttpServer(httpServer: Server): string {
52+
const { address, port } = httpServer.address() as AddressInfo;
53+
54+
// Convert IPs which mean "any address" (IPv4 or IPv6) into localhost
55+
// corresponding loopback ip. Note that the url field we're setting is
56+
// primarily for consumption by our test suite. If this heuristic is wrong for
57+
// your use case, explicitly specify a frontend host (in the `host` option
58+
// when listening).
59+
const hostname = address === '' || address === '::' ? 'localhost' : address;
60+
61+
return format({
62+
protocol: 'http',
63+
hostname,
64+
port,
65+
pathname: '/',
66+
});
67+
}

src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ interface Options<Context extends BaseContext> {
1010
functionTarget: string;
1111
}
1212

13-
type GoogleCloudApiHandler = (req: Request, res: Response) => Promise<unknown> | unknown;
13+
export type GoogleCloudApiHandler = (req: Request, res: Response) => Promise<unknown> | unknown;
1414

1515
const defaultContext: ContextFunction<[], any> = async () => ({});
1616

@@ -60,6 +60,10 @@ export function startServerAndCreateGoogleCloudFunctionsHandler<Context extends
6060
},
6161
});
6262

63+
for (const [key, value] of httpGraphQLResponse.headers) {
64+
res.setHeader(key, value);
65+
}
66+
6367
res.statusCode = httpGraphQLResponse.status || 200;
6468

6569
if (httpGraphQLResponse.body.kind === 'complete') {

0 commit comments

Comments
 (0)