method-override
Express/Connect middleware that lets clients override the HTTP method of a request via a header or query string.
Repository Health
Technical Analysis
method-override is a lightweight Connect/Express middleware maintained under the expressjs GitHub organization that lets clients signal an HTTP verb the underlying transport doesn’t support. It reads an overridden method from a request header (default X-HTTP-Method-Override) or a query string key, replaces req.method with the resolved verb when Node’s methods list recognizes it, and preserves the original value on req.originalMethod.
This solves a specific and durable problem: HTML forms only submit GET and POST, and some proxies, corporate networks, or older HTTP clients strip or block PUT/DELETE/PATCH requests. Rather than redesigning routes around POST-only clients, apps drop this single middleware in front of their route handlers and continue writing RESTful PUT/DELETE routes as if the transport supported them natively.
What You Get
- Header-based override - reads a configurable header (default
X-HTTP-Method-Override) and rewritesreq.methodwhen the value is a method Node recognizes. - Query-string override - accepts a non-
X-string as a URL query key (e.g._method) so plain HTML<form>submissions can request DELETE/PUT via?_method=DELETE. - Custom getter function - accepts a
(req, res) => methodfunction for arbitrary lookup logic, such as pulling_methodout of a parsed request body. - Method allowlisting -
options.methodsrestricts which original request methods are eligible for override (defaults toPOSTonly), reducing the risk of caches or proxies misinterpreting overridden requests.
Common Use Cases
- RESTful HTML forms - a plain
<form method="POST" action="/resource?_method=DELETE">deletes a resource without client-side JavaScript. - Legacy client support - XMLHttpRequest clients or SDKs that can’t issue PUT/DELETE directly send
X-HTTP-Method-Override: DELETEon a POST instead. - Proxy/firewall workarounds - corporate proxies or CDNs that block non-standard verbs still deliver intent via header or query override on an allowed POST request.
- Body-based method fields - frameworks that put
_methodinside a parsed request body use the custom-getter form to look it up afterbody-parserruns.
Under The Hood
Architecture
The entire module lives in a single ~140-line index.js that exports one factory function, methodOverride(getter, options), returning a standard three-argument Express/Connect middleware. Configuration (the resolved getter function and allowed-methods list) is captured once in closures at setup time, so the returned middleware does no re-parsing of options per request. Three private helpers, createGetter, createQueryGetter, and createHeaderGetter, translate a string argument into a getter function, and a supports helper validates the resolved value against Node’s known HTTP methods before mutating req.method. There are no classes, no dependency injection, and no exported internals, just a small functional pipeline: resolve getter to configure once, then call getter to override per request.
Tech Stack
The package targets plain Node.js (engines: >= 0.10) as CommonJS with no build step, it ships index.js directly per its package.json files field. Runtime dependencies are all small, long-lived expressjs-ecosystem libraries: debug@3.1.0 for namespaced debug logging, methods@~1.1.2 for the canonical list of supported HTTP verbs, parseurl@~1.3.2 for cached URL parsing, and vary@~1.1.2 for correct Vary response-header manipulation. Development tooling is eslint with the standard config for linting, mocha plus supertest for HTTP-level test assertions, and istanbul for coverage, wired through Travis CI.
Code Quality
A single test/test.js file (~5.9KB) exercises the module through supertest against a real http.createServer, covering the default header path, custom header names, query-string overrides, custom getter functions, the method allowlist, case-insensitivity, and Vary header behavior. There’s no TypeScript and no runtime type checking, values are validated defensively (typeof method === 'string') rather than through a type system, and errors are handled by silently falling through to next() rather than throwing, an appropriate style for a passthrough middleware. Code style is enforced via eslint-config-standard, and naming is consistent and minimal throughout.
API Design
The public surface is a single function with a heavily overloaded but ergonomic first argument, string for header or query lookup, or a function for fully custom logic, so the common case needs zero configuration beyond mounting the middleware. Documentation in the README walks through header, query, multi-header precedence, and custom-getter scenarios with runnable examples, and the option to restrict eligible methods (options.methods) is opt-in rather than required. It’s one of the oldest and most widely copied middleware patterns in the Express ecosystem rather than a novel design, but its minimal-boilerplate, sensible-defaults approach to a narrow problem is close to a reference implementation for the shape.
Used by 2 apps in this directory
ChartBrew
Analytics · Databases
Open-source reporting platform to build live dashboards from SQL, NoSQL, APIs, and SaaS tools with an AI assistant that creates charts from natural language.
Countly
Analytics · Marketing
Privacy-first, self-hosted analytics and customer engagement platform with full data ownership, GDPR compliance, and AI-powered insights across mobile, web, desktop, and IoT.