expressjs/expressMIT9a34acfReport / request removal

The Request Object

Express builds req on Node’s http.IncomingMessage.prototype, preserving the Node HTTP request object as its base.

It exists to give handlers a single request surface for negotiation, address resolution, route parameters, and other request-derived state. The supplied source shows these concerns being assembled from small imported modules and application settings.

Sources: lib/request.js:30, lib/request.js:16, lib/request.js:17, lib/request.js:18, lib/request.js:19, lib/request.js:20, lib/request.js:21, lib/request.js:22, lib/request.js:23

Core concepts

The request prototype

The Express request object is created with Node’s http.IncomingMessage.prototype as its prototype.

Sources: lib/request.js:30

Content negotiation

Content negotiation selects a server-supported representation from candidate types using the request’s Accept header. The test shows req.accepts returning text/html for Accept: */html when given JSON and HTML candidates.

Sources: test/req.accepts.js:112-122

Proxy-aware addresses

The values of req.ip and req.ips depend on the configured trust proxy behavior and the forwarded-address chain.

Sources: test/req.ip.js:9-37

Route and query state

Route parameters are exposed through req.params, while the supplied source only shows how the application configures a query parser, not the later population of req.query.

The request module imports these names; the import lines alone do not establish each name’s internal responsibility.

IdentifierWhat the shown source establishes
acceptsImported from the accepts package
isIPAssigned from node:net.isIP
typeisImported from the type-is package
httpImported from node:http
freshImported from the fresh package
parseRangeImported from the range-parser package
parseImported from the parseurl package
proxyaddrImported from the proxy-addr package

defineGetter exposes a property by calling Object.defineProperty with configurable, enumerable, and getter settings.

Sources: test/app.router.js:16-36, lib/application.js:363-369, lib/request.js:16, lib/request.js:17, lib/request.js:18, lib/request.js:19, lib/request.js:20, lib/request.js:21, lib/request.js:22, lib/request.js:23, lib/request.js:521-527

How the request object is assembled

This architecture view shows the construction boundary and the imported request-related modules without assigning unsupported behavior to those imports.

Request object boundary — What does the Express request object build on and import?

Evidence

The concrete construction evidence is Object.create(http.IncomingMessage.prototype), while the request module separately imports accepts and proxyaddr.

defineGetter provides the property-definition mechanism used by the request module, but the supplied excerpt does not identify which individual request properties use it.

Sources: lib/request.js:16, lib/request.js:23, lib/request.js:30, lib/request.js:521-527

How req.accepts() chooses a representation

A handler passes candidate representations to req.accepts, and the test demonstrates the resulting choice from the request’s Accept header.

In the example, the request advertises * /html as Accept—shown in the source as */html—and the candidate list is ['application/json', 'text/html']; the handler receives text/html.

The supplied excerpts do not show the internal algorithm used to compare header values, quality weights, or aliases. They establish the observable candidate-selection behavior, not the implementation details of the external package.

res.format consumes the same request-facing decision: it removes default, passes the remaining keys to req.accepts, invokes the selected handler, and otherwise uses default or passes a 406 error to next.

Sources: test/req.accepts.js:115-122, test/req.accepts.js:112-122, lib/response.js:573-597

How addresses and route state reach a handler

The address distinction is observable in the tests. With trust proxy enabled and X-Forwarded-For: client, p1, p2, req.ip returns client, while req.ips returns ["client","p1","p2"].

With app.set('trust proxy', 2), the same forwarded chain produces p1 for req.ip and ["p1","p2"] for req.ips, stopping at the first untrusted address.

Changing trust proxy causes the application to compile and store trust proxy fn, which connects address behavior to application configuration.

This flow summarizes the tested difference between the single resolved address and the retained forwarded list.

Diagram omitted: missing

Route parameters are populated by route matching before the handler reads them: a route registered as /user/:id exposes req.params.id as 1 to the surrounding handlers.

A mounted router temporarily sees a different parameter view: the test observes undefined inside the router, then confirms that the outer handlers still see 1 after the router returns.

The resource example reads several captured values directly from req.params, including a, b, format, and id.

For query state, app.set('query parser', val) compiles and stores query parser fn. The supplied excerpts do not show the parser being invoked or req.query being assigned, so the complete query-population path cannot be established here.

Sources: test/req.ip.js:9-23, test/req.ips.js:9-23, test/req.ip.js:25-37, test/req.ips.js:25-37, lib/application.js:359-372, test/app.router.js:16-36, test/app.router.js:25-36, examples/resource/index.js:13-24, lib/application.js:363-369

How it connects

An HTTP server uses the Express application function as its callback, providing the entry boundary for incoming requests. The surrounding startup path is described in Application Lifecycle, and handler dispatch is described in App Routing & Request Dispatch.

Route matching, router parameter scope, and restoration connect to Routing Architecture.

The request’s negotiation result is consumed by response formatting, which connects this page to Response: Sending Data.

The trust proxy and query parser settings are configured through the application settings system described in App Configuration & Settings.

Sources: lib/application.js:577-594, lib/response.js:573-597

Key takeaways

  • req is created from http.IncomingMessage.prototype.
  • req.accepts chooses among supplied candidates based on the request’s advertised type; the shown test returns text/html.
  • req.ip exposes one resolved address, while req.ips exposes the tested forwarded list.
  • Numeric trust proxy changes where address resolution stops.
  • The excerpts show route parameters reaching handlers through req.params, but do not show the full req.query population path.

Sources: lib/request.js:30, test/req.accepts.js:115-122, test/req.ip.js:9-37, test/req.ip.js:25-37, test/req.ips.js:25-37, lib/application.js:363-369

Want this for your repos?

Try Angada AI Wiki