/expressjs-restrict-http-method

Return custom status code in Node.js server

Primary LanguageJavaScriptMIT LicenseMIT

TL;DR

Run npm run http and npm run express.

Both scripts log INVALID: 400, instead of 405.

# Request Method: Response Status

# Allowed methods
GET: 200
POST: 200

# Un-allowed methods
DELETE: 405
PUT: 405

# Invalid method(s)
INVALID: 400

In Node.js, invalid HTTP methods always return 400.

This behavior cannot be customized, as it is hardcoded.

Features

Example Code with and without using Express.js

Feature Express.js HTTP
Restrict HTTP Request Methods Valid Request Methods Only
Handle Error with a Custom Function

Specifications

Request with GET or POST

→ Respond with 200 and OK


Request with other valid request methods

→ Respond with 405 and Method Not Allowed


Request with any invalid request methods

→ Respond with 400 (related GitHub issue)


Error occurs in Express.js

→ Respond with 500 and Error Occurred

Appendix

Express.js vs Node.js HTTP

Express.js app.listen() simply returns a Node.js http.Server

/**
 * Listen for connections.
 *
 * A node `http.Server` is returned, with this
 * application (which is a `Function`) as its
 * callback. If you wish to create both an HTTP
 * and HTTPS server you may do so with the "http"
 * and "https" modules as shown here:
 *
 *    var http = require('http')
 *      , https = require('https')
 *      , express = require('express')
 *      , app = express();
 *
 *    http.createServer(app).listen(80);
 *    https.createServer({ ... }, app).listen(443);
 *
 * @return {http.Server}
 * @public
 */

expressjs / express / lib / application.js, GitHub

Valid Request Methods in Node.js

Node.js HTTP Parser only considers these methods as valid

HTTP_ACL;
HTTP_BIND;
HTTP_CONNECT;
HTTP_DELETE;
HTTP_GET;
HTTP_HEAD;
HTTP_LOCK;
HTTP_MKCOL;
HTTP_NOTIFY;
HTTP_OPTIONS;
HTTP_POST;
HTTP_REPORT;
HTTP_SUBSCRIBE;
HTTP_TRACE;
HTTP_UNLOCK;

nodejs / http-parser / http_parser.c, GitHub


Other methods are considered invalid and are handled as error

switch (ch) {
  case 'A': parser->method = HTTP_ACL; break;
  // Other switch cases go here
  break;
  default:
    SET_ERRNO(HPE_INVALID_METHOD);
    goto error;
}

nodejs / http-parser / http_parser.c, GitHub


Therefore in Node.js HTTP, invalid HTTP method returns a 400.

const http = require('http');
http.createServer((req, res) => {
  res.statusCode = 200;
  res.end('OK');
}).listen(80);

// Respond to all requests with `200` and `OK`
// Request using `AAA` method responds with `400`

Reference Code From Official Documents

const express = require('express')
const https = require('https')
const http = require('http')
const app = express()

http.createServer(app).listen(80)
https.createServer(options, app).listen(443)

Express.js 4.x API / app.listen, Express.js Docs


function errorHandler (err, req, res, next) {
  if (res.headersSent) {
    return next(err)
  }
  res.status(500)
  res.render('error', { error: err })
}

The default error handler, Express.js Docs