3秒でわかる
1回の HTTP リクエストを受けてからレスポンスを返すまでの間だけ生きるデータの範囲。リクエストごとの情報を安全に持ち回るために使います。
もう少し詳しく
どういうものか
リクエストスコープは、サーバーがリクエストを受け取った瞬間に作られ、レスポンスを返し終えた時点で捨てられる入れ物です。認証済みのユーザー情報、リクエスト ID、トレース用の開始時刻など、その1回の処理でだけ意味を持つ値を入れます。
サーバーは同時に何十件ものリクエストを扱いますが、それぞれが自分専用の入れ物を持つため、他のリクエストの値と混ざりません。
なぜ必要か
ログインユーザーをグローバル変数に置くと、同時アクセスした別の利用者の情報で上書きされます。他人の注文履歴が表示される、という事故はこの取り違えが原因です。かといって、すべての関数の引数にユーザー情報を足していくと、実際には使わない中間の層まで引数だらけになります。リクエスト単位の入れ物は、この2つの間を取るための仕組みです。
具体例
Express なら res.locals、Spring なら @RequestScope の Bean が該当します。
// 入り口の1か所で詰めておく
app.use((req, res, next) => {
res.locals.requestId = crypto.randomUUID();
res.locals.user = verifyToken(req.headers.authorization);
next();
});
app.get("/orders", (req, res) => {
// 引数で持ち回らずに取り出せる。応答を返した時点で消える
const orders = findOrdersByUser(res.locals.user.id);
res.json({ requestId: res.locals.requestId, orders });
});つまずきやすいところ
setTimeout やジョブキューへ処理を逃がした後で読み出す。その頃にはレスポンスが終わっていて中身は消えています似た用語との違い
| スコープ | 生存期間 | 入れるもの |
|---|---|---|
| アプリケーション | プロセスが起動している間ずっと | 設定値、接続プール |
| セッション | 同じ利用者のログイン中 | ログイン状態、カート |
| リクエスト | 応答を返すまで | ユーザー情報、リクエスト ID |
覚え方
寿命の長い順にアプリケーション、セッション、リクエスト。短いほど安全なので、迷ったら一番短いところに置きます。