`type` parameter is ignored
carlpaten opened this issue · comments
Cross-post from Stack Overflow
I have inbound requests with Content-Type: application/vnd.surveymonkey.response.v1+json
. I'm trying to use body-parser
on them. The documentation for body-parser
's json
factory method states:
Returns middleware that only parses json and only looks at requests where the Content-Type header matches the type option.
[...]
The type option is used to determine what media type the middleware will parse. This option can be a string, array of strings, or a function. If not a function, type option is passed directly to the type-is library and this can be an extension name (like json), a mime type (like application/json), or a mime type with a wildcard (like / or */json). If a function, the type option is called as fn(req) and the request is parsed if it returns a truthy value. Defaults to application/json.
I tried a variety of parameters, but regardless of whatever I put the parser middleware continues to accept application/json
while rejecting application/vnd.surveymonkey.response.v1+json
. In fact, when I put a console.debug
statement in the type
function, it never does print, so it looks like the type
argument is being ignored entirely.
Am I doing anything wrong? what do I need to do for body-parser
to respect the type
parameter?
import * as bodyParser from 'body-parser';
import * as express from 'express';
const app = express();
app.use(
bodyParser.json({
// type: 'application/vnd.surveymonkey.response.v1+json', // doesn't work
// type: ['application/vnd.surveymonkey.response.v1+json'], // doesn't work
// type: ['application/*'], // doesn't work
// type: (req) => /application\/(.+\+)?json/.test(req.headers['Content-Type'] as string), // doesn't work
type: (req) => console.debug('Hello world!'),
})
);
app.post(`/`, (req, res) => {
console.log('Request: ', req.body);
res.status(200).send();
});
Hi @LilRed I'm sorry you are having problems. The code sample you provided works just like you expected, though, so my only guess as to why you are not getting the results you are expecting is maybe either (a) what you are sending to the server is not what you think you are or (b) the server you are sending to is not actually running the code you think it is. I have no other guesses, unfortunately :(
Here is an example session to validate the code you posted above:
$ npm i express body-parser
+ express@4.17.1
+ body-parser@1.19.0
added 50 packages from 37 contributors and audited 51 packages in 3.03s
found 0 vulnerabilities
$ cat app.js
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
app.use(
bodyParser.json({
type: 'application/vnd.surveymonkey.response.v1+json'
})
);
app.post(`/`, (req, res) => {
console.log('Request: ', req.body);
res.status(200).send();
});
app.listen(3000);
$ node app.js &
[1] 1801
$ curl -i http://localhost:3000/ -d'{"foo":"bar"}' -H'Content-Type: application/json'
Request: {}
HTTP/1.1 200 OK
X-Powered-By: Express
Date: Wed, 25 Nov 2020 15:19:15 GMT
Connection: keep-alive
Content-Length: 0
$ curl -i http://localhost:3000/ -d'{"foo":"bar"}' -H'Content-Type: application/vnd.surveymonkey.response.v1+json'
Request: { foo: 'bar' }
HTTP/1.1 200 OK
X-Powered-By: Express
Date: Wed, 25 Nov 2020 15:19:37 GMT
Connection: keep-alive
Content-Length: 0
Hi @dougwilson! Thank you for your help. I apologize for not attempting a minimal repro, as I would have found what you have: this is indeed the correct use of body-parser
, and the problem is elsewhere.
It turns out that my issue is with Google's Firebase Functions runtime, which already uses body-parser
and hard-codes the options. When a request goes through the system, it first goes through the instance of body-parser
defined by the runtime, and it is marked as already parsed by setting the _body
field. Then the request goes through the instance of body-parser
that I've defined in my code; that instance is completely ignored.
From glancing at the code I'm guessing that you intentionally do not support multiple layers of body-parser
. So for now I'm going to implement an ugly hack: if the content type is application/vnd.surveymonkey.response.v1+json
, unset the _body
field, and re-run body-parser
.
Thank you again for your time, I really appreciate it.
From glancing at the code I'm guessing that you intentionally do not support multiple layers of body-parser.
This is not a decision we made; Node.js itself only allows you to read the body a single time. If we didn't add that guard, the second instance of body-parser
would just hang until the request times out, as there is no longer any data emitted from the Node.js request object.