Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

req.body gets populated to empty object even when it shouldn't #350

Closed
mkartashov opened this issue Feb 19, 2019 · 3 comments
Closed

req.body gets populated to empty object even when it shouldn't #350

mkartashov opened this issue Feb 19, 2019 · 3 comments

Comments

@mkartashov
Copy link

Problem

https://github.com/expressjs/body-parser/blob/master/lib/types/json.js#L99-L121

(seems to echo #146 ?)

Expected behaviour

If the body was not parsed by some other parser before bodyParser.json, and if the current request is NOT to be parsed with current parser, I expect the req.body to be undefined.

Current behaviour

The shouldParse check happens after the body has been populated with an empty object, thus polluting the req.

My usecase

Currently I am using express as a backend proxy for my react application.

The vast majority of my requests are fetch GET with missing content-type and with accept: */*. There are some user-profile requests (GET /user, for example, that expects json in return).

But two of my requests are very different. One is POST /save-something, which sends over content-type: application/json, and the other one is POST /upload-a-file-to-another-system with content-type: application/binary and content-transfer-encoding: binary.

The server serving as a proxy SHOULD NOT look into the request to understand how to parse/reparse it. So, my expected behaviour would be for all requests that were not parsed by JSON to leave the req.body = undefined, so that I can make a general check on req.is("json") or req.is("binary"), should I need some custom behaviour.

Example

I decided I could write up a simple script to illustrate the point, if you wish. Mostly it contains logs on the console :D

package.json
{
  "name": "express-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.16.4"
  }
}
index.js
const http = require("http");
const express = require("express");

const PORT = Number(process.env.PORT) || 8082;
const DELAY = Number(process.env.DELAY) || 1000;

const app = express();

function shouldParse(req){
  console.log("shouldParse invoked. Before parsing: body: ", req.body);
  return req.get("content-type") === "application/json";
}

function call(method, path, body, isJson, expectedBody){
  const req = http.request({
    host: "localhost",
    port: PORT,
    method: method,
    path: path,
    headers: {
      "content-type": isJson ? "application/json" : "random/content",
      "expected-body": expectedBody,
    }
  }, (res) => {
    var data = "";
    res.on("data", (ch) => {data += ch});
    res.on("end", () => {});
  });

  return () => {
    if(body){
      req.write(body);
    }
    req.end();
  };
}

app.use(express.json({type: shouldParse }));

app.use((req, res) => {
  console.log(req.method + " " + req.path + ", content: " + req.headers["content-type"]);
  console.log("body: " + JSON.stringify(req.body));
  console.log("expected body: " + req.headers["expected-body"]);
  console.log("");
});


const server = http.createServer(app);
const jsonBody = '{"egg": ["bacon", "spam"]}';
const calls = [
  call("GET", "/no-body", undefined, true, "undefined"),
  call("GET", "/no-body", undefined, false, "undefined"),
  call("POST", "/no-body", undefined, true, "undefined"),
  call("POST", "/no-body", undefined, false, "undefined",),
  call("POST", "/text-body", "egg, bacon, spam", false, "undefined"),
  call("POST", "/json-body", jsonBody, true, jsonBody),
  () => {
    server.close();
    console.log("done.");
    process.exit(0);
  }
];

var counter = 1;
calls.forEach((func) => {
  setTimeout(func, counter * DELAY);
  counter++;
});


server.listen(PORT, () => {
  console.log("listening on " + PORT + "...\n");
});

Output

$ npm install && npm start
npm WARN express-example@1.0.0 No description
npm WARN express-example@1.0.0 No repository field.

added 51 packages in 1.384s

> express-example@1.0.0 start /home/mkartashov/express-example
> node index.js

listening on 8082...

GET /no-body, content: application/json
body: {}
expected body: undefined

GET /no-body, content: random/content
body: {}
expected body: undefined

shouldParse invoked. Before parsing: body:  {}
POST /no-body, content: application/json
body: {}
expected body: undefined

shouldParse invoked. Before parsing: body:  {}
POST /no-body, content: random/content
body: {}
expected body: undefined

shouldParse invoked. Before parsing: body:  {}
POST /text-body, content: random/content
body: {}
expected body: undefined

shouldParse invoked. Before parsing: body:  {}
POST /json-body, content: application/json
body: {"egg":["bacon","spam"]}
expected body: {"egg": ["bacon", "spam"]}

done.
@dougwilson
Copy link
Contributor

Thank you for the detailed report! I agree this should change, which is why it has on the 2.0 branch.

Duplicate of #123

That issue has a comment of how to workaround the 1.0 behavior.

@mkartashov
Copy link
Author

mkartashov commented Feb 19, 2019

@dougwilson I saw mentions of the branch 2.0, but somehow it didn't cross my mind that it was the body-parser repo (whereas the express itself is v4 already 😆 ) ah well, my bad.

Thank you for work-around.

@dougwilson
Copy link
Contributor

No problem. In fact, I will plan to work to rebase that branch today and release it has a rc or something to npm to get it rolling as a real release 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants