UNPKG

8.92 kBMarkdownView Raw
1GraphQL HTTP Server Middleware
2==============================
3
4[![Build Status](https://travis-ci.org/graphql/express-graphql.svg?branch=master)](https://travis-ci.org/graphql/express-graphql)
5[![Coverage Status](https://coveralls.io/repos/graphql/express-graphql/badge.svg?branch=master&service=github)](https://coveralls.io/github/graphql/express-graphql?branch=master)
6
7Create a GraphQL HTTP server with any HTTP web framework that supports connect styled middleware, including [Connect](https://github.com/senchalabs/connect) itself, [Express](http://expressjs.com) and [Restify](http://restify.com/).
8
9## Installation
10
11```sh
12npm install --save express-graphql
13```
14
15
16## Simple Setup
17
18Just mount `express-graphql` as a route handler:
19
20```js
21const express = require('express');
22const graphqlHTTP = require('express-graphql');
23
24const app = express();
25
26app.use('/graphql', graphqlHTTP({
27 schema: MyGraphQLSchema,
28 graphiql: true
29}));
30
31app.listen(4000);
32```
33
34
35## Setup with Restify
36
37Use `.get` or `.post` (or both) rather than `.use` to configure your route handler. If you want to show GraphiQL in the browser, set `graphiql: true` on your `.get` handler.
38
39```js
40const restify = require('restify');
41const graphqlHTTP = require('express-graphql');
42
43const app = restify.createServer();
44
45app.post('/graphql', graphqlHTTP({
46 schema: MyGraphQLSchema,
47 graphiql: false
48}));
49
50app.get('/graphql', graphqlHTTP({
51 schema: MyGraphQLSchema,
52 graphiql: true
53}));
54
55app.listen(4000);
56```
57
58
59## Options
60
61The `graphqlHTTP` function accepts the following options:
62
63 * **`schema`**: A `GraphQLSchema` instance from [`GraphQL.js`][].
64 A `schema` *must* be provided.
65
66 * **`graphiql`**: If `true`, presents [GraphiQL][] when the GraphQL endpoint is
67 loaded in a browser. We recommend that you set
68 `graphiql` to `true` when your app is in development, because it's
69 quite useful. You may or may not want it in production.
70
71 * **`rootValue`**: A value to pass as the `rootValue` to the `graphql()`
72 function from [`GraphQL.js`][].
73
74 * **`context`**: A value to pass as the `context` to the `graphql()`
75 function from [`GraphQL.js`][]. If `context` is not provided, the
76 `request` object is passed as the context.
77
78 * **`pretty`**: If `true`, any JSON response will be pretty-printed.
79
80 * **`formatError`**: An optional function which will be used to format any
81 errors produced by fulfilling a GraphQL operation. If no function is
82 provided, GraphQL's default spec-compliant [`formatError`][] function will be used.
83
84 * **`extensions`**: An optional function for adding additional metadata to the
85 GraphQL response as a key-value object. The result will be added to
86 `"extensions"` field in the resulting JSON. This is often a useful place to
87 add development time metadata such as the runtime of a query or the amount
88 of resources consumed. This may be an async function. The function is
89 give one object as an argument: `{ document, variables, operationName, result }`.
90
91 * **`validationRules`**: Optional additional validation rules queries must
92 satisfy in addition to those defined by the GraphQL spec.
93
94In addition to an object defining each option, options can also be provided as
95a function (or async function) which returns this options object. This function
96is provided the arguments `(request, response, graphQLParams)` and is called
97after the request has been parsed.
98
99The `graphQLParams` is provided as the object `{ query, variables, operationName, raw }`.
100
101```js
102app.use('/graphql', graphqlHTTP(async (request, response, graphQLParams) => ({
103 schema: MyGraphQLSchema,
104 rootValue: await someFunctionToGetRootValue(request)
105 graphiql: true
106})));
107```
108
109
110## HTTP Usage
111
112Once installed at a path, `express-graphql` will accept requests with
113the parameters:
114
115 * **`query`**: A string GraphQL document to be executed.
116
117 * **`variables`**: The runtime values to use for any GraphQL query variables
118 as a JSON object.
119
120 * **`operationName`**: If the provided `query` contains multiple named
121 operations, this specifies which operation should be executed. If not
122 provided, a 400 error will be returned if the `query` contains multiple
123 named operations.
124
125 * **`raw`**: If the `graphiql` option is enabled and the `raw` parameter is
126 provided raw JSON will always be returned instead of GraphiQL even when
127 loaded from a browser.
128
129GraphQL will first look for each parameter in the URL's query-string:
130
131```
132/graphql?query=query+getUser($id:ID){user(id:$id){name}}&variables={"id":"4"}
133```
134
135If not found in the query-string, it will look in the POST request body.
136
137If a previous middleware has already parsed the POST body, the `request.body`
138value will be used. Use [`multer`][] or a similar middleware to add support
139for `multipart/form-data` content, which may be useful for GraphQL mutations
140involving uploading files. See an [example using multer](https://github.com/graphql/express-graphql/blob/304b24b993c8f16fffff8d23b0fa4088e690874b/src/__tests__/http-test.js#L674-L741).
141
142If the POST body has not yet been parsed, express-graphql will interpret it
143depending on the provided *Content-Type* header.
144
145 * **`application/json`**: the POST body will be parsed as a JSON
146 object of parameters.
147
148 * **`application/x-www-form-urlencoded`**: this POST body will be
149 parsed as a url-encoded string of key-value pairs.
150
151 * **`application/graphql`**: The POST body will be parsed as GraphQL
152 query string, which provides the `query` parameter.
153
154
155## Combining with Other Express Middleware
156
157By default, the express request is passed as the GraphQL `context`.
158Since most express middleware operates by adding extra data to the
159request object, this means you can use most express middleware just by inserting it before `graphqlHTTP` is mounted. This covers scenarios such as authenticating the user, handling file uploads, or mounting GraphQL on a dynamic endpoint.
160
161This example uses [`express-session`][] to provide GraphQL with the currently logged-in session.
162
163```js
164const session = require('express-session');
165const graphqlHTTP = require('express-graphql');
166
167const app = express();
168
169app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}));
170
171app.use('/graphql', graphqlHTTP({
172 schema: MySessionAwareGraphQLSchema,
173 graphiql: true
174}));
175```
176
177Then in your type definitions, you can access the request via the third "context" argument in your `resolve` function:
178
179```js
180new GraphQLObjectType({
181 name: 'MyType',
182 fields: {
183 myField: {
184 type: GraphQLString,
185 resolve(parentValue, args, request) {
186 // use `request.session` here
187 }
188 }
189 }
190});
191```
192
193
194## Providing Extensions
195
196The GraphQL response allows for adding additional information in a response to
197a GraphQL query via a field in the response called `"extensions"`. This is added
198by providing an `extensions` function when using `graphqlHTTP`. The function
199must return a JSON-serializable Object.
200
201When called, this is provided an argument which you can use to get information
202about the GraphQL request:
203
204`{ document, variables, operationName, result }`
205
206This example illustrates adding the amount of time consumed by running the
207provided query, which could perhaps be used by your development tools.
208
209```js
210const graphqlHTTP = require('express-graphql');
211
212const app = express();
213
214app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}));
215
216app.use('/graphql', graphqlHTTP(request => {
217 const startTime = Date.now();
218 return {
219 schema: MyGraphQLSchema,
220 graphiql: true,
221 extensions({ document, variables, operationName, result }) {
222 return { runTime: Date.now() - startTime };
223 }
224 };
225}));
226```
227
228When querying this endpoint, it would include this information in the result,
229for example:
230
231```js
232{
233 "data": { ... }
234 "extensions": {
235 "runTime": 135
236 }
237}
238```
239
240
241## Other Exports
242
243**`getGraphQLParams(request: Request): Promise<GraphQLParams>`**
244
245Given an HTTP Request, this returns a Promise for the parameters relevant to
246running a GraphQL request. This function is used internally to handle the
247incoming request, you may use it directly for building other similar services.
248
249```js
250const graphqlHTTP = require('express-graphql');
251
252graphqlHTTP.getGraphQLParams(request).then(params => {
253 // do something...
254})
255```
256
257
258## Debugging Tips
259
260During development, it's useful to get more information from errors, such as
261stack traces. Providing a function to `formatError` enables this:
262
263```js
264formatError: error => ({
265 message: error.message,
266 locations: error.locations,
267 stack: error.stack,
268 path: error.path
269})
270```
271
272
273[`GraphQL.js`]: https://github.com/graphql/graphql-js
274[`formatError`]: https://github.com/graphql/graphql-js/blob/master/src/error/formatError.js
275[GraphiQL]: https://github.com/graphql/graphiql
276[`multer`]: https://github.com/expressjs/multer
277[`express-session`]: https://github.com/expressjs/session