HTTP Method Override Middleware
method-override is a Node.js middleware designed for Express.js and similar frameworks, enabling clients to utilize HTTP verbs like PUT or DELETE even when their environment (e.g., older browsers, specific `XMLHttpRequest` implementations) primarily supports GET and POST. It achieves this by inspecting a specified request header (e.g., `X-HTTP-Method-Override`), a query string parameter (e.g., `_method`), or a custom function's return value to override the `req.method` property. The current stable version is 3.0.0. The package has a stable, but not high-frequency, release cadence, primarily focusing on maintaining compatibility within the Express.js ecosystem, updating dependencies, and adjusting Node.js version support. Its key differentiator lies in its flexibility in defining the 'getter' for the overridden method and its explicit warning about middleware order for security and functionality, positioning it as a robust solution for method simulation in web applications.
Common errors
-
TypeError: methodOverride is not a function
cause Attempting to use `methodOverride` as middleware without invoking it first, e.g., `app.use(methodOverride);` instead of `app.use(methodOverride('X-HTTP-Method-Override'));`.fixEnsure you call the `methodOverride` function with its required `getter` argument (e.g., a string for a header/query param or a custom function) to get the actual middleware function to pass to `app.use`. -
ReferenceError: require is not defined
cause Attempting to use `require('method-override')` in an ECMAScript Module (ESM) context without proper configuration (e.g., in a file with `"type": "module"` in `package.json` or a `.mjs` file).fixFor ESM projects, use `import methodOverride from 'method-override';`. If you must use `require` in an ESM file, consider dynamic import `const methodOverride = await import('method-override');` or ensure your environment supports CommonJS `require` calls. -
The HTTP method is not being overridden as expected.
cause This can be due to several reasons: `method-override` middleware being placed too late in the middleware chain; the specified `getter` (header name, query parameter) not matching the client's request; or the original request method not being `POST` when `options.methods` is at its default.fix1. Verify `method-override` is at the very top of your `app.use` calls. 2. Double-check the exact header name or query parameter key used in the client request matches the `getter` argument. 3. Ensure the original request from the client is a `POST` request, as this is the default and safest method for overrides.
Warnings
- breaking Version 3.0.0 of method-override dropped support for Node.js versions below 0.10. While highly unlikely to affect modern applications, ensure your Node.js runtime meets this minimal requirement if upgrading from very old versions.
- gotcha It is critical that `method-override` middleware is mounted *before* any other middleware or route handlers that need to know the correct HTTP method of the request. Placing it after could lead to security vulnerabilities (e.g., CSRF protection not working correctly) or incorrect routing decisions.
- gotcha The `options.methods` parameter defaults to `['POST']`, meaning method overriding is only checked if the original request method was POST. Changing this to allow `null` (all methods) or other methods can introduce security issues, especially when requests pass through caches, as it can lead to unexpected behavior or cache poisoning.
Install
-
npm install method-override -
yarn add method-override -
pnpm add method-override
Imports
- methodOverride
const methodOverride = require('method-override').default;import methodOverride from 'method-override';
- methodOverride
import { methodOverride } from 'method-override';const methodOverride = require('method-override'); - methodOverride
app.use(methodOverride);
app.use(methodOverride('X-HTTP-Method-Override'));
Quickstart
import express from 'express';
import methodOverride from 'method-override';
const app = express();
const port = 3000;
// --- Configuration of method-override middleware ---
// Option 1: Override using the 'X-HTTP-Method-Override' header
app.use(methodOverride('X-HTTP-Method-Override'));
// Option 2: Override using a query string parameter named '_method'
// This allows clients to send POST requests with ?_method=PUT or ?_method=DELETE
app.use(methodOverride('_method'));
// Option 3: Custom getter function (e.g., from a form field)
app.use(methodOverride(function (req, res) {
if (req.body && typeof req.body === 'object' && '_method' in req.body) {
// look in urlencoded POST bodies and delete it
const method = req.body._method;
delete req.body._method;
return method;
}
}));
// Ensure method-override is used before any routes or other middleware
// that rely on the correct HTTP method (e.g., csurf, route handlers).
// --- Example Routes ---
app.get('/', (req, res) => {
res.send(`
<h1>Method Override Example</h1>
<p>Original Method: ${req.originalMethod}</p>
<p>Current Method: ${req.method}</p>
<form action="/resource?_method=DELETE" method="POST">
<button type="submit">Delete via Query String</button>
</form>
<p>Try sending a POST request with 'X-HTTP-Method-Override: PUT' header to /resource.</p>
`);
});
app.all('/resource', (req, res) => {
const message = `Received a ${req.method} request to /resource (original: ${req.originalMethod || req.method})`;
console.log(message);
res.status(200).send(message);
});
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
console.log('Test with curl:');
console.log(' curl -X POST -H "X-HTTP-Method-Override: PUT" http://localhost:3000/resource');
console.log(' curl -X POST "http://localhost:3000/resource?_method=DELETE"');
});