Skip to content

Commit faf3b2e

Browse files
committed
fastify parse request
1 parent 35c3caf commit faf3b2e

File tree

1 file changed

+75
-9
lines changed

1 file changed

+75
-9
lines changed

src/use/fastify.ts

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ import type { FastifyRequest, FastifyReply, RouteHandler } from 'fastify';
22
import {
33
createHandler as createRawHandler,
44
HandlerOptions as RawHandlerOptions,
5+
Request as RawRequest,
6+
parseRequestParams as rawParseRequestParams,
57
OperationContext,
68
} from '../handler';
9+
import { RequestParams } from '../common';
710

811
/**
912
* The context in the request for the handler.
@@ -13,6 +16,62 @@ import {
1316
export interface RequestContext {
1417
reply: FastifyReply;
1518
}
19+
/**
20+
* The GraphQL over HTTP spec compliant request parser for an incoming GraphQL request.
21+
*
22+
* 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
23+
* on the `Response` argument and return `null`.
24+
*
25+
* 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,
26+
* the function will throw an error and it is up to the user to handle and respond as they see fit.
27+
*
28+
* ```js
29+
* import Fastify from 'fastify'; // yarn add fastify
30+
* import { parseRequestParams } from 'graphql-http/lib/use/fastify';
31+
*
32+
* const fastify = Fastify();
33+
* fastify.all('/graphql', async (req, reply) => {
34+
* try {
35+
* const maybeParams = await parseRequestParams(req, reply);
36+
* if (!maybeParams) {
37+
* // not a well-formatted GraphQL over HTTP request,
38+
* // parser responded and there's nothing else to do
39+
* return;
40+
* }
41+
*
42+
* // well-formatted GraphQL over HTTP request,
43+
* // with valid parameters
44+
* reply.status(200).send(JSON.stringify(maybeParams, null, ' '));
45+
* } catch (err) {
46+
* // well-formatted GraphQL over HTTP request,
47+
* // but with invalid parameters
48+
* reply.status(400).send(err.message);
49+
* }
50+
* });
51+
*
52+
* fastify.listen({ port: 4000 });
53+
* console.log('Listening to port 4000');
54+
* ```
55+
*
56+
* @category Server/fastify
57+
*/
58+
export async function parseRequestParams(
59+
req: FastifyRequest,
60+
reply: FastifyReply,
61+
): Promise<RequestParams | null> {
62+
const rawReq = toRequest(req, reply);
63+
const paramsOrRes = await rawParseRequestParams(rawReq);
64+
if (!('query' in paramsOrRes)) {
65+
const [body, init] = paramsOrRes;
66+
reply
67+
.status(init.status)
68+
.headers(init.headers || {})
69+
// "or undefined" because `null` will be JSON stringified
70+
.send(body || undefined);
71+
return null;
72+
}
73+
return paramsOrRes;
74+
}
1675

1776
/**
1877
* Handler options when using the fastify adapter.
@@ -46,15 +105,7 @@ export function createHandler<Context extends OperationContext = undefined>(
46105
const handle = createRawHandler(options);
47106
return async function requestListener(req, reply) {
48107
try {
49-
const [body, init] = await handle({
50-
url: req.url,
51-
method: req.method,
52-
headers: req.headers,
53-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
54-
body: req.body as any,
55-
raw: req,
56-
context: { reply },
57-
});
108+
const [body, init] = await handle(toRequest(req, reply));
58109
reply
59110
.status(init.status)
60111
.headers(init.headers || {})
@@ -72,3 +123,18 @@ export function createHandler<Context extends OperationContext = undefined>(
72123
}
73124
};
74125
}
126+
127+
function toRequest(
128+
req: FastifyRequest,
129+
reply: FastifyReply,
130+
): RawRequest<FastifyRequest, RequestContext> {
131+
return {
132+
url: req.url,
133+
method: req.method,
134+
headers: req.headers,
135+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
136+
body: req.body as any,
137+
raw: req,
138+
context: { reply },
139+
};
140+
}

0 commit comments

Comments
 (0)