domains / app-frameworks / expressjs/Express
Preserve API compatibility and semantics
When adding or modifying public request/response/app methods, preserve their documented types, return values, and behavior unless the change is explicitly scoped to a major version with a deprecation path. Examples: don't silently change `flatten` to `Array.prototype.flat` (different depth semantics) in a minor release, don't let `cookie.expires` accept a...
When adding or modifying public request/response/app methods, preserve their documented types, return values, and behavior unless the change is explicitly scoped to a major version with a deprecation path. Examples: don’t silently change flatten to Array.prototype.flat (different depth semantics) in a minor release, don’t let cookie.expires accept a number when the documented type is Date, don’t alter req.accepts() so it always returns true, and don’t change req.path semantics between HTTP/1 and HTTP/2 without a deprecation cycle. If a behavior change is unavoidable, gate it behind a new major version or a deprecation warning, and add tests covering the old and new behavior.
Additionally, new or extended API surface should be built on top of existing, well-tested primitives rather than reimplemented from scratch, so HTTP semantics stay correct and consistent:
res.sendStatus()should delegate tores.send()(notres.end()) so Content-Type, Content-Length, and other headers are set the same way as the rest of the response API:res.sendStatus = function sendStatus(statusCode) { var body = http.STATUS_CODES[statusCode] || String(statusCode) this.statusCode = statusCode this.type('txt') return this.send(body) }- Don’t reuse getters/setters for a purpose they weren’t designed for (e.g.
res.get/res.setare header accessors and must not be used to read/write arbitrary app settings). - Follow the relevant HTTP/W3C spec when generating headers (e.g.
Linkheader attribute quoting/ordering, not injectingcharsetinto aBlob’stypethat the caller didn’t request, respecting an already-setContent-Type). - Choose HTTP verbs that match the semantics of the operation (e.g.
PUTfor full-resource replacement vsPATCHfor partial updates), and validate/clamp inputs (status codes, lengths) according to the spec rather than accepting out-of-range or ambiguous values.
Treat any change to a public method’s signature, return type, or side effects as a breaking change requiring explicit versioning, tests for both old and new behavior, and clear documentation.