UNPKG

10.2 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/src/execute.js`](https://github.com/graphql/graphql-js/blob/master/src/execution/execute.js#L121).
73
74 * **`context`**: A value to pass as the `context` to the `graphql()`
75 function from [`GraphQL.js/src/execute.js`](https://github.com/graphql/graphql-js/blob/master/src/execution/execute.js#L122). 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## Additional Validation Rules
242
243GraphQL's [validation phase](https://facebook.github.io/graphql/#sec-Validation) checks the query to ensure that it can be sucessfully executed against the schema. The `validationRules` option allows for additional rules to be run during this phase. Rules are applied to each node in an AST representing the query using the Visitor pattern.
244
245A validation rule is a function which returns a visitor for one or more node Types. Below is an example of a validation preventing the specific fieldname `metadata` from being queried. For more examples see the [`specifiedRules`](https://github.com/graphql/graphql-js/tree/master/src/validation/rules) in the [graphql-js](https://github.com/graphql/graphql-js) package.
246
247```js
248import { GraphQLError } from 'graphql';
249
250export function DisallowMetadataQueries(context) {
251 return {
252 Field(node) {
253 const fieldName = node.name.value;
254
255 if (fieldName === "metadata") {
256 context.reportError(
257 new GraphQLError(
258 `Validation: Requesting the field ${fieldName} is not allowed`,
259 ),
260 );
261 }
262 }
263 };
264}
265```
266
267## Other Exports
268
269**`getGraphQLParams(request: Request): Promise<GraphQLParams>`**
270
271Given an HTTP Request, this returns a Promise for the parameters relevant to
272running a GraphQL request. This function is used internally to handle the
273incoming request, you may use it directly for building other similar services.
274
275```js
276const graphqlHTTP = require('express-graphql');
277
278graphqlHTTP.getGraphQLParams(request).then(params => {
279 // do something...
280})
281```
282
283
284## Debugging Tips
285
286During development, it's useful to get more information from errors, such as
287stack traces. Providing a function to `formatError` enables this:
288
289```js
290formatError: error => ({
291 message: error.message,
292 locations: error.locations,
293 stack: error.stack,
294 path: error.path
295})
296```
297
298
299[`GraphQL.js`]: https://github.com/graphql/graphql-js
300[`formatError`]: https://github.com/graphql/graphql-js/blob/master/src/error/formatError.js
301[GraphiQL]: https://github.com/graphql/graphiql
302[`multer`]: https://github.com/expressjs/multer
303[`express-session`]: https://github.com/expressjs/session