このページを翻訳

Express API のオーバーライド

Express API は、リクエストオブジェクトとレスポンスオブジェクトのさまざまなメソッドとプロパティで構成されています。 これらはプロトタイプによって継承されます。 Express API には 2 つの拡張ポイントがあります。 These are inherited by prototype. There are two extension points for the Express API:

  1. express.requestexpress.response のグローバルプロトタイプ。
  2. app.requestapp.responseでアプリ固有のプロトタイプ。

グローバルプロトタイプを変更すると、読み込まれたすべてのExpressアプリが同じプロセスで影響を受けます。 必要に応じて、新しいアプリを作成した後にアプリ固有のプロトタイプを変更するだけで、アプリ固有の変更を行うことができます。 If desired, alterations can be made app-specific by only altering the app-specific prototypes after creating a new app.

メソッド

カスタム関数を割り当てることで、既存のメソッドの署名と振る舞いを独自のメソッドで上書きできます。

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 の元の署名を完全に変更します。 ステータスコード、エンコーディングタイプ、およびメッセージをクライアントに送信できるようになりました。 It now accepts a status code, encoding type, and the message to be sent to the client.

In TypeScript, augmenting express-serve-static-core adds the new overload to the Response type so call sites such as res.sendStatus(404, 'application/json', body) type-check. The assignment is cast with as Response['sendStatus'] because replacing a method with a different signature cannot be checked against the original declaration.

オーバーライドされたメソッドは次のように使用できます。

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

プロパティー

Express API のプロパティは以下のいずれかです。

  1. 割り当てられたプロパティ (例: req.baseUrl, req.originalUrl)
  2. getters (例: req.secure, req.ip) として定義されています。

category 1 のプロパティは、現在のリクエスト-レスポンスサイクルのコンテキストで requestresponse オブジェクトに動的に割り当てられます。 彼らの行動はオーバーライドできない

カテゴリ2のプロパティはExpress API拡張機能APIを使用して上書きすることができます。

The following code rewrites how the value of req.ip is to be derived. 次のコードは req.ip の値をどのように派生するかを書き換えます。 これで、Client-IP リクエストヘッダの値を返すだけです。

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

Extending the API in TypeScript

The sections above override members that Express already provides. To add your own properties or methods to the request or response, describe them to TypeScript with declaration merging on the Express namespace. Put the augmentation in a .d.ts file that is part of your project. No tsconfig.json change is needed unless a custom include does not cover its location.

For example, an authentication middleware may attach a user to the request, and you might add a sendError helper to the response:

types/express.d.ts
interface User {
id: string;
name: string;
}
declare global {
namespace Express {
interface Request {
user?: User;
}
interface Response {
sendError(status: number, message: string): this;
}
}
}
export {};

The additions are now known throughout the application:

import { type Request, type Response, type NextFunction } from 'express';
app.use((req: Request, res: Response, next: NextFunction) => {
req.user = { id: '1', name: 'Tobi' };
next();
});
app.response.sendError = function (this: Response, status: number, message: string) {
return this.status(status).json({ error: message });
};
app.get('/', (req: Request, res: Response) => {
if (!req.user) {
res.sendError(401, 'unauthorized');
return;
}
res.send(req.user.name);
});

Declare custom request properties as optional (user?). The type applies to every request, but TypeScript cannot know which middleware ran before a given handler, so a required property would be a false guarantee. Check for the value (as with if (!req.user) above) before relying on it.

Adding a new method needs no cast, unlike overriding an existing method with a different signature, because the method did not previously exist on the type.

プロトタイプ

Express API を提供するためには、Express に渡された request/response オブジェクトを (app(req) 経由で) 提供します。 res)は同じプロトタイプチェーンから継承する必要があります。 デフォルトでは、リクエストの http.IncomingRequest.prototype と、レスポンスの http.ServerResponse.prototype です。 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);