Nodejs Express – return 405 for un-supported method

Issue

I’m running a standard NodeJs 8 with Express and currently when a request for an existing path but un-supported method comes in, Express return 404.

For example ‘POST /login’ is supported, but ‘GET /login’ is not, but it returns 404.

How can I make Express return 405 in such a case?

Here’s the routes file:

const express = require('express');
const router = express.Router();
const loginController = require('../controllers/login');


router.route('/login').post(loginController.loginUser);

module.exports = router;

Please advise.

Solution

You can simply add the .all() handler to your route chain, like so:

const methodNotAllowed = (req, res, next) => res.status(405).send();

router
.route(`/login`)
.post(loginController.loginUser)
.all(methodNotAllowed);

Explanation

This works because requests are passed to the handlers in the order they are attached to the route (the request “waterfall”). The .post() handler will catch your POST requests, and the rest will fall through to the .all() handler.

Also see this question for more details.

Authenticating all POST routes

If you would like to ensure that the user is logged in for all POST requests, but return a 405 response for any other requests, you can use a regular expression to match all routes with router.post('*'), like so:

router
.post(`*`, loginController.loginUser)
.all(methodNotAllowed);

The problem with this approach, however, is that no 404 errors will ever be returned to the client, only 405. Therefore I recommend attaching the methodNotAllowed handler to each individual route, like in the first code snippet above. This approach will return 404 errors for routes that don’t exist, but 405 errors for routes that do.

Determining the available methods for a route

To determine which methods are allowed for a route, use router.stack:

app.use((req, res, next) => {

  const methods = router.stack

  // Filter for the route that matches the currently matched route
  .filter(layer => layer.route.path === req.path)[0]
  .route
  .methods;

  if (!methods[req.method]) methodNotAllowed(req, res, next);
  else next();

});

Answered By – dwhieb

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published