method-override

Express/Connect middleware that lets clients override the HTTP method of a request via a header or query string.

Library
npm
v3.0.0
628stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
43/100Fair
Development Activity4
Maintenance20
Community68
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
67/100Good
Architecture75
Code Quality70
Innovation78
Learning Curve45

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 rewrites req.method when 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) => method function for arbitrary lookup logic, such as pulling _method out of a parsed request body.
  • Method allowlisting - options.methods restricts which original request methods are eligible for override (defaults to POST only), 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: DELETE on 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 _method inside a parsed request body use the custom-getter form to look it up after body-parser runs.

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.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search