Friday, 8 November, 2019 UTC


Summary

Introduction

In this brief article we'll be going over how to extract information from a POST body in Express.js. The HTTP protocol provides a number of ways to pass information from a client to a server, with POST bodies being the most flexible and most commonly used method to send data via HTTP.
Another way, which is typically used for different use-cases, is to convey information using query strings or URL parameters. For more info, check out how to get query strings and parameters in Express.js.
For this article I assume you have some experience with Node.js and creating simple Express.js servers.

Sending POST Data in HTTP

Data can be sent via an HTTP POST call for many reasons, with some of the most common being via an HTML <form> or an API request. The data can take on a few different forms, with the most common being:
  • application/x-www-form-urlencoded: Data in this encoding is formatted like a query string you'd see in a URL, with key-value paris being separated by & characters. For example: foo=bar&abc=123&stack=abuse. This is the default encoding.
  • multipart/form-data: This encoding is typically used for sending files. In short, each key-value is sent in the same request, but different "parts", which are separated by "boundaries" and include more meta-data.
  • text/plain: This data is just sent as unstructured plain text, and typically is not used.
A raw HTTP POST request with the application/x-www-form-urlencoded encoding might look something like this:
POST /signup HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 53

username=scott&password=secret&website=stackabuse.com

Extracting POST Data

Before we can get started accessing POST data right away, we need to properly configure our Express app. This configuration needs to be done since not all web app servers need body parsing, and what body parsing is enabled depends on your application.
To set this up, we'll be using the body-parser package, which can handle many forms of data. This package is a middleware that intercepts the raw body and parses it in to a form that your application code can easily use.
// index.js
const express = require('express');
const bodyParser = require('body-parser');

const app = express();
app.use(bodyParser.urlencoded({ extended: true }));

app.post('/post-test', (req, res) => {
    console.log('Got body:', req.body);
    res.sendStatus(200);
});

app.listen(8080, () => console.log(`Started server at http://localhost:8080!`));
Notice how we call app.use(...) before defining our route. The order here matters. This will ensure that the body-parser will run before our route, which ensures that our route can then access the parsed HTTP POST body.
To test this, we'll first start the Express app and then use the curl utility in a different console window:
$ curl -d "username=scott&password=secret&website=stackabuse.com" -X POST http://localhost:8080/post-test
OK
$ node index.js
Started server at http://localhost:8080!
Got body: { username: 'scott',
  password: 'secret',
  website: 'stackabuse.com' }
Here you can see that the query string data was parsed in to a JavaScript object that we can easily access.
Another important thing to note is our use of the extended option when calling bodyParser.urlencoded. Using the extended option tells body-parser to use the qs library to parse the URL-encoded data. This allows for things like objects and arrays to be encoded into the URL-encoded format.
And while urlencoded is one of the most commonly used parsers that body-parser provides, you can also use the following:
  • .json(): Parses JSON-formatted text for bodies with a Content-Type of application/json.
  • .raw(): Parses HTTP body in to a Buffer for specified custom Content-Types, although the default accepted Content-Type is application/octet-stream.
  • .text(): Parses HTTP bodies with a Content-Type of text/plain, which returns it as a plain string.
Each of these parsers also supports automatic inflation of data encoded with gzip or deflate, so compression can still be transparently used without any extra work by your application code.
The great thing about the middleware model and how this package parses data is that you're not stuck to using just one parser. You can enable one or more parsers for your app to ensure that all data types are processed properly:
// index.js
const express = require('express');
const bodyParser = require('body-parser');

const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(bodyParser.raw());

// ...
So now if we were to send an HTTP POST request with JSON as the body, it will be parsed in to a regular JSON object in the req.body property:
POST /post-test HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Content-Length: 69

'{"username":"scott","password":"secret","website":"stackabuse.com"}'
$ node index.js
Started server at http://localhost:8080!
Got body: { username: 'scott',
  password: 'secret',
  website: 'stackabuse.com' }

Conclusion

The most common way to send diverse and large amounts of data via HTTP is to use the POST method. Before we can easily access this data on the server side in Express, we need to use some middleware, like the body-parser package, to parse the data in to a format that we can easily access. Once the data from the raw HTTP request is parsed, it can then be accessed via the body property of the req object.
In this article we explained a bit about the various content types/encodings, how to use the body-parser package and its various options, and how to access the parsed data. If you see any issues or have suggestions, feel free to leave a comment below.