1 | ;
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 |
|
7 | 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; }; /**
|
8 | * Copyright (c) 2015-present, Facebook, Inc.
|
9 | * All rights reserved.
|
10 | *
|
11 | * This source code is licensed under the BSD-style license found in the
|
12 | * LICENSE file in the root directory of this source tree. An additional grant
|
13 | * of patent rights can be found in the PATENTS file in the same directory.
|
14 | *
|
15 | * strict
|
16 | */
|
17 |
|
18 | exports.parseBody = parseBody;
|
19 |
|
20 | var _contentType = require('content-type');
|
21 |
|
22 | var _contentType2 = _interopRequireDefault(_contentType);
|
23 |
|
24 | var _rawBody = require('raw-body');
|
25 |
|
26 | var _rawBody2 = _interopRequireDefault(_rawBody);
|
27 |
|
28 | var _httpErrors = require('http-errors');
|
29 |
|
30 | var _httpErrors2 = _interopRequireDefault(_httpErrors);
|
31 |
|
32 | var _querystring = require('querystring');
|
33 |
|
34 | var _querystring2 = _interopRequireDefault(_querystring);
|
35 |
|
36 | var _zlib = require('zlib');
|
37 |
|
38 | var _zlib2 = _interopRequireDefault(_zlib);
|
39 |
|
40 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
41 |
|
42 | /**
|
43 | * Provided a "Request" provided by express or connect (typically a node style
|
44 | * HTTPClientRequest), Promise the body data contained.
|
45 | */
|
46 | function parseBody(req) {
|
47 | return new Promise(function (resolve, reject) {
|
48 | var body = req.body;
|
49 |
|
50 | // If express has already parsed a body as a keyed object, use it.
|
51 | if ((typeof body === 'undefined' ? 'undefined' : _typeof(body)) === 'object' && !(body instanceof Buffer)) {
|
52 | return resolve(body);
|
53 | }
|
54 |
|
55 | // Skip requests without content types.
|
56 | if (req.headers['content-type'] === undefined) {
|
57 | return resolve({});
|
58 | }
|
59 |
|
60 | var typeInfo = _contentType2.default.parse(req);
|
61 |
|
62 | // If express has already parsed a body as a string, and the content-type
|
63 | // was application/graphql, parse the string body.
|
64 | if (typeof body === 'string' && typeInfo.type === 'application/graphql') {
|
65 | return resolve(graphqlParser(body));
|
66 | }
|
67 |
|
68 | // Already parsed body we didn't recognise? Parse nothing.
|
69 | if (body) {
|
70 | return resolve({});
|
71 | }
|
72 |
|
73 | // Use the correct body parser based on Content-Type header.
|
74 | switch (typeInfo.type) {
|
75 | case 'application/graphql':
|
76 | return read(req, typeInfo, graphqlParser, resolve, reject);
|
77 | case 'application/json':
|
78 | return read(req, typeInfo, jsonEncodedParser, resolve, reject);
|
79 | case 'application/x-www-form-urlencoded':
|
80 | return read(req, typeInfo, urlEncodedParser, resolve, reject);
|
81 | }
|
82 |
|
83 | // If no Content-Type header matches, parse nothing.
|
84 | return resolve({});
|
85 | });
|
86 | }
|
87 |
|
88 | function jsonEncodedParser(body) {
|
89 | if (jsonObjRegex.test(body)) {
|
90 | /* eslint-disable no-empty */
|
91 | try {
|
92 | return JSON.parse(body);
|
93 | } catch (error) {}
|
94 | // Do nothing
|
95 |
|
96 | /* eslint-enable no-empty */
|
97 | }
|
98 | throw (0, _httpErrors2.default)(400, 'POST body sent invalid JSON.');
|
99 | }
|
100 |
|
101 | function urlEncodedParser(body) {
|
102 | return _querystring2.default.parse(body);
|
103 | }
|
104 |
|
105 | function graphqlParser(body) {
|
106 | return { query: body };
|
107 | }
|
108 |
|
109 | /**
|
110 | * RegExp to match an Object-opening brace "{" as the first non-space
|
111 | * in a string. Allowed whitespace is defined in RFC 7159:
|
112 | *
|
113 | * x20 Space
|
114 | * x09 Horizontal tab
|
115 | * x0A Line feed or New line
|
116 | * x0D Carriage return
|
117 | */
|
118 | var jsonObjRegex = /^[\x20\x09\x0a\x0d]*\{/;
|
119 |
|
120 | // Read and parse a request body.
|
121 | function read(req, typeInfo, parseFn, resolve, reject) {
|
122 | var charset = (typeInfo.parameters.charset || 'utf-8').toLowerCase();
|
123 |
|
124 | // Assert charset encoding per JSON RFC 7159 sec 8.1
|
125 | if (charset.slice(0, 4) !== 'utf-') {
|
126 | throw (0, _httpErrors2.default)(415, 'Unsupported charset "' + charset.toUpperCase() + '".');
|
127 | }
|
128 |
|
129 | // Get content-encoding (e.g. gzip)
|
130 | var contentEncoding = req.headers['content-encoding'];
|
131 | var encoding = typeof contentEncoding === 'string' ? contentEncoding.toLowerCase() : 'identity';
|
132 | var length = encoding === 'identity' ? req.headers['content-length'] : null;
|
133 | var limit = 100 * 1024; // 100kb
|
134 | var stream = decompressed(req, encoding);
|
135 |
|
136 | // Read body from stream.
|
137 | (0, _rawBody2.default)(stream, { encoding: charset, length: length, limit: limit }, function (err, body) {
|
138 | if (err) {
|
139 | return reject(err.type === 'encoding.unsupported' ? (0, _httpErrors2.default)(415, 'Unsupported charset "' + charset.toUpperCase() + '".') : (0, _httpErrors2.default)(400, 'Invalid body: ' + err.message + '.'));
|
140 | }
|
141 |
|
142 | try {
|
143 | // Decode and parse body.
|
144 | return resolve(parseFn(body));
|
145 | } catch (error) {
|
146 | return reject(error);
|
147 | }
|
148 | });
|
149 | }
|
150 |
|
151 | // Return a decompressed stream, given an encoding.
|
152 | function decompressed(req, encoding) {
|
153 | switch (encoding) {
|
154 | case 'identity':
|
155 | return req;
|
156 | case 'deflate':
|
157 | return req.pipe(_zlib2.default.createInflate());
|
158 | case 'gzip':
|
159 | return req.pipe(_zlib2.default.createGunzip());
|
160 | }
|
161 | throw (0, _httpErrors2.default)(415, 'Unsupported content-encoding "' + encoding + '".');
|
162 | } |
\ | No newline at end of file |