Skip to content

Commit 2caae00

Browse files
authored
feat(handler): Expose parseRequestParams from the core and each of the adapters (#111)
1 parent 5d5a821 commit 2caae00

16 files changed

+1225
-211
lines changed

docs/modules/handler.md

+39-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
### Functions
2626

2727
- [createHandler](handler.md#createhandler)
28+
- [parseRequestParams](handler.md#parserequestparams-1)
2829

2930
## Server
3031

@@ -124,8 +125,10 @@ ___
124125

125126
▸ (`req`): `Promise`<[`RequestParams`](../interfaces/common.RequestParams.md) \| [`Response`](handler.md#response) \| `void`\> \| [`RequestParams`](../interfaces/common.RequestParams.md) \| [`Response`](handler.md#response) \| `void`
126127

127-
The request parser for an incoming GraphQL request. It parses and validates the
128-
request itself, including the request method and the content-type of the body.
128+
The request parser for an incoming GraphQL request in the handler.
129+
130+
It should parse and validate the request itself, including the request method
131+
and the content-type of the body.
129132

130133
In case you are extending the server to handle more request types, this is the
131134
perfect place to do so.
@@ -258,3 +261,37 @@ console.log('Listening to port 4000');
258261
#### Returns
259262

260263
[`Handler`](handler.md#handler)<`RequestRaw`, `RequestContext`\>
264+
265+
___
266+
267+
### parseRequestParams
268+
269+
**parseRequestParams**<`RequestRaw`, `RequestContext`\>(`req`): `Promise`<[`Response`](handler.md#response) \| [`RequestParams`](../interfaces/common.RequestParams.md)\>
270+
271+
The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
272+
It parses and validates the request itself, including the request method and the
273+
content-type of the body.
274+
275+
If the HTTP request itself is invalid or malformed, the function will return an
276+
appropriate [Response](handler.md#response).
277+
278+
If the HTTP request is valid, but is not a well-formatted GraphQL request, the
279+
function will throw an error and it is up to the user to handle and respond as
280+
they see fit.
281+
282+
#### Type parameters
283+
284+
| Name | Type |
285+
| :------ | :------ |
286+
| `RequestRaw` | `unknown` |
287+
| `RequestContext` | `unknown` |
288+
289+
#### Parameters
290+
291+
| Name | Type |
292+
| :------ | :------ |
293+
| `req` | [`Request`](../interfaces/handler.Request.md)<`RequestRaw`, `RequestContext`\> |
294+
295+
#### Returns
296+
297+
`Promise`<[`Response`](handler.md#response) \| [`RequestParams`](../interfaces/common.RequestParams.md)\>

docs/modules/use_express.md

+54
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
### Functions
1616

1717
- [createHandler](use_express.md#createhandler)
18+
- [parseRequestParams](use_express.md#parserequestparams)
1819

1920
## Server/express
2021

@@ -66,3 +67,56 @@ console.log('Listening to port 4000');
6667
#### Returns
6768

6869
`Handler`
70+
71+
___
72+
73+
### parseRequestParams
74+
75+
**parseRequestParams**(`req`, `res`): `Promise`<[`RequestParams`](../interfaces/common.RequestParams.md) \| ``null``\>
76+
77+
The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
78+
79+
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
80+
on the `Response` argument and return `null`.
81+
82+
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,
83+
the function will throw an error and it is up to the user to handle and respond as they see fit.
84+
85+
```js
86+
import express from 'express'; // yarn add express
87+
import { parseRequestParams } from 'graphql-http/lib/use/express';
88+
89+
const app = express();
90+
app.all('/graphql', async (req, res) => {
91+
try {
92+
const maybeParams = await parseRequestParams(req, res);
93+
if (!maybeParams) {
94+
// not a well-formatted GraphQL over HTTP request,
95+
// parser responded and there's nothing else to do
96+
return;
97+
}
98+
99+
// well-formatted GraphQL over HTTP request,
100+
// with valid parameters
101+
res.writeHead(200).end(JSON.stringify(maybeParams, null, ' '));
102+
} catch (err) {
103+
// well-formatted GraphQL over HTTP request,
104+
// but with invalid parameters
105+
res.writeHead(400).end(err.message);
106+
}
107+
});
108+
109+
app.listen({ port: 4000 });
110+
console.log('Listening to port 4000');
111+
```
112+
113+
#### Parameters
114+
115+
| Name | Type |
116+
| :------ | :------ |
117+
| `req` | `Request`<`ParamsDictionary`, `any`, `any`, `ParsedQs`, `Record`<`string`, `any`\>\> |
118+
| `res` | `Response`<`any`, `Record`<`string`, `any`\>\> |
119+
120+
#### Returns
121+
122+
`Promise`<[`RequestParams`](../interfaces/common.RequestParams.md) \| ``null``\>

docs/modules/use_fastify.md

+54
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
### Functions
1616

1717
- [createHandler](use_fastify.md#createhandler)
18+
- [parseRequestParams](use_fastify.md#parserequestparams)
1819

1920
## Server/fastify
2021

@@ -66,3 +67,56 @@ console.log('Listening to port 4000');
6667
#### Returns
6768

6869
`RouteHandler`
70+
71+
___
72+
73+
### parseRequestParams
74+
75+
**parseRequestParams**(`req`, `reply`): `Promise`<[`RequestParams`](../interfaces/common.RequestParams.md) \| ``null``\>
76+
77+
The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
78+
79+
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
80+
on the `FastifyReply` argument and return `null`.
81+
82+
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,
83+
the function will throw an error and it is up to the user to handle and respond as they see fit.
84+
85+
```js
86+
import Fastify from 'fastify'; // yarn add fastify
87+
import { parseRequestParams } from 'graphql-http/lib/use/fastify';
88+
89+
const fastify = Fastify();
90+
fastify.all('/graphql', async (req, reply) => {
91+
try {
92+
const maybeParams = await parseRequestParams(req, reply);
93+
if (!maybeParams) {
94+
// not a well-formatted GraphQL over HTTP request,
95+
// parser responded and there's nothing else to do
96+
return;
97+
}
98+
99+
// well-formatted GraphQL over HTTP request,
100+
// with valid parameters
101+
reply.status(200).send(JSON.stringify(maybeParams, null, ' '));
102+
} catch (err) {
103+
// well-formatted GraphQL over HTTP request,
104+
// but with invalid parameters
105+
reply.status(400).send(err.message);
106+
}
107+
});
108+
109+
fastify.listen({ port: 4000 });
110+
console.log('Listening to port 4000');
111+
```
112+
113+
#### Parameters
114+
115+
| Name | Type |
116+
| :------ | :------ |
117+
| `req` | `FastifyRequest`<`RouteGenericInterface`, `RawServerDefault`, `IncomingMessage`, `FastifySchema`, `FastifyTypeProviderDefault`, `unknown`, `FastifyBaseLogger`, `ResolveFastifyRequestType`<`FastifyTypeProviderDefault`, `FastifySchema`, `RouteGenericInterface`\>\> |
118+
| `reply` | `FastifyReply`<`RawServerDefault`, `IncomingMessage`, `ServerResponse`<`IncomingMessage`\>, `RouteGenericInterface`, `unknown`, `FastifySchema`, `FastifyTypeProviderDefault`, `unknown`\> |
119+
120+
#### Returns
121+
122+
`Promise`<[`RequestParams`](../interfaces/common.RequestParams.md) \| ``null``\>

docs/modules/use_fetch.md

+63
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
### Functions
1616

1717
- [createHandler](use_fetch.md#createhandler)
18+
- [parseRequestParams](use_fetch.md#parserequestparams)
1819

1920
## Server/fetch
2021

@@ -87,3 +88,65 @@ console.log('Listening to port 4000');
8788
##### Returns
8889

8990
`Promise`<`Response`\>
91+
92+
___
93+
94+
### parseRequestParams
95+
96+
**parseRequestParams**(`req`, `api?`): `Promise`<[`RequestParams`](../interfaces/common.RequestParams.md) \| `Response`\>
97+
98+
The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
99+
100+
It is important to pass in the `abortedRef` so that the parser does not perform any
101+
operations on a disposed request (see example).
102+
103+
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`.
104+
105+
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,
106+
the function will throw an error and it is up to the user to handle and respond as they see fit.
107+
108+
```js
109+
import http from 'http';
110+
import { createServerAdapter } from '@whatwg-node/server'; // yarn add @whatwg-node/server
111+
import { parseRequestParams } from 'graphql-http/lib/use/fetch';
112+
113+
// Use this adapter in _any_ environment.
114+
const adapter = createServerAdapter({
115+
handleRequest: async (req) => {
116+
try {
117+
const paramsOrResponse = await parseRequestParams(req);
118+
if (paramsOrResponse instanceof Response) {
119+
// not a well-formatted GraphQL over HTTP request,
120+
// parser created a response object to use
121+
return paramsOrResponse;
122+
}
123+
124+
// well-formatted GraphQL over HTTP request,
125+
// with valid parameters
126+
return new Response(JSON.stringify(paramsOrResponse, null, ' '), {
127+
status: 200,
128+
});
129+
} catch (err) {
130+
// well-formatted GraphQL over HTTP request,
131+
// but with invalid parameters
132+
return new Response(err.message, { status: 400 });
133+
}
134+
},
135+
});
136+
137+
const server = http.createServer(adapter);
138+
139+
server.listen(4000);
140+
console.log('Listening to port 4000');
141+
```
142+
143+
#### Parameters
144+
145+
| Name | Type |
146+
| :------ | :------ |
147+
| `req` | `Request` |
148+
| `api` | `Partial`<[`FetchAPI`](../interfaces/use_fetch.FetchAPI.md)\> |
149+
150+
#### Returns
151+
152+
`Promise`<[`RequestParams`](../interfaces/common.RequestParams.md) \| `Response`\>

docs/modules/use_http.md

+57
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
### Functions
1616

1717
- [createHandler](use_http.md#createhandler)
18+
- [parseRequestParams](use_http.md#parserequestparams)
1819

1920
## Server/http
2021

@@ -78,3 +79,59 @@ console.log('Listening to port 4000');
7879
##### Returns
7980

8081
`Promise`<`void`\>
82+
83+
___
84+
85+
### parseRequestParams
86+
87+
**parseRequestParams**(`req`, `res`): `Promise`<[`RequestParams`](../interfaces/common.RequestParams.md) \| ``null``\>
88+
89+
The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
90+
91+
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
92+
on the `ServerResponse` argument and return `null`.
93+
94+
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,
95+
the function will throw an error and it is up to the user to handle and respond as they see fit.
96+
97+
```js
98+
import http from 'http';
99+
import { parseRequestParams } from 'graphql-http/lib/use/http';
100+
101+
const server = http.createServer(async (req, res) => {
102+
if (req.url.startsWith('/graphql')) {
103+
try {
104+
const maybeParams = await parseRequestParams(req, res);
105+
if (!maybeParams) {
106+
// not a well-formatted GraphQL over HTTP request,
107+
// parser responded and there's nothing else to do
108+
return;
109+
}
110+
111+
// well-formatted GraphQL over HTTP request,
112+
// with valid parameters
113+
res.writeHead(200).end(JSON.stringify(maybeParams, null, ' '));
114+
} catch (err) {
115+
// well-formatted GraphQL over HTTP request,
116+
// but with invalid parameters
117+
res.writeHead(400).end(err.message);
118+
}
119+
} else {
120+
res.writeHead(404).end();
121+
}
122+
});
123+
124+
server.listen(4000);
125+
console.log('Listening to port 4000');
126+
```
127+
128+
#### Parameters
129+
130+
| Name | Type |
131+
| :------ | :------ |
132+
| `req` | `IncomingMessage` |
133+
| `res` | `ServerResponse`<`IncomingMessage`\> |
134+
135+
#### Returns
136+
137+
`Promise`<[`RequestParams`](../interfaces/common.RequestParams.md) \| ``null``\>

0 commit comments

Comments
 (0)