UNPKG

2.17 kBPlain TextView Raw
1import express from 'express';
2import {
3 GraphQLOptions,
4 HttpQueryError,
5 runHttpQuery,
6 convertNodeHttpToRequest,
7} from 'apollo-server-core';
8import { ValueOrPromise } from 'apollo-server-types';
9
10export interface ExpressGraphQLOptionsFunction {
11 (req: express.Request, res: express.Response): ValueOrPromise<GraphQLOptions>;
12}
13
14// Design principles:
15// - there is just one way allowed: POST request with JSON body. Nothing else.
16// - simple, fast and secure
17//
18
19export function graphqlExpress(
20 options: GraphQLOptions | ExpressGraphQLOptionsFunction,
21): express.Handler {
22 if (!options) {
23 throw new Error('Apollo Server requires options.');
24 }
25
26 if (arguments.length > 1) {
27 throw new Error(
28 `Apollo Server expects exactly one argument, got ${arguments.length}`,
29 );
30 }
31
32 return (req, res, next): void => {
33 runHttpQuery([req, res], {
34 method: req.method,
35 options: options,
36 query: req.method === 'POST' ? req.body : req.query,
37 request: convertNodeHttpToRequest(req),
38 }).then(
39 ({ graphqlResponse, responseInit }) => {
40 if (responseInit.headers) {
41 for (const [name, value] of Object.entries(responseInit.headers)) {
42 res.setHeader(name, value);
43 }
44 }
45
46 // Using `.send` is a best practice for Express, but we also just use
47 // `.end` for compatibility with `connect`.
48 if (typeof res.send === 'function') {
49 res.send(graphqlResponse);
50 } else {
51 res.end(graphqlResponse);
52 }
53 },
54 (error: HttpQueryError) => {
55 if ('HttpQueryError' !== error.name) {
56 return next(error);
57 }
58
59 if (error.headers) {
60 for (const [name, value] of Object.entries(error.headers)) {
61 res.setHeader(name, value);
62 }
63 }
64
65 res.statusCode = error.statusCode;
66 if (typeof res.send === 'function') {
67 // Using `.send` is a best practice for Express, but we also just use
68 // `.end` for compatibility with `connect`.
69 res.send(error.message);
70 } else {
71 res.end(error.message);
72 }
73 },
74 );
75 };
76}