このページを翻訳

Express アプリで使用するミドルウェアを書く

Middleware 関数は、request object (req) にアクセスできる関数です。 response object (res)とアプリケーションのリクエストレスポンスサイクルの中の next 関数。 next 関数はExpressルータ内の関数で、呼び出されたときに現在のミドルウェアを継承してミドルウェアを実行します。 next 関数はExpressルータ内の関数で、呼び出されたときに現在のミドルウェアを継承してミドルウェアを実行します。

ミドルウェア機能は以下のタスクを実行できます。

  • 任意のコードを実行します。
  • リクエストとレスポンスオブジェクトに変更を加えます。
  • リクエストレスポンスサイクルを終了します。
  • スタック内の次のミドルウェアを呼び出します。

現在のミドルウェア関数がリクエスト応答サイクルを終了しない場合は、次のミドルウェア関数に制御を渡すために next() を呼び出す必要があります。 そうでなければ、リクエストはハングアップのままになります。 そうでなければ、リクエストはハングアップのままになります。

次の図はミドルウェア関数呼び出しの要素を示しています。

Elements of a middleware function call

Express 5以降、Promiseを返すミドルウェア関数はエラーの拒否またはスロー時に「next(value)」を呼び出します。 nextは、拒否された値またはスローされたエラーで呼び出されます。 nextは、拒否された値またはスローされたエラーで呼び出されます。

以下は、簡単な「Hello World」エクスプレスアプリケーションの例です。 以下は、簡単な「Hello World」エクスプレスアプリケーションの例です。 The remainder of this article will define and add three middleware functions to the application: one called myLogger that prints a simple log message, one called requestTime that displays the timestamp of the HTTP request, and one called validateCookies that validates incoming cookies.

index.cjs
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000);

ミドルウェア関数 myLogger

Here is a simple example of a middleware function called “myLogger”. This function just prints “LOGGED” when a request to the app passes through it. 以下は、「myLogger」というミドルウェア関数の簡単な例です。 この関数は、アプリへのリクエストがそれを通過したときに “LOGGED” を出力します。 ミドルウェア関数は、myLoggerという名前の 変数に割り当てられます。

const myLogger = function (req, res, next) {
console.log('LOGGED');
next();
};

Here myLogger is defined on its own rather than passed directly to app.use(), so TypeScript has no context to infer its parameters and they are annotated explicitly. You can instead type the whole function as RequestHandler, which types req, res, and next for you. When the middleware is written inline in the app.use() call, Express infers those three parameters and no annotations are needed.

Notice the call above to next(). Calling this function invokes the next middleware function in the app. The next() function is not a part of the Node.js or Express API, but is the third argument that is passed to the middleware function. The next() function could be named anything, but by convention it is always named “next”. To avoid confusion, always use this convention.

ミドルウェア関数をロードするには、ミドルウェア関数を指定して app.use() を呼び出します。 例えば、次のコードはルートパス(/)の前にmyLoggerミドルウェア関数をロードします。 For example, the following code loads the myLogger middleware function before the route to the root path (/).

index.cjs
const express = require('express');
const app = express();
const myLogger = function (req, res, next) {
console.log('LOGGED');
next();
};
app.use(myLogger);
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000);

アプリがリクエストを受け取るたびに、「LOGGED」というメッセージが端末に出力されます。

ミドルウェアのロード順序は重要です。最初にロードされるミドルウェア関数も最初に実行されます。

ルートパスの後にmyLoggerがロードされている場合、リクエストは到達せず、アプリは”LOGGED”を出力しません。 なぜなら、ルートパスのルートハンドラは、リクエスト応答サイクルを終了するからです。

ミドルウェア関数 myLogger は単にメッセージを出力します。 次に、next()関数を呼び出すことで、スタック内の次のミドルウェア関数にリクエストを渡します。

ミドルウェア関数requestTime

次に、“requestTime” というミドルウェア関数を作成し、リクエストオブジェクトに requestTime というプロパティを追加します。

Because the middleware adds a property to req, extend the request type in TypeScript with declaration merging. Declare the property (as optional, since a middleware may not run for every request) in a .d.ts file that is part of your project:

types/express.d.ts
declare global {
namespace Express {
interface Request {
requestTime?: number;
}
}
}
export {};

TypeScript picks up the file automatically, so no tsconfig.json change is needed unless you have set a custom include that does not cover its location. See Extending the API in TypeScript for adding other custom properties and methods.

const requestTime = function (req, res, next) {
req.requestTime = Date.now();
next();
};

The app now uses the requestTime middleware function. アプリは requestTime ミドルウェア関数を使用します。 また、ルートのコールバック関数はミドルウェア関数がreq(リクエストオブジェクト)に追加するプロパティを使用します。

index.cjs
const express = require('express');
const app = express();
const requestTime = function (req, res, next) {
req.requestTime = Date.now();
next();
};
app.use(requestTime);
app.get('/', (req, res) => {
let responseText = 'Hello World!<br>';
responseText += `<small>Requested at: ${req.requestTime}</small>`;
res.send(responseText);
});
app.listen(3000);

アプリのルートにリクエストを送信すると、アプリはブラウザにリクエストのタイムスタンプを表示するようになりました。

ミドルウェア関数 validateCookies

最後に、入力されたクッキーを検証するミドルウェア機能を作成し、クッキーが無効な場合に400回のレスポンスを送信します。

ここでは、外部非同期サービスで Cookie を検証する機能の例を示します。

async function cookieValidator(cookies) {
try {
await externallyValidateCookie(cookies.testCookie);
} catch {
throw new Error('Invalid cookies');
}
}

ここでは、cookie-parser ミドルウェアを使用して、reqオブジェクトから入ってくるCookieを解析し、それを私たちのcookieValidator関数に渡します。 validateCookiesミドルウェアは、拒否時に自動的にエラーハンドラをトリガーするPromiseを返します。 The validateCookies middleware returns a Promise that upon rejection will automatically trigger our error handler.

index.cjs
const express = require('express');
const cookieParser = require('cookie-parser');
const cookieValidator = require('./cookieValidator');
const app = express();
async function validateCookies(req, res, next) {
await cookieValidator(req.cookies);
next();
}
app.use(cookieParser());
app.use(validateCookies);
// error handler
app.use((err, req, res, next) => {
res.status(400).send(err.message);
});
app.listen(3000);

await cookieValidator(req.cookies)の後にnext()が呼び出されることに注意してください。 これにより、 cookieValidator が解決した場合、スタック内の次のミドルウェアが呼ばれます。 If you pass anything to the next() function (except the string 'route' or 'router'), Express regards the current request as being an error and will skip any remaining non-error handling routing and middleware functions. This ensures that if cookieValidator resolves, the next middleware in the stack will get called. If you pass anything to the next() function (except the string 'route' or 'router'), Express regards the current request as being an error and will skip any remaining non-error handling routing and middleware functions.

リクエストオブジェクト、レスポンスオブジェクト、スタック内の次のミドルウェア関数、そしてノード全体にアクセスできるためです。 s API、ミドルウェア関数の可能性は無限大です。

Express ミドルウェアの詳細については、Express ミドルウェアを使用するを参照してください。

設定可能なミドルウェア

ミドルウェアの設定が必要な場合は、optionsオブジェクトや他のパラメータを受け付ける関数をエクスポートしてください。 入力パラメータに基づいてミドルウェアの実装を返します。

my-middleware.cjs
module.exports = function (options) {
return function (req, res, next) {
// Implement the middleware function based on the options object
next();
};
};

ミドルウェアを以下のように使用できるようになりました。

index.cjs
const mw = require('./my-middleware.cjs');
app.use(mw({ option1: '1', option2: '2' }));

構成可能なミドルウェアの例については、 cookie-sessioncompression を参照してください。