tl;dr; No need install or require body-parser and it's important to send the right content-type header.
I know Express has great documentation but I'm still confused about how to receive JSON and/or how to test it from curl
. A great deal of confusion comes from the fact that, I think, body-parser
used to be a third-party library you had to install yourself to add it to your Express app. You don't. It now gets installed by installing express
. E.g.
▶ yarn init -y ▶ yarn add express ▶ ls node_modules/body-parser HISTORY.md LICENSE README.md index.js lib package.json
Let's work backward. This is how you set up the Express handler:
const express = require("express"); // v4.17.x as of Apr 2020
const app = express();
app.use(express.json());
app.post("/echo", (req, res) => {
res.json(req.body);
});
app.listen(5000);
And, this is how you test it:
▶ curl -XPOST -d '{"foo": "bar"}' -H 'content-type: application/json' localhost:5000/echo {"foo":"bar"}%
That's it. No need to require("body-parser")
or anything like that. And make sure you're sending the content-type: application/json
in the curl
command.
Things that can go wrong
I kept fumbling around on StackOverflow questions and rummaging the Express documentation until I figured out what mistake I kept doing. So, here's a variant of the handler above, but much more verbose:
app.post("/echo", (req, res) => {
if (req.body === undefined) {
throw new Error("express.json middleware not installed");
}
if (!Object.keys(req.body).length) {
// E.g curl -v -XPOST http://localhost:5000/echo
if (!req.get("content-Type")) {
return res.status(400).send("no content-type header\n");
}
// E.g. curl -v -XPOST -d '{"foo": "bar"}' http://localhost:5000/echo
if (!req.get("content-Type").includes("application/json")) {
return res.status(400).send("content-type not application/json\n");
}
// E.g. curl -XPOST -H 'content-type:application/json' http://localhost:5000/echo
return res.status(400).send("no data payload included\n");
}
// At this point 'req.body' is *something*.
// For example, you might want to `console.log(req.body.foo)`
res.json(req.body);
});
How you treat these things is up to you. For example, an empty JSON data might be OK in your application.
I.e. perhaps curl -XPOST -d '{}' -H 'content-type:application/json' http://localhost:5000/echo
might be fine.
An important option
express.json()
is a piece of middleware. By default, it has a simple mechanism for bothering to do put .body
into the request object. The default configuration is as if you'd typed:
app.use(express.json({
type: 'application/json',
}));
(it's actually a bit more complicated than that)
If you're confident that you'll always be sending JSON to this handler, and you don't want to have to force clients to have to specify the application/json
Content-Type you can change this to:
app.use(express.json({ type: '*/*', }));
Now you'll find that curl -XPOST -d '{"foo": "bar3"}' localhost:5000/
will work fine.
Instead of curl
, let's fetch
This code works the same with node-fetch
or browser Fetch API.
fetch("http://localhost:5000/echo", {
method: "post",
body: JSON.stringify({ foo: "bar" }),
headers: { "Content-Type": "application/json" },
})
.then((res) => res.json())
.then((json) => console.log(json));
Comments
Thank you very much bro!!!!
Thank you so much! This is exactly what I've been seraching for, but somehow did not manage to find anywhere else.