graphql-http 1.21.0 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/lib/handler.d.mts +19 -2
- package/lib/handler.d.ts +19 -2
- package/lib/handler.js +115 -108
- package/lib/handler.mjs +113 -107
- package/lib/use/@netlify/functions.d.mts +1 -1
- package/lib/use/express.d.mts +41 -0
- package/lib/use/express.d.ts +41 -0
- package/lib/use/express.js +72 -19
- package/lib/use/express.mjs +71 -19
- package/lib/use/fastify.d.mts +42 -1
- package/lib/use/fastify.d.ts +42 -1
- package/lib/use/fastify.js +68 -11
- package/lib/use/fastify.mjs +67 -11
- package/lib/use/fetch.d.mts +50 -0
- package/lib/use/fetch.d.ts +50 -0
- package/lib/use/fetch.js +74 -9
- package/lib/use/fetch.mjs +73 -9
- package/lib/use/http.d.mts +44 -0
- package/lib/use/http.d.ts +44 -0
- package/lib/use/http.js +75 -13
- package/lib/use/http.mjs +74 -13
- package/lib/use/http2.d.mts +56 -0
- package/lib/use/http2.d.ts +56 -0
- package/lib/use/http2.js +93 -13
- package/lib/use/http2.mjs +92 -13
- package/lib/use/koa.d.mts +47 -1
- package/lib/use/koa.d.ts +47 -1
- package/lib/use/koa.js +84 -1
- package/lib/use/koa.mjs +83 -1
- package/lib/use/uWebSockets.d.mts +55 -0
- package/lib/use/uWebSockets.d.ts +55 -0
- package/lib/use/uWebSockets.js +109 -31
- package/lib/use/uWebSockets.mjs +108 -31
- package/package.json +21 -21
package/lib/use/fetch.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HandlerOptions as RawHandlerOptions, OperationContext } from '../handler';
|
|
2
|
+
import { RequestParams } from '../common';
|
|
2
3
|
/**
|
|
3
4
|
* The necessary API from the fetch environment for the handler.
|
|
4
5
|
*
|
|
@@ -9,6 +10,55 @@ export interface FetchAPI {
|
|
|
9
10
|
ReadableStream: typeof ReadableStream;
|
|
10
11
|
TextEncoder: typeof TextEncoder;
|
|
11
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
|
|
15
|
+
*
|
|
16
|
+
* It is important to pass in the `abortedRef` so that the parser does not perform any
|
|
17
|
+
* operations on a disposed request (see example).
|
|
18
|
+
*
|
|
19
|
+
* If the HTTP request _is not_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), the function will return a `Response`.
|
|
20
|
+
*
|
|
21
|
+
* If the HTTP request _is_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), but is invalid or malformed,
|
|
22
|
+
* the function will throw an error and it is up to the user to handle and respond as they see fit.
|
|
23
|
+
*
|
|
24
|
+
* ```js
|
|
25
|
+
* import http from 'http';
|
|
26
|
+
* import { createServerAdapter } from '@whatwg-node/server'; // yarn add @whatwg-node/server
|
|
27
|
+
* import { parseRequestParams } from 'graphql-http/lib/use/fetch';
|
|
28
|
+
*
|
|
29
|
+
* // Use this adapter in _any_ environment.
|
|
30
|
+
* const adapter = createServerAdapter({
|
|
31
|
+
* handleRequest: async (req) => {
|
|
32
|
+
* try {
|
|
33
|
+
* const paramsOrResponse = await parseRequestParams(req);
|
|
34
|
+
* if (paramsOrResponse instanceof Response) {
|
|
35
|
+
* // not a well-formatted GraphQL over HTTP request,
|
|
36
|
+
* // parser created a response object to use
|
|
37
|
+
* return paramsOrResponse;
|
|
38
|
+
* }
|
|
39
|
+
*
|
|
40
|
+
* // well-formatted GraphQL over HTTP request,
|
|
41
|
+
* // with valid parameters
|
|
42
|
+
* return new Response(JSON.stringify(paramsOrResponse, null, ' '), {
|
|
43
|
+
* status: 200,
|
|
44
|
+
* });
|
|
45
|
+
* } catch (err) {
|
|
46
|
+
* // well-formatted GraphQL over HTTP request,
|
|
47
|
+
* // but with invalid parameters
|
|
48
|
+
* return new Response(err.message, { status: 400 });
|
|
49
|
+
* }
|
|
50
|
+
* },
|
|
51
|
+
* });
|
|
52
|
+
*
|
|
53
|
+
* const server = http.createServer(adapter);
|
|
54
|
+
*
|
|
55
|
+
* server.listen(4000);
|
|
56
|
+
* console.log('Listening to port 4000');
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @category Server/fetch
|
|
60
|
+
*/
|
|
61
|
+
export declare function parseRequestParams(req: Request, api?: Partial<FetchAPI>): Promise<RequestParams | Response>;
|
|
12
62
|
/**
|
|
13
63
|
* Handler options when using the fetch adapter.
|
|
14
64
|
*
|
package/lib/use/fetch.js
CHANGED
|
@@ -1,7 +1,65 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createHandler = void 0;
|
|
3
|
+
exports.createHandler = exports.parseRequestParams = void 0;
|
|
4
4
|
const handler_1 = require("../handler");
|
|
5
|
+
/**
|
|
6
|
+
* The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
|
|
7
|
+
*
|
|
8
|
+
* It is important to pass in the `abortedRef` so that the parser does not perform any
|
|
9
|
+
* operations on a disposed request (see example).
|
|
10
|
+
*
|
|
11
|
+
* If the HTTP request _is not_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), the function will return a `Response`.
|
|
12
|
+
*
|
|
13
|
+
* If the HTTP request _is_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), but is invalid or malformed,
|
|
14
|
+
* the function will throw an error and it is up to the user to handle and respond as they see fit.
|
|
15
|
+
*
|
|
16
|
+
* ```js
|
|
17
|
+
* import http from 'http';
|
|
18
|
+
* import { createServerAdapter } from '@whatwg-node/server'; // yarn add @whatwg-node/server
|
|
19
|
+
* import { parseRequestParams } from 'graphql-http/lib/use/fetch';
|
|
20
|
+
*
|
|
21
|
+
* // Use this adapter in _any_ environment.
|
|
22
|
+
* const adapter = createServerAdapter({
|
|
23
|
+
* handleRequest: async (req) => {
|
|
24
|
+
* try {
|
|
25
|
+
* const paramsOrResponse = await parseRequestParams(req);
|
|
26
|
+
* if (paramsOrResponse instanceof Response) {
|
|
27
|
+
* // not a well-formatted GraphQL over HTTP request,
|
|
28
|
+
* // parser created a response object to use
|
|
29
|
+
* return paramsOrResponse;
|
|
30
|
+
* }
|
|
31
|
+
*
|
|
32
|
+
* // well-formatted GraphQL over HTTP request,
|
|
33
|
+
* // with valid parameters
|
|
34
|
+
* return new Response(JSON.stringify(paramsOrResponse, null, ' '), {
|
|
35
|
+
* status: 200,
|
|
36
|
+
* });
|
|
37
|
+
* } catch (err) {
|
|
38
|
+
* // well-formatted GraphQL over HTTP request,
|
|
39
|
+
* // but with invalid parameters
|
|
40
|
+
* return new Response(err.message, { status: 400 });
|
|
41
|
+
* }
|
|
42
|
+
* },
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* const server = http.createServer(adapter);
|
|
46
|
+
*
|
|
47
|
+
* server.listen(4000);
|
|
48
|
+
* console.log('Listening to port 4000');
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @category Server/fetch
|
|
52
|
+
*/
|
|
53
|
+
async function parseRequestParams(req, api = {}) {
|
|
54
|
+
const rawReq = toRequest(req, api);
|
|
55
|
+
const paramsOrRes = await (0, handler_1.parseRequestParams)(rawReq);
|
|
56
|
+
if (!('query' in paramsOrRes)) {
|
|
57
|
+
const [body, init] = paramsOrRes;
|
|
58
|
+
return new (api.Response || Response)(body, init);
|
|
59
|
+
}
|
|
60
|
+
return paramsOrRes;
|
|
61
|
+
}
|
|
62
|
+
exports.parseRequestParams = parseRequestParams;
|
|
5
63
|
/**
|
|
6
64
|
* Create a GraphQL over HTTP spec compliant request handler for
|
|
7
65
|
* a fetch environment like Deno, Bun, CloudFlare Workers, Lambdas, etc.
|
|
@@ -39,14 +97,7 @@ function createHandler(options, reqCtx = {}) {
|
|
|
39
97
|
const handler = (0, handler_1.createHandler)(options);
|
|
40
98
|
return async function handleRequest(req) {
|
|
41
99
|
try {
|
|
42
|
-
const [body, init] = await handler(
|
|
43
|
-
method: req.method,
|
|
44
|
-
url: req.url,
|
|
45
|
-
headers: req.headers,
|
|
46
|
-
body: () => req.text(),
|
|
47
|
-
raw: req,
|
|
48
|
-
context: api,
|
|
49
|
-
});
|
|
100
|
+
const [body, init] = await handler(toRequest(req, api));
|
|
50
101
|
return new api.Response(body, init);
|
|
51
102
|
}
|
|
52
103
|
catch (err) {
|
|
@@ -59,3 +110,17 @@ function createHandler(options, reqCtx = {}) {
|
|
|
59
110
|
};
|
|
60
111
|
}
|
|
61
112
|
exports.createHandler = createHandler;
|
|
113
|
+
function toRequest(req, api = {}) {
|
|
114
|
+
return {
|
|
115
|
+
method: req.method,
|
|
116
|
+
url: req.url,
|
|
117
|
+
headers: req.headers,
|
|
118
|
+
body: () => req.text(),
|
|
119
|
+
raw: req,
|
|
120
|
+
context: {
|
|
121
|
+
Response: api.Response || Response,
|
|
122
|
+
TextEncoder: api.TextEncoder || TextEncoder,
|
|
123
|
+
ReadableStream: api.ReadableStream || ReadableStream,
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
package/lib/use/fetch.mjs
CHANGED
|
@@ -1,4 +1,61 @@
|
|
|
1
|
-
import { createHandler as createRawHandler, } from '../handler.mjs';
|
|
1
|
+
import { createHandler as createRawHandler, parseRequestParams as rawParseRequestParams, } from '../handler.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
|
|
4
|
+
*
|
|
5
|
+
* It is important to pass in the `abortedRef` so that the parser does not perform any
|
|
6
|
+
* operations on a disposed request (see example).
|
|
7
|
+
*
|
|
8
|
+
* If the HTTP request _is not_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), the function will return a `Response`.
|
|
9
|
+
*
|
|
10
|
+
* If the HTTP request _is_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), but is invalid or malformed,
|
|
11
|
+
* the function will throw an error and it is up to the user to handle and respond as they see fit.
|
|
12
|
+
*
|
|
13
|
+
* ```js
|
|
14
|
+
* import http from 'http';
|
|
15
|
+
* import { createServerAdapter } from '@whatwg-node/server'; // yarn add @whatwg-node/server
|
|
16
|
+
* import { parseRequestParams } from 'graphql-http/lib/use/fetch';
|
|
17
|
+
*
|
|
18
|
+
* // Use this adapter in _any_ environment.
|
|
19
|
+
* const adapter = createServerAdapter({
|
|
20
|
+
* handleRequest: async (req) => {
|
|
21
|
+
* try {
|
|
22
|
+
* const paramsOrResponse = await parseRequestParams(req);
|
|
23
|
+
* if (paramsOrResponse instanceof Response) {
|
|
24
|
+
* // not a well-formatted GraphQL over HTTP request,
|
|
25
|
+
* // parser created a response object to use
|
|
26
|
+
* return paramsOrResponse;
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* // well-formatted GraphQL over HTTP request,
|
|
30
|
+
* // with valid parameters
|
|
31
|
+
* return new Response(JSON.stringify(paramsOrResponse, null, ' '), {
|
|
32
|
+
* status: 200,
|
|
33
|
+
* });
|
|
34
|
+
* } catch (err) {
|
|
35
|
+
* // well-formatted GraphQL over HTTP request,
|
|
36
|
+
* // but with invalid parameters
|
|
37
|
+
* return new Response(err.message, { status: 400 });
|
|
38
|
+
* }
|
|
39
|
+
* },
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* const server = http.createServer(adapter);
|
|
43
|
+
*
|
|
44
|
+
* server.listen(4000);
|
|
45
|
+
* console.log('Listening to port 4000');
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @category Server/fetch
|
|
49
|
+
*/
|
|
50
|
+
export async function parseRequestParams(req, api = {}) {
|
|
51
|
+
const rawReq = toRequest(req, api);
|
|
52
|
+
const paramsOrRes = await rawParseRequestParams(rawReq);
|
|
53
|
+
if (!('query' in paramsOrRes)) {
|
|
54
|
+
const [body, init] = paramsOrRes;
|
|
55
|
+
return new (api.Response || Response)(body, init);
|
|
56
|
+
}
|
|
57
|
+
return paramsOrRes;
|
|
58
|
+
}
|
|
2
59
|
/**
|
|
3
60
|
* Create a GraphQL over HTTP spec compliant request handler for
|
|
4
61
|
* a fetch environment like Deno, Bun, CloudFlare Workers, Lambdas, etc.
|
|
@@ -36,14 +93,7 @@ export function createHandler(options, reqCtx = {}) {
|
|
|
36
93
|
const handler = createRawHandler(options);
|
|
37
94
|
return async function handleRequest(req) {
|
|
38
95
|
try {
|
|
39
|
-
const [body, init] = await handler(
|
|
40
|
-
method: req.method,
|
|
41
|
-
url: req.url,
|
|
42
|
-
headers: req.headers,
|
|
43
|
-
body: () => req.text(),
|
|
44
|
-
raw: req,
|
|
45
|
-
context: api,
|
|
46
|
-
});
|
|
96
|
+
const [body, init] = await handler(toRequest(req, api));
|
|
47
97
|
return new api.Response(body, init);
|
|
48
98
|
}
|
|
49
99
|
catch (err) {
|
|
@@ -55,3 +105,17 @@ export function createHandler(options, reqCtx = {}) {
|
|
|
55
105
|
}
|
|
56
106
|
};
|
|
57
107
|
}
|
|
108
|
+
function toRequest(req, api = {}) {
|
|
109
|
+
return {
|
|
110
|
+
method: req.method,
|
|
111
|
+
url: req.url,
|
|
112
|
+
headers: req.headers,
|
|
113
|
+
body: () => req.text(),
|
|
114
|
+
raw: req,
|
|
115
|
+
context: {
|
|
116
|
+
Response: api.Response || Response,
|
|
117
|
+
TextEncoder: api.TextEncoder || TextEncoder,
|
|
118
|
+
ReadableStream: api.ReadableStream || ReadableStream,
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
package/lib/use/http.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import type { IncomingMessage, ServerResponse } from 'http';
|
|
3
3
|
import { HandlerOptions as RawHandlerOptions, OperationContext } from '../handler.mjs';
|
|
4
|
+
import { RequestParams } from '../common.mjs';
|
|
4
5
|
/**
|
|
5
6
|
* The context in the request for the handler.
|
|
6
7
|
*
|
|
@@ -9,6 +10,49 @@ import { HandlerOptions as RawHandlerOptions, OperationContext } from '../handle
|
|
|
9
10
|
export interface RequestContext {
|
|
10
11
|
res: ServerResponse;
|
|
11
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
|
|
15
|
+
*
|
|
16
|
+
* If the HTTP request _is not_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), the function will respond
|
|
17
|
+
* on the `ServerResponse` argument and return `null`.
|
|
18
|
+
*
|
|
19
|
+
* If the HTTP request _is_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), but is invalid or malformed,
|
|
20
|
+
* the function will throw an error and it is up to the user to handle and respond as they see fit.
|
|
21
|
+
*
|
|
22
|
+
* ```js
|
|
23
|
+
* import http from 'http';
|
|
24
|
+
* import { parseRequestParams } from 'graphql-http/lib/use/http';
|
|
25
|
+
*
|
|
26
|
+
* const server = http.createServer(async (req, res) => {
|
|
27
|
+
* if (req.url.startsWith('/graphql')) {
|
|
28
|
+
* try {
|
|
29
|
+
* const maybeParams = await parseRequestParams(req, res);
|
|
30
|
+
* if (!maybeParams) {
|
|
31
|
+
* // not a well-formatted GraphQL over HTTP request,
|
|
32
|
+
* // parser responded and there's nothing else to do
|
|
33
|
+
* return;
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* // well-formatted GraphQL over HTTP request,
|
|
37
|
+
* // with valid parameters
|
|
38
|
+
* res.writeHead(200).end(JSON.stringify(maybeParams, null, ' '));
|
|
39
|
+
* } catch (err) {
|
|
40
|
+
* // well-formatted GraphQL over HTTP request,
|
|
41
|
+
* // but with invalid parameters
|
|
42
|
+
* res.writeHead(400).end(err.message);
|
|
43
|
+
* }
|
|
44
|
+
* } else {
|
|
45
|
+
* res.writeHead(404).end();
|
|
46
|
+
* }
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* server.listen(4000);
|
|
50
|
+
* console.log('Listening to port 4000');
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @category Server/http
|
|
54
|
+
*/
|
|
55
|
+
export declare function parseRequestParams(req: IncomingMessage, res: ServerResponse): Promise<RequestParams | null>;
|
|
12
56
|
/**
|
|
13
57
|
* Handler options when using the http adapter.
|
|
14
58
|
*
|
package/lib/use/http.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import type { IncomingMessage, ServerResponse } from 'http';
|
|
3
3
|
import { HandlerOptions as RawHandlerOptions, OperationContext } from '../handler';
|
|
4
|
+
import { RequestParams } from '../common';
|
|
4
5
|
/**
|
|
5
6
|
* The context in the request for the handler.
|
|
6
7
|
*
|
|
@@ -9,6 +10,49 @@ import { HandlerOptions as RawHandlerOptions, OperationContext } from '../handle
|
|
|
9
10
|
export interface RequestContext {
|
|
10
11
|
res: ServerResponse;
|
|
11
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
|
|
15
|
+
*
|
|
16
|
+
* If the HTTP request _is not_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), the function will respond
|
|
17
|
+
* on the `ServerResponse` argument and return `null`.
|
|
18
|
+
*
|
|
19
|
+
* If the HTTP request _is_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), but is invalid or malformed,
|
|
20
|
+
* the function will throw an error and it is up to the user to handle and respond as they see fit.
|
|
21
|
+
*
|
|
22
|
+
* ```js
|
|
23
|
+
* import http from 'http';
|
|
24
|
+
* import { parseRequestParams } from 'graphql-http/lib/use/http';
|
|
25
|
+
*
|
|
26
|
+
* const server = http.createServer(async (req, res) => {
|
|
27
|
+
* if (req.url.startsWith('/graphql')) {
|
|
28
|
+
* try {
|
|
29
|
+
* const maybeParams = await parseRequestParams(req, res);
|
|
30
|
+
* if (!maybeParams) {
|
|
31
|
+
* // not a well-formatted GraphQL over HTTP request,
|
|
32
|
+
* // parser responded and there's nothing else to do
|
|
33
|
+
* return;
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* // well-formatted GraphQL over HTTP request,
|
|
37
|
+
* // with valid parameters
|
|
38
|
+
* res.writeHead(200).end(JSON.stringify(maybeParams, null, ' '));
|
|
39
|
+
* } catch (err) {
|
|
40
|
+
* // well-formatted GraphQL over HTTP request,
|
|
41
|
+
* // but with invalid parameters
|
|
42
|
+
* res.writeHead(400).end(err.message);
|
|
43
|
+
* }
|
|
44
|
+
* } else {
|
|
45
|
+
* res.writeHead(404).end();
|
|
46
|
+
* }
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* server.listen(4000);
|
|
50
|
+
* console.log('Listening to port 4000');
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @category Server/http
|
|
54
|
+
*/
|
|
55
|
+
export declare function parseRequestParams(req: IncomingMessage, res: ServerResponse): Promise<RequestParams | null>;
|
|
12
56
|
/**
|
|
13
57
|
* Handler options when using the http adapter.
|
|
14
58
|
*
|
package/lib/use/http.js
CHANGED
|
@@ -1,7 +1,60 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createHandler = void 0;
|
|
3
|
+
exports.createHandler = exports.parseRequestParams = void 0;
|
|
4
4
|
const handler_1 = require("../handler");
|
|
5
|
+
/**
|
|
6
|
+
* The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
|
|
7
|
+
*
|
|
8
|
+
* If the HTTP request _is not_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), the function will respond
|
|
9
|
+
* on the `ServerResponse` argument and return `null`.
|
|
10
|
+
*
|
|
11
|
+
* If the HTTP request _is_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), but is invalid or malformed,
|
|
12
|
+
* the function will throw an error and it is up to the user to handle and respond as they see fit.
|
|
13
|
+
*
|
|
14
|
+
* ```js
|
|
15
|
+
* import http from 'http';
|
|
16
|
+
* import { parseRequestParams } from 'graphql-http/lib/use/http';
|
|
17
|
+
*
|
|
18
|
+
* const server = http.createServer(async (req, res) => {
|
|
19
|
+
* if (req.url.startsWith('/graphql')) {
|
|
20
|
+
* try {
|
|
21
|
+
* const maybeParams = await parseRequestParams(req, res);
|
|
22
|
+
* if (!maybeParams) {
|
|
23
|
+
* // not a well-formatted GraphQL over HTTP request,
|
|
24
|
+
* // parser responded and there's nothing else to do
|
|
25
|
+
* return;
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* // well-formatted GraphQL over HTTP request,
|
|
29
|
+
* // with valid parameters
|
|
30
|
+
* res.writeHead(200).end(JSON.stringify(maybeParams, null, ' '));
|
|
31
|
+
* } catch (err) {
|
|
32
|
+
* // well-formatted GraphQL over HTTP request,
|
|
33
|
+
* // but with invalid parameters
|
|
34
|
+
* res.writeHead(400).end(err.message);
|
|
35
|
+
* }
|
|
36
|
+
* } else {
|
|
37
|
+
* res.writeHead(404).end();
|
|
38
|
+
* }
|
|
39
|
+
* });
|
|
40
|
+
*
|
|
41
|
+
* server.listen(4000);
|
|
42
|
+
* console.log('Listening to port 4000');
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @category Server/http
|
|
46
|
+
*/
|
|
47
|
+
async function parseRequestParams(req, res) {
|
|
48
|
+
const rawReq = toRequest(req, res);
|
|
49
|
+
const paramsOrRes = await (0, handler_1.parseRequestParams)(rawReq);
|
|
50
|
+
if (!('query' in paramsOrRes)) {
|
|
51
|
+
const [body, init] = paramsOrRes;
|
|
52
|
+
res.writeHead(init.status, init.statusText, init.headers).end(body);
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
return paramsOrRes;
|
|
56
|
+
}
|
|
57
|
+
exports.parseRequestParams = parseRequestParams;
|
|
5
58
|
/**
|
|
6
59
|
* Create a GraphQL over HTTP spec compliant request handler for
|
|
7
60
|
* the Node environment http module.
|
|
@@ -29,18 +82,7 @@ function createHandler(options) {
|
|
|
29
82
|
if (!req.method) {
|
|
30
83
|
throw new Error('Missing request method');
|
|
31
84
|
}
|
|
32
|
-
const [body, init] = await handle(
|
|
33
|
-
url: req.url,
|
|
34
|
-
method: req.method,
|
|
35
|
-
headers: req.headers,
|
|
36
|
-
body: () => new Promise((resolve) => {
|
|
37
|
-
let body = '';
|
|
38
|
-
req.on('data', (chunk) => (body += chunk));
|
|
39
|
-
req.on('end', () => resolve(body));
|
|
40
|
-
}),
|
|
41
|
-
raw: req,
|
|
42
|
-
context: { res },
|
|
43
|
-
});
|
|
85
|
+
const [body, init] = await handle(toRequest(req, res));
|
|
44
86
|
res.writeHead(init.status, init.statusText, init.headers).end(body);
|
|
45
87
|
}
|
|
46
88
|
catch (err) {
|
|
@@ -53,3 +95,23 @@ function createHandler(options) {
|
|
|
53
95
|
};
|
|
54
96
|
}
|
|
55
97
|
exports.createHandler = createHandler;
|
|
98
|
+
function toRequest(req, res) {
|
|
99
|
+
if (!req.url) {
|
|
100
|
+
throw new Error('Missing request URL');
|
|
101
|
+
}
|
|
102
|
+
if (!req.method) {
|
|
103
|
+
throw new Error('Missing request method');
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
url: req.url,
|
|
107
|
+
method: req.method,
|
|
108
|
+
headers: req.headers,
|
|
109
|
+
body: () => new Promise((resolve) => {
|
|
110
|
+
let body = '';
|
|
111
|
+
req.on('data', (chunk) => (body += chunk));
|
|
112
|
+
req.on('end', () => resolve(body));
|
|
113
|
+
}),
|
|
114
|
+
raw: req,
|
|
115
|
+
context: { res },
|
|
116
|
+
};
|
|
117
|
+
}
|
package/lib/use/http.mjs
CHANGED
|
@@ -1,4 +1,56 @@
|
|
|
1
|
-
import { createHandler as createRawHandler, } from '../handler.mjs';
|
|
1
|
+
import { createHandler as createRawHandler, parseRequestParams as rawParseRequestParams, } from '../handler.mjs';
|
|
2
|
+
/**
|
|
3
|
+
* The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
|
|
4
|
+
*
|
|
5
|
+
* If the HTTP request _is not_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), the function will respond
|
|
6
|
+
* on the `ServerResponse` argument and return `null`.
|
|
7
|
+
*
|
|
8
|
+
* If the HTTP request _is_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), but is invalid or malformed,
|
|
9
|
+
* the function will throw an error and it is up to the user to handle and respond as they see fit.
|
|
10
|
+
*
|
|
11
|
+
* ```js
|
|
12
|
+
* import http from 'http';
|
|
13
|
+
* import { parseRequestParams } from 'graphql-http/lib/use/http';
|
|
14
|
+
*
|
|
15
|
+
* const server = http.createServer(async (req, res) => {
|
|
16
|
+
* if (req.url.startsWith('/graphql')) {
|
|
17
|
+
* try {
|
|
18
|
+
* const maybeParams = await parseRequestParams(req, res);
|
|
19
|
+
* if (!maybeParams) {
|
|
20
|
+
* // not a well-formatted GraphQL over HTTP request,
|
|
21
|
+
* // parser responded and there's nothing else to do
|
|
22
|
+
* return;
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* // well-formatted GraphQL over HTTP request,
|
|
26
|
+
* // with valid parameters
|
|
27
|
+
* res.writeHead(200).end(JSON.stringify(maybeParams, null, ' '));
|
|
28
|
+
* } catch (err) {
|
|
29
|
+
* // well-formatted GraphQL over HTTP request,
|
|
30
|
+
* // but with invalid parameters
|
|
31
|
+
* res.writeHead(400).end(err.message);
|
|
32
|
+
* }
|
|
33
|
+
* } else {
|
|
34
|
+
* res.writeHead(404).end();
|
|
35
|
+
* }
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* server.listen(4000);
|
|
39
|
+
* console.log('Listening to port 4000');
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @category Server/http
|
|
43
|
+
*/
|
|
44
|
+
export async function parseRequestParams(req, res) {
|
|
45
|
+
const rawReq = toRequest(req, res);
|
|
46
|
+
const paramsOrRes = await rawParseRequestParams(rawReq);
|
|
47
|
+
if (!('query' in paramsOrRes)) {
|
|
48
|
+
const [body, init] = paramsOrRes;
|
|
49
|
+
res.writeHead(init.status, init.statusText, init.headers).end(body);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return paramsOrRes;
|
|
53
|
+
}
|
|
2
54
|
/**
|
|
3
55
|
* Create a GraphQL over HTTP spec compliant request handler for
|
|
4
56
|
* the Node environment http module.
|
|
@@ -26,18 +78,7 @@ export function createHandler(options) {
|
|
|
26
78
|
if (!req.method) {
|
|
27
79
|
throw new Error('Missing request method');
|
|
28
80
|
}
|
|
29
|
-
const [body, init] = await handle(
|
|
30
|
-
url: req.url,
|
|
31
|
-
method: req.method,
|
|
32
|
-
headers: req.headers,
|
|
33
|
-
body: () => new Promise((resolve) => {
|
|
34
|
-
let body = '';
|
|
35
|
-
req.on('data', (chunk) => (body += chunk));
|
|
36
|
-
req.on('end', () => resolve(body));
|
|
37
|
-
}),
|
|
38
|
-
raw: req,
|
|
39
|
-
context: { res },
|
|
40
|
-
});
|
|
81
|
+
const [body, init] = await handle(toRequest(req, res));
|
|
41
82
|
res.writeHead(init.status, init.statusText, init.headers).end(body);
|
|
42
83
|
}
|
|
43
84
|
catch (err) {
|
|
@@ -49,3 +90,23 @@ export function createHandler(options) {
|
|
|
49
90
|
}
|
|
50
91
|
};
|
|
51
92
|
}
|
|
93
|
+
function toRequest(req, res) {
|
|
94
|
+
if (!req.url) {
|
|
95
|
+
throw new Error('Missing request URL');
|
|
96
|
+
}
|
|
97
|
+
if (!req.method) {
|
|
98
|
+
throw new Error('Missing request method');
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
url: req.url,
|
|
102
|
+
method: req.method,
|
|
103
|
+
headers: req.headers,
|
|
104
|
+
body: () => new Promise((resolve) => {
|
|
105
|
+
let body = '';
|
|
106
|
+
req.on('data', (chunk) => (body += chunk));
|
|
107
|
+
req.on('end', () => resolve(body));
|
|
108
|
+
}),
|
|
109
|
+
raw: req,
|
|
110
|
+
context: { res },
|
|
111
|
+
};
|
|
112
|
+
}
|
package/lib/use/http2.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import type { Http2ServerRequest, Http2ServerResponse } from 'http2';
|
|
3
3
|
import { HandlerOptions as RawHandlerOptions, OperationContext } from '../handler.mjs';
|
|
4
|
+
import { RequestParams } from '../common.mjs';
|
|
4
5
|
/**
|
|
5
6
|
* The context in the request for the handler.
|
|
6
7
|
*
|
|
@@ -9,6 +10,61 @@ import { HandlerOptions as RawHandlerOptions, OperationContext } from '../handle
|
|
|
9
10
|
export interface RequestContext {
|
|
10
11
|
res: Http2ServerResponse;
|
|
11
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
|
|
15
|
+
*
|
|
16
|
+
* If the HTTP request _is not_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), the function will respond
|
|
17
|
+
* on the `Http2ServerResponse` argument and return `null`.
|
|
18
|
+
*
|
|
19
|
+
* If the HTTP request _is_ a [well-formatted GraphQL over HTTP request](https://graphql.github.io/graphql-over-http/draft/#sec-Request), but is invalid or malformed,
|
|
20
|
+
* the function will throw an error and it is up to the user to handle and respond as they see fit.
|
|
21
|
+
*
|
|
22
|
+
* ```shell
|
|
23
|
+
* $ openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \
|
|
24
|
+
* -keyout localhost-privkey.pem -out localhost-cert.pem
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* ```js
|
|
28
|
+
* import fs from 'fs';
|
|
29
|
+
* import http2 from 'http2';
|
|
30
|
+
* import { parseRequestParams } from 'graphql-http/lib/use/http2';
|
|
31
|
+
*
|
|
32
|
+
* const server = http2.createSecureServer(
|
|
33
|
+
* {
|
|
34
|
+
* key: fs.readFileSync('localhost-privkey.pem'),
|
|
35
|
+
* cert: fs.readFileSync('localhost-cert.pem'),
|
|
36
|
+
* },
|
|
37
|
+
* async (req, res) => {
|
|
38
|
+
* if (req.url.startsWith('/graphql')) {
|
|
39
|
+
* try {
|
|
40
|
+
* const maybeParams = await parseRequestParams(req, res);
|
|
41
|
+
* if (!maybeParams) {
|
|
42
|
+
* // not a well-formatted GraphQL over HTTP request,
|
|
43
|
+
* // parser responded and there's nothing else to do
|
|
44
|
+
* return;
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* // well-formatted GraphQL over HTTP request,
|
|
48
|
+
* // with valid parameters
|
|
49
|
+
* res.writeHead(200).end(JSON.stringify(maybeParams, null, ' '));
|
|
50
|
+
* } catch (err) {
|
|
51
|
+
* // well-formatted GraphQL over HTTP request,
|
|
52
|
+
* // but with invalid parameters
|
|
53
|
+
* res.writeHead(400).end(err.message);
|
|
54
|
+
* }
|
|
55
|
+
* } else {
|
|
56
|
+
* res.writeHead(404).end();
|
|
57
|
+
* }
|
|
58
|
+
* },
|
|
59
|
+
* );
|
|
60
|
+
*
|
|
61
|
+
* server.listen(4000);
|
|
62
|
+
* console.log('Listening to port 4000');
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* @category Server/http2
|
|
66
|
+
*/
|
|
67
|
+
export declare function parseRequestParams(req: Http2ServerRequest, res: Http2ServerResponse): Promise<RequestParams | null>;
|
|
12
68
|
/**
|
|
13
69
|
* Handler options when using the http adapter.
|
|
14
70
|
*
|