How to handle forms in Express#

Forms can be submitted using the GET method or the POST method.

GET method forms are recommended for simple forms like a search query or specifying a user id. The form submission details are passed in the request URL and can be seen in the browser address bar.

POST method forms are recommended for forms with sensitive data such as user login; and forms which send a lot of data to the backend, such as submitting an article. For file uploads, POST method is the only way.

Just as birds can be used for carrying Internet Protocol traffic, file uploads can be implemented using other ways too, but that does not mean one should.

Let's see how form submissions are handled in Express.

1. Handling GET forms#

There are two ways of sending data to Express using the GET method:

  1. GET parameters
  2. Using named placeholders

Both these methods work right out of the box, you don't need to install any packages to make them work.

a. GET Parameters#

GET Parameters are the standard for GET form submissions across all browsers and backend systems. It consists of a key and a value in the URL string, specified after a ?. More than one key-value pairs can be specified by using & as a demarcator.

The submitted data is accessible in the req.query object.

If this is the URL:

http://localhost:5000/books?category=biographies&type=paperback

You can access the GET parameters in Express, this way:

app.get('/books', function(req, res) {
  console.log('Category: ' + req.query['category']);
  console.log('Type: ' + req.query['type']);
});

b. Named Placeholders#

Named placeholder is non-standard, Express feature, it uses URL segments for sending data to the app.

The submitted data is accessible in the req.params object.

Considering this URL:

http://localhost:5000/user/313

The named placeholder is defined and accessed this way:

app.get('/user/:id', function(req, res) {
  res.send('user ' + req.params.id);
});

2. Handling POST forms#

Express can handle three types of data submitted via the POST method.

  1. Text-only data
  2. JSON data
  3. Multipart data (file uploads)

a. Handling text-only data#

If you want to handle text data submitted via the POST method, you are in luck. You don't have to install any packages. Express has an in-built middleware express.urlencoded, which you can use to process the text data.

The processed form data is available on the body property of the request object.

The form:

./public/login.html
<form method="post" action="/handler">
  <input type="text" name="username" /><br />
  <input type="password" name="password" /><br />
  <input type="submit" />
</form>

The HTML form element has an attribute named enctype, if not specified, its value defaults to "application/x-www-form-urlencoded" (URL encoded form). The express.urlencoded middleware can handle URL encoded forms only.

Unless you are uploading files, express.urlencoded is all you need for processing forms.

The app:

./app.js
var path = require('path');
var express = require('express');
var app = express();
app.use(express.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));

app.post('/handler', function (req, res) {
  console.log(req.body);
  res.send(req.body);
});

app.listen(5000);

The URL: http://localhost:5000/login.html

b. Handling JSON data#

HTML forms cannot submit JSON data, but JavaScript clients and other apps can. Your Express app should be able to handle JSON data submitted via POST request.

Express has another in-built request data processing middleware, express.json, which is all you need for processing JSON data.

The client:

./client.js
// https://github.com/axios/axios
var axios = require('axios');

axios({
  method: 'post',
  url: 'http://localhost:5000/user',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
})
.then(function (res) {
  console.log(res.data);
})
.catch(function (err) {
  console.log(err);
});

The app:

./app.js
var express = require('express');
var app = express();
app.use(express.json());

app.post('/user', function (req, res) {
  console.log(req.body);
  res.send(req.body);
});

app.listen(5000);

c. Handling file uploads#

Forms containing files are submitted by setting the enctype attribute of the form element to "multipart/form-data" (multipart form).

Processing multipart forms in Express require the installation of a multipart form processing module. Let's use the aptyly named multer for handling multipart forms in the next example.

The form:

./public/upload.html
<form method="post" action="/upload" enctype="multipart/form-data">
  <input type="text" name="title" /><br />
  <input type="file" name="wallpaper" /><br />
  <input type="submit" />
</form>

The app:

./app.js
var path = require('path');
var express = require('express');
var app = express();
var multer  = require('multer');

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './public/images/');
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + file.originalname);
  }
});

var upload = multer({ storage: storage });

app.use(express.static(path.join(__dirname, 'public')));

app.post('/upload', upload.single('wallpaper'), function (req, res) {
  // Text data from the form
  console.log(req.body);
  // Details about the uploaded file
  console.log(req.file);
  var imagePath = req.file.path.replace(/^public\//, '');
  res.redirect(imagePath);
});

app.listen(5000);

The URL: http://localhost:5000/upload.html

For a detailed explanation about this code, multer, and more advanced file upload usecases refer to "Express.js: Handling file uploads".

Summary#

Express comes with in-built middleware for processing text and JSON data submitted via forms or by clients. Multipart forms containing text and files can be handled using the multer module. Text data are populated in the req.body object, file upload details are found in the req.file object.

References#

  1. Express.js: Handling file uploads
  2. Express.js - express.urlencoded
  3. Express.js - express.json
  4. multer
  5. axios