1 | 'use strict';
|
2 |
|
3 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | var _accepts = require('accepts');
|
14 |
|
15 | var _accepts2 = _interopRequireDefault(_accepts);
|
16 |
|
17 | var _graphql = require('graphql');
|
18 |
|
19 | var _httpErrors = require('http-errors');
|
20 |
|
21 | var _httpErrors2 = _interopRequireDefault(_httpErrors);
|
22 |
|
23 | var _url = require('url');
|
24 |
|
25 | var _url2 = _interopRequireDefault(_url);
|
26 |
|
27 | var _parseBody = require('./parseBody');
|
28 |
|
29 | var _renderGraphiQL = require('./renderGraphiQL');
|
30 |
|
31 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 | module.exports = graphqlHTTP;
|
52 | function graphqlHTTP(options) {
|
53 | if (!options) {
|
54 | throw new Error('GraphQL middleware requires options.');
|
55 | }
|
56 |
|
57 | return function (request, response) {
|
58 |
|
59 |
|
60 | var params = void 0;
|
61 | var pretty = void 0;
|
62 | var formatErrorFn = void 0;
|
63 | var extensionsFn = void 0;
|
64 | var showGraphiQL = void 0;
|
65 | var query = void 0;
|
66 |
|
67 | var documentAST = void 0;
|
68 | var variables = void 0;
|
69 | var operationName = void 0;
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 | return getGraphQLParams(request).then(function (graphQLParams) {
|
76 | params = graphQLParams;
|
77 |
|
78 | return new Promise(function (resolve) {
|
79 | return resolve(typeof options === 'function' ? options(request, response, params) : options);
|
80 | });
|
81 | }).then(function (optionsData) {
|
82 |
|
83 | if (!optionsData || (typeof optionsData === 'undefined' ? 'undefined' : _typeof(optionsData)) !== 'object') {
|
84 | throw new Error('GraphQL middleware option function must return an options object ' + 'or a promise which will be resolved to an options object.');
|
85 | }
|
86 |
|
87 |
|
88 | if (!optionsData.schema) {
|
89 | throw new Error('GraphQL middleware options must contain a schema.');
|
90 | }
|
91 |
|
92 |
|
93 | var schema = optionsData.schema;
|
94 | var context = optionsData.context || request;
|
95 | var rootValue = optionsData.rootValue;
|
96 | var graphiql = optionsData.graphiql;
|
97 | pretty = optionsData.pretty;
|
98 | formatErrorFn = optionsData.formatError;
|
99 | extensionsFn = optionsData.extensions;
|
100 |
|
101 | var validationRules = _graphql.specifiedRules;
|
102 | if (optionsData.validationRules) {
|
103 | validationRules = validationRules.concat(optionsData.validationRules);
|
104 | }
|
105 |
|
106 |
|
107 | if (request.method !== 'GET' && request.method !== 'POST') {
|
108 | response.setHeader('Allow', 'GET, POST');
|
109 | throw (0, _httpErrors2.default)(405, 'GraphQL only supports GET and POST requests.');
|
110 | }
|
111 |
|
112 |
|
113 | query = params.query;
|
114 | variables = params.variables;
|
115 | operationName = params.operationName;
|
116 | showGraphiQL = graphiql && canDisplayGraphiQL(request, params);
|
117 |
|
118 |
|
119 |
|
120 | if (!query) {
|
121 | if (showGraphiQL) {
|
122 | return null;
|
123 | }
|
124 | throw (0, _httpErrors2.default)(400, 'Must provide query string.');
|
125 | }
|
126 |
|
127 |
|
128 | var source = new _graphql.Source(query, 'GraphQL request');
|
129 |
|
130 |
|
131 | try {
|
132 | documentAST = (0, _graphql.parse)(source);
|
133 | } catch (syntaxError) {
|
134 |
|
135 | response.statusCode = 400;
|
136 | return { errors: [syntaxError] };
|
137 | }
|
138 |
|
139 |
|
140 | var validationErrors = (0, _graphql.validate)(schema, documentAST, validationRules);
|
141 | if (validationErrors.length > 0) {
|
142 |
|
143 | response.statusCode = 400;
|
144 | return { errors: validationErrors };
|
145 | }
|
146 |
|
147 |
|
148 | if (request.method === 'GET') {
|
149 |
|
150 | var operationAST = (0, _graphql.getOperationAST)(documentAST, operationName);
|
151 | if (operationAST && operationAST.operation !== 'query') {
|
152 |
|
153 |
|
154 |
|
155 | if (showGraphiQL) {
|
156 | return null;
|
157 | }
|
158 |
|
159 |
|
160 | response.setHeader('Allow', 'POST');
|
161 | throw (0, _httpErrors2.default)(405, 'Can only perform a ' + operationAST.operation + ' operation ' + 'from a POST request.');
|
162 | }
|
163 | }
|
164 |
|
165 | try {
|
166 | return (0, _graphql.execute)(schema, documentAST, rootValue, context, variables, operationName);
|
167 | } catch (contextError) {
|
168 |
|
169 | response.statusCode = 400;
|
170 | return { errors: [contextError] };
|
171 | }
|
172 | }).then(function (result) {
|
173 |
|
174 |
|
175 | if (result && extensionsFn) {
|
176 | return Promise.resolve(extensionsFn({
|
177 | document: documentAST,
|
178 | variables: variables,
|
179 | operationName: operationName,
|
180 | result: result
|
181 | })).then(function (extensions) {
|
182 | if (extensions && (typeof extensions === 'undefined' ? 'undefined' : _typeof(extensions)) === 'object') {
|
183 | result.extensions = extensions;
|
184 | }
|
185 | return result;
|
186 | });
|
187 | }
|
188 | return result;
|
189 | }).catch(function (error) {
|
190 |
|
191 | response.statusCode = error.status || 500;
|
192 | return { errors: [error] };
|
193 | }).then(function (result) {
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 | if (result && result.data === null) {
|
200 | response.statusCode = 500;
|
201 | }
|
202 |
|
203 | if (result && result.errors) {
|
204 | result.errors = result.errors.map(formatErrorFn || _graphql.formatError);
|
205 | }
|
206 |
|
207 |
|
208 | if (showGraphiQL) {
|
209 | var payload = (0, _renderGraphiQL.renderGraphiQL)({
|
210 | query: query,
|
211 | variables: variables,
|
212 | operationName: operationName,
|
213 | result: result
|
214 | });
|
215 | return sendResponse(response, 'text/html', payload);
|
216 | }
|
217 |
|
218 |
|
219 |
|
220 | if (!result) {
|
221 | throw (0, _httpErrors2.default)(500, 'Internal Error');
|
222 | }
|
223 |
|
224 |
|
225 |
|
226 |
|
227 | if (!pretty && typeof response.json === 'function') {
|
228 | response.json(result);
|
229 | } else {
|
230 | var _payload = JSON.stringify(result, null, pretty ? 2 : 0);
|
231 | sendResponse(response, 'application/json', _payload);
|
232 | }
|
233 | });
|
234 | };
|
235 | }
|
236 |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 | module.exports.getGraphQLParams = getGraphQLParams;
|
242 | function getGraphQLParams(request) {
|
243 | return (0, _parseBody.parseBody)(request).then(function (bodyData) {
|
244 | var urlData = request.url && _url2.default.parse(request.url, true).query || {};
|
245 | return parseGraphQLParams(urlData, bodyData);
|
246 | });
|
247 | }
|
248 |
|
249 |
|
250 |
|
251 |
|
252 | function parseGraphQLParams(urlData, bodyData) {
|
253 |
|
254 | var query = urlData.query || bodyData.query;
|
255 | if (typeof query !== 'string') {
|
256 | query = null;
|
257 | }
|
258 |
|
259 |
|
260 | var variables = urlData.variables || bodyData.variables;
|
261 | if (variables && typeof variables === 'string') {
|
262 | try {
|
263 | variables = JSON.parse(variables);
|
264 | } catch (error) {
|
265 | throw (0, _httpErrors2.default)(400, 'Variables are invalid JSON.');
|
266 | }
|
267 | } else if ((typeof variables === 'undefined' ? 'undefined' : _typeof(variables)) !== 'object') {
|
268 | variables = null;
|
269 | }
|
270 |
|
271 |
|
272 | var operationName = urlData.operationName || bodyData.operationName;
|
273 | if (typeof operationName !== 'string') {
|
274 | operationName = null;
|
275 | }
|
276 |
|
277 | var raw = urlData.raw !== undefined || bodyData.raw !== undefined;
|
278 |
|
279 | return { query: query, variables: variables, operationName: operationName, raw: raw };
|
280 | }
|
281 |
|
282 |
|
283 |
|
284 |
|
285 | function canDisplayGraphiQL(request, params) {
|
286 |
|
287 |
|
288 |
|
289 | return !params.raw && (0, _accepts2.default)(request).types(['json', 'html']) === 'html';
|
290 | }
|
291 |
|
292 |
|
293 |
|
294 |
|
295 | function sendResponse(response, type, data) {
|
296 | var chunk = new Buffer(data, 'utf8');
|
297 | response.setHeader('Content-Type', type + '; charset=utf-8');
|
298 | response.setHeader('Content-Length', String(chunk.length));
|
299 | response.end(chunk);
|
300 | } |
\ | No newline at end of file |