graphql-http 1.21.0 → 1.22.1
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 +11 -1
- package/lib/audits/render.js +8 -3
- package/lib/audits/render.mjs +8 -3
- package/lib/handler.d.mts +19 -2
- package/lib/handler.d.ts +19 -2
- package/lib/handler.js +118 -111
- package/lib/handler.mjs +116 -110
- package/lib/use/express.d.mts +41 -0
- package/lib/use/express.d.ts +41 -0
- package/lib/use/express.js +73 -19
- package/lib/use/express.mjs +72 -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 +76 -13
- package/lib/use/http.mjs +75 -13
- package/lib/use/http2.d.mts +56 -0
- package/lib/use/http2.d.ts +56 -0
- package/lib/use/http2.js +94 -13
- package/lib/use/http2.mjs +93 -13
- package/lib/use/koa.d.mts +47 -1
- package/lib/use/koa.d.ts +47 -1
- package/lib/use/koa.js +85 -1
- package/lib/use/koa.mjs +84 -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 +32 -32
- package/umd/graphql-http-audits.js +8 -3
- package/umd/graphql-http-audits.min.js +1 -1
- package/umd/graphql-http-audits.min.js.gz +0 -0
- package/umd/graphql-http.min.js.gz +0 -0
package/README.md
CHANGED
|
@@ -264,6 +264,16 @@ const client = createClient({
|
|
|
264
264
|
})();
|
|
265
265
|
```
|
|
266
266
|
|
|
267
|
+
#### Serve [GraphiQL](https://github.com/graphql/graphiql)
|
|
268
|
+
|
|
269
|
+
Thanks to [`ruru`](https://github.com/graphile/crystal/tree/main/grafast/ruru), serving GraphiQL is as easy as running:
|
|
270
|
+
|
|
271
|
+
```sh
|
|
272
|
+
npx ruru -SP -p 4001 -e http://localhost:4000/graphql
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Open [http://localhost:4001](http://localhost:4001) in the browser to use it.
|
|
276
|
+
|
|
267
277
|
## Recipes
|
|
268
278
|
|
|
269
279
|
<details id="promise">
|
|
@@ -497,7 +507,7 @@ const client = createClient({
|
|
|
497
507
|
<summary><a href="#browser">🔗</a> Client usage in browser</summary>
|
|
498
508
|
|
|
499
509
|
```html
|
|
500
|
-
<!
|
|
510
|
+
<!doctype html>
|
|
501
511
|
<html>
|
|
502
512
|
<head>
|
|
503
513
|
<meta charset="utf-8" />
|
package/lib/audits/render.js
CHANGED
|
@@ -89,6 +89,7 @@ async function renderAuditResultsToHTML(results) {
|
|
|
89
89
|
}
|
|
90
90
|
exports.renderAuditResultsToHTML = renderAuditResultsToHTML;
|
|
91
91
|
async function printAuditFail(result) {
|
|
92
|
+
var _a;
|
|
92
93
|
let report = '';
|
|
93
94
|
report += `<li><code>${result.id}</code> ${result.name}\n`;
|
|
94
95
|
report += '<details>\n';
|
|
@@ -101,7 +102,7 @@ async function printAuditFail(result) {
|
|
|
101
102
|
if (key === 'date') {
|
|
102
103
|
headers[key] = '<timestamp>';
|
|
103
104
|
}
|
|
104
|
-
else if (['cf-ray', 'server-timing'].includes(key)) {
|
|
105
|
+
else if (['cf-ray', 'server-timing', 'set-cookie'].includes(key)) {
|
|
105
106
|
headers[key] = '<omitted>';
|
|
106
107
|
}
|
|
107
108
|
else {
|
|
@@ -112,9 +113,13 @@ async function printAuditFail(result) {
|
|
|
112
113
|
try {
|
|
113
114
|
text = await res.text();
|
|
114
115
|
json = JSON.parse(text);
|
|
116
|
+
// is json, there shouldnt be nothing to sanitize (hopefully)
|
|
115
117
|
}
|
|
116
|
-
catch (
|
|
117
|
-
//
|
|
118
|
+
catch (_b) {
|
|
119
|
+
// is not json, avoid rendering html (rest is allowed)
|
|
120
|
+
if ((_a = res.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('text/html')) {
|
|
121
|
+
text = '<html omitted>';
|
|
122
|
+
}
|
|
118
123
|
}
|
|
119
124
|
const stringified = JSON.stringify({
|
|
120
125
|
status: res.status,
|
package/lib/audits/render.mjs
CHANGED
|
@@ -85,6 +85,7 @@ export async function renderAuditResultsToHTML(results) {
|
|
|
85
85
|
return report;
|
|
86
86
|
}
|
|
87
87
|
async function printAuditFail(result) {
|
|
88
|
+
var _a;
|
|
88
89
|
let report = '';
|
|
89
90
|
report += `<li><code>${result.id}</code> ${result.name}\n`;
|
|
90
91
|
report += '<details>\n';
|
|
@@ -97,7 +98,7 @@ async function printAuditFail(result) {
|
|
|
97
98
|
if (key === 'date') {
|
|
98
99
|
headers[key] = '<timestamp>';
|
|
99
100
|
}
|
|
100
|
-
else if (['cf-ray', 'server-timing'].includes(key)) {
|
|
101
|
+
else if (['cf-ray', 'server-timing', 'set-cookie'].includes(key)) {
|
|
101
102
|
headers[key] = '<omitted>';
|
|
102
103
|
}
|
|
103
104
|
else {
|
|
@@ -108,9 +109,13 @@ async function printAuditFail(result) {
|
|
|
108
109
|
try {
|
|
109
110
|
text = await res.text();
|
|
110
111
|
json = JSON.parse(text);
|
|
112
|
+
// is json, there shouldnt be nothing to sanitize (hopefully)
|
|
111
113
|
}
|
|
112
|
-
catch (
|
|
113
|
-
//
|
|
114
|
+
catch (_b) {
|
|
115
|
+
// is not json, avoid rendering html (rest is allowed)
|
|
116
|
+
if ((_a = res.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('text/html')) {
|
|
117
|
+
text = '<html omitted>';
|
|
118
|
+
}
|
|
114
119
|
}
|
|
115
120
|
const stringified = JSON.stringify({
|
|
116
121
|
status: res.status,
|
package/lib/handler.d.mts
CHANGED
|
@@ -102,8 +102,10 @@ export type OperationContext = Record<PropertyKey, unknown> | symbol | number |
|
|
|
102
102
|
*/
|
|
103
103
|
export type FormatError = (err: Readonly<GraphQLError | Error>) => GraphQLError | Error;
|
|
104
104
|
/**
|
|
105
|
-
* The request parser for an incoming GraphQL request
|
|
106
|
-
*
|
|
105
|
+
* The request parser for an incoming GraphQL request in the handler.
|
|
106
|
+
*
|
|
107
|
+
* It should parse and validate the request itself, including the request method
|
|
108
|
+
* and the content-type of the body.
|
|
107
109
|
*
|
|
108
110
|
* In case you are extending the server to handle more request types, this is the
|
|
109
111
|
* perfect place to do so.
|
|
@@ -120,6 +122,21 @@ export type FormatError = (err: Readonly<GraphQLError | Error>) => GraphQLError
|
|
|
120
122
|
* @category Server
|
|
121
123
|
*/
|
|
122
124
|
export type ParseRequestParams<RequestRaw = unknown, RequestContext = unknown> = (req: Request<RequestRaw, RequestContext>) => Promise<RequestParams | Response | void> | RequestParams | Response | void;
|
|
125
|
+
/**
|
|
126
|
+
* The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
|
|
127
|
+
* It parses and validates the request itself, including the request method and the
|
|
128
|
+
* content-type of the body.
|
|
129
|
+
*
|
|
130
|
+
* If the HTTP request itself is invalid or malformed, the function will return an
|
|
131
|
+
* appropriate {@link Response}.
|
|
132
|
+
*
|
|
133
|
+
* If the HTTP request is valid, but is not a well-formatted GraphQL request, the
|
|
134
|
+
* function will throw an error and it is up to the user to handle and respond as
|
|
135
|
+
* they see fit.
|
|
136
|
+
*
|
|
137
|
+
* @category Server
|
|
138
|
+
*/
|
|
139
|
+
export declare function parseRequestParams<RequestRaw = unknown, RequestContext = unknown>(req: Request<RequestRaw, RequestContext>): Promise<Response | RequestParams>;
|
|
123
140
|
/** @category Server */
|
|
124
141
|
export type OperationArgs<Context extends OperationContext = undefined> = ExecutionArgs & {
|
|
125
142
|
contextValue?: Context;
|
package/lib/handler.d.ts
CHANGED
|
@@ -102,8 +102,10 @@ export type OperationContext = Record<PropertyKey, unknown> | symbol | number |
|
|
|
102
102
|
*/
|
|
103
103
|
export type FormatError = (err: Readonly<GraphQLError | Error>) => GraphQLError | Error;
|
|
104
104
|
/**
|
|
105
|
-
* The request parser for an incoming GraphQL request
|
|
106
|
-
*
|
|
105
|
+
* The request parser for an incoming GraphQL request in the handler.
|
|
106
|
+
*
|
|
107
|
+
* It should parse and validate the request itself, including the request method
|
|
108
|
+
* and the content-type of the body.
|
|
107
109
|
*
|
|
108
110
|
* In case you are extending the server to handle more request types, this is the
|
|
109
111
|
* perfect place to do so.
|
|
@@ -120,6 +122,21 @@ export type FormatError = (err: Readonly<GraphQLError | Error>) => GraphQLError
|
|
|
120
122
|
* @category Server
|
|
121
123
|
*/
|
|
122
124
|
export type ParseRequestParams<RequestRaw = unknown, RequestContext = unknown> = (req: Request<RequestRaw, RequestContext>) => Promise<RequestParams | Response | void> | RequestParams | Response | void;
|
|
125
|
+
/**
|
|
126
|
+
* The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
|
|
127
|
+
* It parses and validates the request itself, including the request method and the
|
|
128
|
+
* content-type of the body.
|
|
129
|
+
*
|
|
130
|
+
* If the HTTP request itself is invalid or malformed, the function will return an
|
|
131
|
+
* appropriate {@link Response}.
|
|
132
|
+
*
|
|
133
|
+
* If the HTTP request is valid, but is not a well-formatted GraphQL request, the
|
|
134
|
+
* function will throw an error and it is up to the user to handle and respond as
|
|
135
|
+
* they see fit.
|
|
136
|
+
*
|
|
137
|
+
* @category Server
|
|
138
|
+
*/
|
|
139
|
+
export declare function parseRequestParams<RequestRaw = unknown, RequestContext = unknown>(req: Request<RequestRaw, RequestContext>): Promise<Response | RequestParams>;
|
|
123
140
|
/** @category Server */
|
|
124
141
|
export type OperationArgs<Context extends OperationContext = undefined> = ExecutionArgs & {
|
|
125
142
|
contextValue?: Context;
|
package/lib/handler.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.createHandler = void 0;
|
|
8
|
+
exports.createHandler = exports.parseRequestParams = void 0;
|
|
9
9
|
const graphql_1 = require("graphql");
|
|
10
10
|
const utils_1 = require("./utils");
|
|
11
11
|
/** Checks whether the passed value is the `graphql-http` server agnostic response. */
|
|
@@ -15,6 +15,117 @@ function isResponse(val) {
|
|
|
15
15
|
(typeof val[0] === 'string' || val[0] === null) &&
|
|
16
16
|
(0, utils_1.isObject)(val[1]));
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
|
|
20
|
+
* It parses and validates the request itself, including the request method and the
|
|
21
|
+
* content-type of the body.
|
|
22
|
+
*
|
|
23
|
+
* If the HTTP request itself is invalid or malformed, the function will return an
|
|
24
|
+
* appropriate {@link Response}.
|
|
25
|
+
*
|
|
26
|
+
* If the HTTP request is valid, but is not a well-formatted GraphQL request, the
|
|
27
|
+
* function will throw an error and it is up to the user to handle and respond as
|
|
28
|
+
* they see fit.
|
|
29
|
+
*
|
|
30
|
+
* @category Server
|
|
31
|
+
*/
|
|
32
|
+
async function parseRequestParams(req) {
|
|
33
|
+
var _a, _b;
|
|
34
|
+
const method = req.method;
|
|
35
|
+
if (method !== 'GET' && method !== 'POST') {
|
|
36
|
+
return [
|
|
37
|
+
null,
|
|
38
|
+
{
|
|
39
|
+
status: 405,
|
|
40
|
+
statusText: 'Method Not Allowed',
|
|
41
|
+
headers: {
|
|
42
|
+
allow: 'GET, POST',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
const [mediaType, charset = 'charset=utf-8', // utf-8 is assumed when not specified. this parameter is either "charset" or "boundary" (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length)
|
|
48
|
+
] = (getHeader(req, 'content-type') || '')
|
|
49
|
+
.replace(/\s/g, '')
|
|
50
|
+
.toLowerCase()
|
|
51
|
+
.split(';');
|
|
52
|
+
const partParams = {};
|
|
53
|
+
switch (true) {
|
|
54
|
+
case method === 'GET': {
|
|
55
|
+
// TODO: what if content-type is specified and is not application/x-www-form-urlencoded?
|
|
56
|
+
try {
|
|
57
|
+
const [, search] = req.url.split('?');
|
|
58
|
+
const searchParams = new URLSearchParams(search);
|
|
59
|
+
partParams.operationName =
|
|
60
|
+
(_a = searchParams.get('operationName')) !== null && _a !== void 0 ? _a : undefined;
|
|
61
|
+
partParams.query = (_b = searchParams.get('query')) !== null && _b !== void 0 ? _b : undefined;
|
|
62
|
+
const variables = searchParams.get('variables');
|
|
63
|
+
if (variables)
|
|
64
|
+
partParams.variables = JSON.parse(variables);
|
|
65
|
+
const extensions = searchParams.get('extensions');
|
|
66
|
+
if (extensions)
|
|
67
|
+
partParams.extensions = JSON.parse(extensions);
|
|
68
|
+
}
|
|
69
|
+
catch (_c) {
|
|
70
|
+
throw new Error('Unparsable URL');
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case method === 'POST' &&
|
|
75
|
+
mediaType === 'application/json' &&
|
|
76
|
+
charset === 'charset=utf-8':
|
|
77
|
+
{
|
|
78
|
+
if (!req.body) {
|
|
79
|
+
throw new Error('Missing body');
|
|
80
|
+
}
|
|
81
|
+
let data;
|
|
82
|
+
try {
|
|
83
|
+
const body = typeof req.body === 'function' ? await req.body() : req.body;
|
|
84
|
+
data = typeof body === 'string' ? JSON.parse(body) : body;
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
throw new Error('Unparsable JSON body');
|
|
88
|
+
}
|
|
89
|
+
if (!(0, utils_1.isObject)(data)) {
|
|
90
|
+
throw new Error('JSON body must be an object');
|
|
91
|
+
}
|
|
92
|
+
partParams.operationName = data.operationName;
|
|
93
|
+
partParams.query = data.query;
|
|
94
|
+
partParams.variables = data.variables;
|
|
95
|
+
partParams.extensions = data.extensions;
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
default: // graphql-http doesnt support any other content type
|
|
99
|
+
return [
|
|
100
|
+
null,
|
|
101
|
+
{
|
|
102
|
+
status: 415,
|
|
103
|
+
statusText: 'Unsupported Media Type',
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
}
|
|
107
|
+
if (partParams.query == null)
|
|
108
|
+
throw new Error('Missing query');
|
|
109
|
+
if (typeof partParams.query !== 'string')
|
|
110
|
+
throw new Error('Invalid query');
|
|
111
|
+
if (partParams.variables != null &&
|
|
112
|
+
(typeof partParams.variables !== 'object' ||
|
|
113
|
+
Array.isArray(partParams.variables))) {
|
|
114
|
+
throw new Error('Invalid variables');
|
|
115
|
+
}
|
|
116
|
+
if (partParams.operationName != null &&
|
|
117
|
+
typeof partParams.operationName !== 'string') {
|
|
118
|
+
throw new Error('Invalid operationName');
|
|
119
|
+
}
|
|
120
|
+
if (partParams.extensions != null &&
|
|
121
|
+
(typeof partParams.extensions !== 'object' ||
|
|
122
|
+
Array.isArray(partParams.extensions))) {
|
|
123
|
+
throw new Error('Invalid extensions');
|
|
124
|
+
}
|
|
125
|
+
// request parameters are checked and now complete
|
|
126
|
+
return partParams;
|
|
127
|
+
}
|
|
128
|
+
exports.parseRequestParams = parseRequestParams;
|
|
18
129
|
/**
|
|
19
130
|
* Makes a GraphQL over HTTP spec compliant server handler. The handler can
|
|
20
131
|
* be used with your favorite server library.
|
|
@@ -71,7 +182,7 @@ function isResponse(val) {
|
|
|
71
182
|
* @category Server
|
|
72
183
|
*/
|
|
73
184
|
function createHandler(options) {
|
|
74
|
-
const { schema, context, validate = graphql_1.validate, validationRules = [], execute = graphql_1.execute, parse = graphql_1.parse, getOperationAST = graphql_1.getOperationAST, rootValue, onSubscribe, onOperation, formatError = (err) => err, parseRequestParams =
|
|
185
|
+
const { schema, context, validate = graphql_1.validate, validationRules = [], execute = graphql_1.execute, parse = graphql_1.parse, getOperationAST = graphql_1.getOperationAST, rootValue, onSubscribe, onOperation, formatError = (err) => err, parseRequestParams: optionsParseRequestParams = parseRequestParams, } = options;
|
|
75
186
|
return async function handler(req) {
|
|
76
187
|
let acceptedMediaType = null;
|
|
77
188
|
const accepts = (getHeader(req, 'accept') || '*/*')
|
|
@@ -82,9 +193,9 @@ function createHandler(options) {
|
|
|
82
193
|
// accept-charset became obsolete, shouldnt be used (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Charset)
|
|
83
194
|
// TODO: handle the weight parameter "q"
|
|
84
195
|
const [mediaType, ...params] = accept.split(';');
|
|
85
|
-
const charset = (params === null || params === void 0 ? void 0 : params.find((param) => param.includes('charset='))) || 'charset=
|
|
196
|
+
const charset = (params === null || params === void 0 ? void 0 : params.find((param) => param.includes('charset='))) || 'charset=utf-8'; // utf-8 is assumed when not specified;
|
|
86
197
|
if (mediaType === 'application/graphql-response+json' &&
|
|
87
|
-
charset === 'charset=
|
|
198
|
+
charset === 'charset=utf-8') {
|
|
88
199
|
acceptedMediaType = 'application/graphql-response+json';
|
|
89
200
|
break;
|
|
90
201
|
}
|
|
@@ -92,7 +203,7 @@ function createHandler(options) {
|
|
|
92
203
|
if ((mediaType === 'application/json' ||
|
|
93
204
|
mediaType === 'application/*' ||
|
|
94
205
|
mediaType === '*/*') &&
|
|
95
|
-
charset === 'charset=utf8') {
|
|
206
|
+
(charset === 'charset=utf-8' || charset === 'charset=utf8')) {
|
|
96
207
|
acceptedMediaType = 'application/json';
|
|
97
208
|
break;
|
|
98
209
|
}
|
|
@@ -111,9 +222,9 @@ function createHandler(options) {
|
|
|
111
222
|
}
|
|
112
223
|
let params;
|
|
113
224
|
try {
|
|
114
|
-
let paramsOrRes = await
|
|
225
|
+
let paramsOrRes = await optionsParseRequestParams(req);
|
|
115
226
|
if (!paramsOrRes)
|
|
116
|
-
paramsOrRes = await
|
|
227
|
+
paramsOrRes = await parseRequestParams(req);
|
|
117
228
|
if (isResponse(paramsOrRes))
|
|
118
229
|
return paramsOrRes;
|
|
119
230
|
params = paramsOrRes;
|
|
@@ -222,110 +333,6 @@ function createHandler(options) {
|
|
|
222
333
|
};
|
|
223
334
|
}
|
|
224
335
|
exports.createHandler = createHandler;
|
|
225
|
-
/**
|
|
226
|
-
* The default request params parser. Used when no custom one is provided or if it
|
|
227
|
-
* returns nothing.
|
|
228
|
-
*
|
|
229
|
-
* Read more about it in {@link ParseRequestParams}.
|
|
230
|
-
*
|
|
231
|
-
* TODO: should graphql-http itself care about content-encoding? I'd say unzipping should happen before handler is reached
|
|
232
|
-
*/
|
|
233
|
-
async function defaultParseRequestParams(req) {
|
|
234
|
-
var _a, _b;
|
|
235
|
-
const method = req.method;
|
|
236
|
-
if (method !== 'GET' && method !== 'POST') {
|
|
237
|
-
return [
|
|
238
|
-
null,
|
|
239
|
-
{
|
|
240
|
-
status: 405,
|
|
241
|
-
statusText: 'Method Not Allowed',
|
|
242
|
-
headers: {
|
|
243
|
-
allow: 'GET, POST',
|
|
244
|
-
},
|
|
245
|
-
},
|
|
246
|
-
];
|
|
247
|
-
}
|
|
248
|
-
const [mediaType, charset = 'charset=utf-8', // utf-8 is assumed when not specified. this parameter is either "charset" or "boundary" (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length)
|
|
249
|
-
] = (getHeader(req, 'content-type') || '')
|
|
250
|
-
.replace(/\s/g, '')
|
|
251
|
-
.toLowerCase()
|
|
252
|
-
.split(';');
|
|
253
|
-
const partParams = {};
|
|
254
|
-
switch (true) {
|
|
255
|
-
case method === 'GET': {
|
|
256
|
-
// TODO: what if content-type is specified and is not application/x-www-form-urlencoded?
|
|
257
|
-
try {
|
|
258
|
-
const [, search] = req.url.split('?');
|
|
259
|
-
const searchParams = new URLSearchParams(search);
|
|
260
|
-
partParams.operationName =
|
|
261
|
-
(_a = searchParams.get('operationName')) !== null && _a !== void 0 ? _a : undefined;
|
|
262
|
-
partParams.query = (_b = searchParams.get('query')) !== null && _b !== void 0 ? _b : undefined;
|
|
263
|
-
const variables = searchParams.get('variables');
|
|
264
|
-
if (variables)
|
|
265
|
-
partParams.variables = JSON.parse(variables);
|
|
266
|
-
const extensions = searchParams.get('extensions');
|
|
267
|
-
if (extensions)
|
|
268
|
-
partParams.extensions = JSON.parse(extensions);
|
|
269
|
-
}
|
|
270
|
-
catch (_c) {
|
|
271
|
-
throw new Error('Unparsable URL');
|
|
272
|
-
}
|
|
273
|
-
break;
|
|
274
|
-
}
|
|
275
|
-
case method === 'POST' &&
|
|
276
|
-
mediaType === 'application/json' &&
|
|
277
|
-
charset === 'charset=utf-8':
|
|
278
|
-
{
|
|
279
|
-
if (!req.body) {
|
|
280
|
-
throw new Error('Missing body');
|
|
281
|
-
}
|
|
282
|
-
let data;
|
|
283
|
-
try {
|
|
284
|
-
const body = typeof req.body === 'function' ? await req.body() : req.body;
|
|
285
|
-
data = typeof body === 'string' ? JSON.parse(body) : body;
|
|
286
|
-
}
|
|
287
|
-
catch (err) {
|
|
288
|
-
throw new Error('Unparsable JSON body');
|
|
289
|
-
}
|
|
290
|
-
if (!(0, utils_1.isObject)(data)) {
|
|
291
|
-
throw new Error('JSON body must be an object');
|
|
292
|
-
}
|
|
293
|
-
partParams.operationName = data.operationName;
|
|
294
|
-
partParams.query = data.query;
|
|
295
|
-
partParams.variables = data.variables;
|
|
296
|
-
partParams.extensions = data.extensions;
|
|
297
|
-
break;
|
|
298
|
-
}
|
|
299
|
-
default: // graphql-http doesnt support any other content type
|
|
300
|
-
return [
|
|
301
|
-
null,
|
|
302
|
-
{
|
|
303
|
-
status: 415,
|
|
304
|
-
statusText: 'Unsupported Media Type',
|
|
305
|
-
},
|
|
306
|
-
];
|
|
307
|
-
}
|
|
308
|
-
if (partParams.query == null)
|
|
309
|
-
throw new Error('Missing query');
|
|
310
|
-
if (typeof partParams.query !== 'string')
|
|
311
|
-
throw new Error('Invalid query');
|
|
312
|
-
if (partParams.variables != null &&
|
|
313
|
-
(typeof partParams.variables !== 'object' ||
|
|
314
|
-
Array.isArray(partParams.variables))) {
|
|
315
|
-
throw new Error('Invalid variables');
|
|
316
|
-
}
|
|
317
|
-
if (partParams.operationName != null &&
|
|
318
|
-
typeof partParams.operationName !== 'string') {
|
|
319
|
-
throw new Error('Invalid operationName');
|
|
320
|
-
}
|
|
321
|
-
if (partParams.extensions != null &&
|
|
322
|
-
(typeof partParams.extensions !== 'object' ||
|
|
323
|
-
Array.isArray(partParams.extensions))) {
|
|
324
|
-
throw new Error('Invalid extensions');
|
|
325
|
-
}
|
|
326
|
-
// request parameters are checked and now complete
|
|
327
|
-
return partParams;
|
|
328
|
-
}
|
|
329
336
|
/**
|
|
330
337
|
* Creates an appropriate GraphQL over HTTP response following the provided arguments.
|
|
331
338
|
*
|