覆盖 Express API

¥Overriding the Express API

Express API 由请求和响应对象的各种方法和属性组成。这些是由原型继承的。Express API 有两个扩展点:

¥The Express API consists of various methods and properties on the request and response objects. These are inherited by prototype. There are two extension points for the Express API:

  1. express.requestexpress.response 的全局原型。

    ¥The global prototypes at express.request and express.response.

  2. app.requestapp.response 的应用特定原型。

    ¥App-specific prototypes at app.request and app.response.

更改全局原型将影响同一进程中所有已加载的 Express 应用。如果需要,可以通过仅在创建新应用后更改特定于应用的原型来进行特定于应用的更改。

¥Altering the global prototypes will affect all loaded Express apps in the same process. If desired, alterations can be made app-specific by only altering the app-specific prototypes after creating a new app.

方法

¥Methods

你可以通过分配自定义函数来用自己的方法覆盖现有方法的签名和行为。

¥You can override the signature and behavior of existing methods with your own, by assigning a custom function.

以下是覆盖 res.sendStatus 行为的示例。

¥Following is an example of overriding the behavior of res.sendStatus.

app.response.sendStatus = function (statusCode, type, message) {
  // code is intentionally kept simple for demonstration purpose
  return this.contentType(type)
    .status(statusCode)
    .send(message)
}

上述实现完全改变了 res.sendStatus 的原始签名。它现在接受状态代码、编码类型和要发送到客户端的消息。

¥The above implementation completely changes the original signature of res.sendStatus. It now accepts a status code, encoding type, and the message to be sent to the client.

现在可以这样使用被覆盖的方法:

¥The overridden method may now be used this way:

res.sendStatus(404, 'application/json', '{"error":"resource not found"}')

属性

¥Properties

Express API 中的属性是:

¥Properties in the Express API are either:

  1. 分配的属性(例如:req.baseUrlreq.originalUrl

    ¥Assigned properties (ex: req.baseUrl, req.originalUrl)

  2. 定义为获取器(例如:req.securereq.ip

    ¥Defined as getters (ex: req.secure, req.ip)

由于类别 1 下的属性是在当前请求-响应周期的上下文中动态分配给 requestresponse 对象的,因此它们的行为不能被覆盖。

¥Since properties under category 1 are dynamically assigned on the request and response objects in the context of the current request-response cycle, their behavior cannot be overridden.

可以使用 Express API 扩展 API 覆盖类别 2 下的属性。

¥Properties under category 2 can be overwritten using the Express API extensions API.

以下代码重写了如何导出 req.ip 的值。现在,它只返回 Client-IP 请求标头的值。

¥The following code rewrites how the value of req.ip is to be derived. Now, it simply returns the value of the Client-IP request header.

Object.defineProperty(app.request, 'ip', {
  configurable: true,
  enumerable: true,
  get () { return this.get('Client-IP') }
})

原型

¥Prototype

为了提供 Express.js API,传递给 Express.js 的请求/响应对象(例如通过 app(req, res))需要继承自同一原型链。默认情况下,请求为 http.IncomingRequest.prototype,响应为 http.ServerResponse.prototype

¥In order to provide the Express.js API, the request/response objects passed to Express.js (via app(req, res), for example) need to inherit from the same prototype chain. By default this is http.IncomingRequest.prototype for the request and http.ServerResponse.prototype for the response.

除非必要,否则建议仅在应用级别而不是全局执行此操作。此外,请注意正在使用的原型尽可能与默认原型匹配的功能。

¥Unless necessary, it is recommended that this be done only at the application level, rather than globally. Also, take care that the prototype that is being used matches the functionality as closely as possible to the default prototypes.

// Use FakeRequest and FakeResponse in place of http.IncomingRequest and http.ServerResponse
// for the given app reference
Object.setPrototypeOf(Object.getPrototypeOf(app.request), FakeRequest.prototype)
Object.setPrototypeOf(Object.getPrototypeOf(app.response), FakeResponse.prototype)