Cannot POST / error in Express and Node.js [Solved]

avatar
Borislav Hadzhiev

Last updated: Apr 5, 2024
4 min

banner

# Cannot POST / error in Express and Node.js [Solved]

The "Cannot POST /" error in Express and Node.js is caused when there is a mismatch between the path in the route handler and the path your form is making a POST request to.

To solve the error, make sure the action attribute of the form corresponds to the path in the request handler.

cannot post express js

Here is a minimal example of making a POST request in an Express.js application.

Let's start with the form that makes the POST request.

This is my index.html file.

index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <h2>bobbyhadz.com</h2> <form action="/register" method="post"> <div> <label>Username:</label> <input type="text" name="username" /><br /> </div> <div> <label>Password:</label> <input type="password" name="password" /> </div> <div><input type="submit" value="Register" /></div> </form> </body> </html>
The code for this article is available on GitHub

The form is quite minimal, it has 2 fields - a username and a password.

This is my index.js file.

index.js
// ๐Ÿ‘‡๏ธ using require() CommonJS imports const express = require('express'); const bodyParser = require('body-parser'); const app = express(); app.use(express.static(__dirname + '/public')); app.use(bodyParser.json()); app.use( bodyParser.urlencoded({ extended: false, }), ); app.get('/register', function (req, res) { // ๐Ÿ‘‡๏ธ if your HTML file is in the root directory (next to package.json) res.sendFile(__dirname + '/index.html'); }); app.post('/register', function (req, res) { console.log( `username: ${req.body.username}, password: ${req.body.password}`, ); res.send( `username: ${req.body.username}, password: ${req.body.password}`, ); }); const port = 5000; app.listen(port, () => { console.log(`Example app listening on port ${port}`); });
The code for this article is available on GitHub

Here is the equivalent code sample using the ES6 modules import/export syntax.

index.js
// ๐Ÿ‘‡๏ธ using ES6 Modules import/export syntax import express from 'express'; import bodyParser from 'body-parser'; import path from 'path'; import {fileURLToPath} from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const app = express(); app.use(express.static(__dirname + '/public')); app.use(bodyParser.json()); app.use( bodyParser.urlencoded({ extended: false, }), ); app.get('/register', function (req, res) { // ๐Ÿ‘‡๏ธ if your HTML file is in the root directory (next to package.json) res.sendFile(__dirname + '/index.html'); }); app.post('/register', function (req, res) { console.log( `username: ${req.body.username}, password: ${req.body.password}`, ); res.send( `username: ${req.body.username}, password: ${req.body.password}`, ); }); const port = 5000; app.listen(port, () => { console.log(`Example app listening on port ${port}`); });
The code for this article is available on GitHub

You can start the server with npx nodemon index.js and open http://localhost:5000/register.

shell
npx nodemon index.js

fill form successfully on post request

As shown in the short clip everything works as expected.

# Things to note to solve the error

Things to note when solving the error:

  1. Make sure the path in your form's action attribute matches the path in your app.post route handler.

For example, my form element has an action attribute set to /register.

index.html
<form action="/register" method="post">

So my route handler should also set its path to /register.

index.js
app.post('/register', function (req, res) { // ... })

You should also have a corresponding app.get handler that is used to render the form when the user visits the page.

index.js
app.get('/register', function (req, res) { // ๐Ÿ‘‡๏ธ if your HTML file is in the root directory (next to package.json) res.sendFile(__dirname + '/index.html'); });
  1. When the user visits the /register route, the app.get() route handler renders the index.html file (the form).
  2. When the user fills out the form and submits it, the form's action attribute POSTS the data to the /register route.
  3. The form triggers the app.post() route handler for /register.
  4. The app.post() route handler logs the submitted username and password and sends them back to the user.
index.js
app.post('/register', function (req, res) { console.log( `username: ${req.body.username}, password: ${req.body.password}`, ); res.send( `username: ${req.body.username}, password: ${req.body.password}`, ); });
The code for this article is available on GitHub

The code sample assumes that your index.html and index.js files are located in the root directory of your project (where your package.json file is).

correct location of js and html files

  1. Make sure to configure the static middleware of files and the bodyParser module.
index.js
// ๐Ÿ‘‡๏ธ using require() CommonJS syntax const express = require('express'); const bodyParser = require('body-parser'); const app = express(); app.use(express.static(__dirname + '/public')); app.use(bodyParser.json()); app.use( bodyParser.urlencoded({ extended: false, }), );

And here is the equivalent code sample using the ES6 modules import/export syntax.

index.js
// ๐Ÿ‘‡๏ธ using ES6 import/export syntax import express from 'express'; import bodyParser from 'body-parser'; import path from 'path'; import {fileURLToPath} from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const app = express(); app.use(express.static(__dirname + '/public')); app.use(bodyParser.json()); app.use( bodyParser.urlencoded({ extended: false, }), );

The code sample assumes that you have a /public directory where you store your static (JS, CSS, images) files.

  1. You can access the posted form data on the req.body object.
index.js
app.post('/register', function (req, res) { console.log( `username: ${req.body.username}, password: ${req.body.password}`, ); res.send( `username: ${req.body.username}, password: ${req.body.password}`, ); });
The code for this article is available on GitHub

# Conclusion

The action attribute of the form element in your index.html file should match the path in your app.get() and app.post() request handlers.

index.html
<form action="/register" method="post">

The action attribute is set to /register in the example above.

Here is the app.get() route handler which renders the form element when the user visits /register.

index.js
app.get('/register', function (req, res) { res.sendFile(__dirname + '/index.html'); });

The route handler shows the form when the user visits the /register route.

And here is the app.post() route handler which is called when the user submits the form (because the form's action corresponds to the path).

index.js
app.post('/register', function (req, res) { console.log( `username: ${req.body.username}, password: ${req.body.password}`, ); res.send( `username: ${req.body.username}, password: ${req.body.password}`, ); });
The code for this article is available on GitHub

The route gets triggered when the form with action set to /register is submitted.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev