UNPKG

10.3 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#L119).
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#L120). 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 given one object as an argument: `{ document, variables, operationName, result, context }`.
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, context }`
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
216const extensions = ({ document, variables, operationName, result, context }) => {
217 return {
218 runTime: Date.now() - context.startTime
219 }
220}
221
222app.use('/graphql', graphqlHTTP(request => {
223 return {
224 schema: MyGraphQLSchema,
225 context: { startTime: Date.now() },
226 graphiql: true,
227 extensions
228 };
229}));
230```
231
232When querying this endpoint, it would include this information in the result,
233for example:
234
235```js
236{
237 "data": { ... }
238 "extensions": {
239 "runTime": 135
240 }
241}
242```
243
244
245## Additional Validation Rules
246
247GraphQL's [validation phase](https://facebook.github.io/graphql/#sec-Validation) checks the query to ensure that it can be successfully 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.
248
249A 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.
250
251```js
252import { GraphQLError } from 'graphql';
253
254export function DisallowMetadataQueries(context) {
255 return {
256 Field(node) {
257 const fieldName = node.name.value;
258
259 if (fieldName === "metadata") {
260 context.reportError(
261 new GraphQLError(
262 `Validation: Requesting the field ${fieldName} is not allowed`,
263 ),
264 );
265 }
266 }
267 };
268}
269```
270
271## Other Exports
272
273**`getGraphQLParams(request: Request): Promise<GraphQLParams>`**
274
275Given an HTTP Request, this returns a Promise for the parameters relevant to
276running a GraphQL request. This function is used internally to handle the
277incoming request, you may use it directly for building other similar services.
278
279```js
280const graphqlHTTP = require('express-graphql');
281
282graphqlHTTP.getGraphQLParams(request).then(params => {
283 // do something...
284})
285```
286
287
288## Debugging Tips
289
290During development, it's useful to get more information from errors, such as
291stack traces. Providing a function to `formatError` enables this:
292
293```js
294formatError: error => ({
295 message: error.message,
296 locations: error.locations,
297 stack: error.stack ? error.stack.split('\n') : [],
298 path: error.path
299})
300```
301
302
303[`GraphQL.js`]: https://github.com/graphql/graphql-js
304[`formatError`]: https://github.com/graphql/graphql-js/blob/master/src/error/formatError.js
305[GraphiQL]: https://github.com/graphql/graphiql
306[`multer`]: https://github.com/expressjs/multer
307[`express-session`]: https://github.com/expressjs/session