Skip to content

Commit e8202a4

Browse files
authored
Fix request usage from context (#99)
* Fix request usage from context * Remove samples folder from npm package * Fix import * Fix tests * Fix ci install
1 parent 09e78d7 commit e8202a4

File tree

10 files changed

+1175
-61
lines changed

10 files changed

+1175
-61
lines changed

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
*
22
!src/**/*
33
src/**/__tests__/**
4+
src/samples/**
45
!dist/**/*
56
dist/**/__tests__/**
67
!package.json

package-lock.json

Lines changed: 19 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@
3333
"start:host": "cd src/sample && func start --cors *"
3434
},
3535
"dependencies": {
36-
"@azure/functions": "^3.5.1",
37-
"@azure/functions-v4": "npm:@azure/functions@^4.7.2"
36+
"@azure/functions": "^3",
37+
"@azure/functions-v4": "npm:@azure/functions@^4"
3838
},
3939
"devDependencies": {
40-
"@apollo/server": "5.0.0",
41-
"@apollo/server-integration-testsuite": "5.0.0",
40+
"@apollo/server": "5.2.0",
41+
"@apollo/server-integration-testsuite": "5.2.0",
4242
"@changesets/changelog-github": "0.5.1",
4343
"@changesets/cli": "2.29.6",
4444
"@types/jest": "29.5.14",
@@ -59,6 +59,6 @@
5959
"npm": "11.5.2"
6060
},
6161
"peerDependencies": {
62-
"@apollo/server": "^4.0.0 || ^5.0.0"
62+
"@apollo/server": "^4 || ^5"
6363
}
6464
}

src/__tests__/mockServer-v4.ts

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,49 @@ export function urlForHttpServer(httpServer: Server): string {
2121
return `http://${hostname}:${port}`;
2222
}
2323

24+
function createHttpRequest(
25+
method: HttpMethod,
26+
url: string,
27+
headers: Headers,
28+
bodyContent: string,
29+
): HttpRequest {
30+
const createRequest = (): HttpRequest => ({
31+
method,
32+
url,
33+
headers,
34+
body: new ReadableStream({
35+
start(controller) {
36+
controller.enqueue(new TextEncoder().encode(bodyContent));
37+
controller.close();
38+
},
39+
}),
40+
query: new URLSearchParams(new URL(url).search),
41+
params: {},
42+
user: null,
43+
arrayBuffer: async () => {
44+
return Buffer.from(bodyContent).buffer;
45+
},
46+
text: async () => {
47+
return bodyContent;
48+
},
49+
json: async () => {
50+
return JSON.parse(bodyContent);
51+
},
52+
blob: async () => {
53+
throw new Error('Not implemented');
54+
},
55+
bodyUsed: false,
56+
formData: async () => {
57+
throw new Error('Not implemented');
58+
},
59+
clone: () => {
60+
return createRequest();
61+
},
62+
});
63+
64+
return createRequest();
65+
}
66+
2467
export const createMockServer = (handler: HttpHandler) => {
2568
return (req: IncomingMessage, res: ServerResponse) => {
2669
let body = '';
@@ -32,39 +75,12 @@ export const createMockServer = (handler: HttpHandler) => {
3275
headers.set(key, value as string);
3376
}
3477

35-
const azReq: HttpRequest = {
36-
method: (req.method as HttpMethod) || null,
37-
url: new URL(req.url || '', 'http://localhost').toString(),
78+
const azReq = createHttpRequest(
79+
(req.method as HttpMethod) || null,
80+
new URL(req.url || '', 'http://localhost').toString(),
3881
headers,
39-
body: new ReadableStream({
40-
start(controller) {
41-
controller.enqueue(new TextEncoder().encode(body));
42-
controller.close();
43-
},
44-
}),
45-
query: new URLSearchParams(req.url),
46-
params: {},
47-
user: null,
48-
arrayBuffer: async () => {
49-
return Buffer.from(body).buffer;
50-
},
51-
text: async () => {
52-
return body;
53-
},
54-
json: async () => {
55-
return JSON.parse(body);
56-
},
57-
blob: async () => {
58-
throw new Error('Not implemented');
59-
},
60-
bodyUsed: false,
61-
formData: async () => {
62-
throw new Error('Not implemented');
63-
},
64-
clone: () => {
65-
throw new Error('Not implemented');
66-
},
67-
};
82+
body,
83+
);
6884

6985
const context = new InvocationContext({
7086
invocationId: 'mock',

src/func-v4.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ import type { WithRequired } from '@apollo/utils.withrequired';
1616
export interface AzureFunctionsContextFunctionArgument {
1717
context: InvocationContext;
1818
req: HttpRequest;
19+
/**
20+
* The parsed request body. This is already parsed from the request stream
21+
* and should be used instead of calling `req.json()` for better performance.
22+
* For POST requests with `application/json` content-type, this contains the parsed JSON object.
23+
* For other requests, this will be `null`.
24+
*/
25+
body: unknown;
1926
}
2027

2128
export interface AzureFunctionsMiddlewareOptions<TContext extends BaseContext> {
@@ -57,18 +64,16 @@ export function startServerAndCreateHandler<TContext extends BaseContext>(
5764
return async (req: HttpRequest, context: InvocationContext) => {
5865
const contextFunction = options?.context ?? defaultContext;
5966
try {
67+
const cloneReq = req.clone();
6068
const normalizedRequest = await normalizeRequest(req);
6169

6270
const { body, headers, status } = await server.executeHTTPGraphQLRequest({
6371
httpGraphQLRequest: normalizedRequest,
6472
context: () =>
6573
contextFunction({
6674
context,
67-
req: {
68-
...req,
69-
// This promise was already used, so we need to create a new one.
70-
json: () => Promise.resolve(normalizedRequest.body),
71-
},
75+
req: cloneReq,
76+
body: normalizedRequest.body,
7277
}),
7378
});
7479

src/samples/v4/.funcignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
*.js.map
2+
*.ts
3+
.git*
4+
.vscode
5+
local.settings.json
6+
test
7+
getting_started.md
8+
node_modules/@types/
9+
node_modules/azure-functions-core-tools/
10+
node_modules/typescript/

src/samples/v4/local.settings.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"IsEncrypted": false,
3+
"Values": {
4+
"FUNCTIONS_WORKER_RUNTIME": "node",
5+
"AzureWebJobsStorage": ""
6+
}
7+
}

0 commit comments

Comments
 (0)