From 162d0c69998de4b7d8dc0420494fea5b3f6b6a1f Mon Sep 17 00:00:00 2001 From: Matt Myers Date: Sat, 18 Nov 2017 10:15:05 -0700 Subject: [PATCH] New formatResponse option allowing more customized responses. --- README.md | 9 +++++++-- src/index.js | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 174d635c..ecf204da 100644 --- a/README.md +++ b/README.md @@ -75,11 +75,16 @@ The `graphqlHTTP` function accepts the following options: 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 `request` object is passed as the context. - * **`pretty`**: If `true`, any JSON response will be pretty-printed. + * **`pretty`**: If `true`, any JSON response will be pretty-printed. When set to `true`, this will override `formatResponse` option. * **`formatError`**: An optional function which will be used to format any errors produced by fulfilling a GraphQL operation. If no function is - provided, GraphQL's default spec-compliant [`formatError`][] function will be used. + provided, GraphQL's default spec-compliant [`formatError`][] function will be used.π + + * **`formatResponse`**: An optional string value to customize the response format. Valid options are: + `result`, `pretty`, or `json`. The default value is `json`. When specifying `result`, the result data will + be returned instead of output. Otherwise both `json` and `pretty` will output the appropriate + response as plain or pretty json respectively. * **`extensions`**: An optional function for adding additional metadata to the GraphQL response as a key-value object. The result will be added to diff --git a/src/index.js b/src/index.js index 0ac3a0e5..337806c7 100644 --- a/src/index.js +++ b/src/index.js @@ -63,6 +63,13 @@ export type OptionsData = { */ pretty?: ?boolean, + /** + * A string to configure the format of the output. + * Options: result, pretty, or json + * Defaults to: json + */ + formatResponse?: ?string, + /** * An optional function which will be used to format any errors produced by * fulfilling a GraphQL operation. If no function is provided, GraphQL's @@ -119,7 +126,7 @@ export type RequestInfo = { result: ?mixed, }; -type Middleware = (request: $Request, response: $Response) => Promise; +type Middleware = (request: $Request, response: $Response) => Promise; /** * Middleware for express; takes an options object or function as input to @@ -135,11 +142,11 @@ function graphqlHTTP(options: Options): Middleware { // Higher scoped variables are referred to at various stages in the // asynchronous state machine below. let params; - let pretty; let formatErrorFn; let extensionsFn; let showGraphiQL; let query; + let formatResponse; let documentAST; let variables; @@ -176,9 +183,15 @@ function graphqlHTTP(options: Options): Middleware { const context = optionsData.context || request; const rootValue = optionsData.rootValue; const graphiql = optionsData.graphiql; - pretty = optionsData.pretty; + formatErrorFn = optionsData.formatError; extensionsFn = optionsData.extensions; + formatResponse = optionsData.formatResponse || 'json'; + + // Backwards compatability + if (optionsData.pretty === true) { + formatResponse = 'pretty'; + } let validationRules = specifiedRules; if (optionsData.validationRules) { @@ -321,15 +334,19 @@ function graphqlHTTP(options: Options): Middleware { throw httpError(500, 'Internal Error'); } - // If "pretty" JSON isn't requested, and the server provides a - // response.json method (express), use that directly. - // Otherwise use the simplified sendResponse method. - if (!pretty && typeof response.json === 'function') { - response.json(result); - } else { - const payload = JSON.stringify(result, null, pretty ? 2 : 0); - sendResponse(response, 'application/json', payload); + // Return the correct formatted response + if (formatResponse === 'result') { + return Promise.resolve(result); + } + if (formatResponse === 'pretty') { + return sendResponse(response, 'application/json', JSON.stringify(result, null, 2)); } + if (typeof response.json === 'function') { + return response.json(result); + } + + // Default json response + return sendResponse(response, 'application/json', JSON.stringify(result, null, 0)); }); }; }