黑人的命也是命。
支持平等正义倡议.

覆盖 Express API

Express API 包含请求和响应对象上的各种方法和属性。这些是通过原型继承的。Express API 有两个扩展点

  1. 位于 express.requestexpress.response 的全局原型。
  2. 位于 app.requestapp.response 的应用程序特定原型。

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

方法

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

以下是如何覆盖 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 的原始签名。它现在接受状态代码、编码类型以及要发送到客户端的消息。

现在可以使用这种方式使用覆盖后的方法

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

属性

Express API 中的属性要么是

  1. 分配的属性(例如:req.baseUrlreq.originalUrl
  2. 定义为 getter(例如:req.securereq.ip

由于类别 1 下的属性是在当前请求-响应周期的上下文中动态分配到 requestresponse 对象上的,因此无法覆盖其行为。

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

以下代码重写了如何获取req.ip的值。现在,它直接返回Client-IP请求头的值。

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

原型

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

除非必要,建议仅在应用程序级别进行此操作,而不是全局操作。此外,请确保所使用的原型尽可能与默认原型匹配。

// 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)