0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ネストされたルータからルートパラメータにアクセスする方法

Last updated at Posted at 2025-03-08

2025.03.12追記

mergeParamsというオプションを使って直接アクセスできるみたいです。

import { Router } from "express";

const router=Router({mergeParams:true});

https://expressjs.com/en/5x/api.html#express.router

はじめに

Expressでは、

app.js
import express from 'express';

const app=express();

app.use('/users/:id',(req,res,next)=>{ 
    //...処理
})

のようにしてルートパラメータを設定することができ、req.params.idとして取得できます。
そして、ルートパラメータは複数設定することもできます。

app.js
app.use('/users/:id/todos/:todoid',(req,res,next)=>{
    //...処理
})

ルーティングがそこまで複雑でなければ同じルータに書いてしまえばよいですが、複雑になってくると下位のルータを使うなどしてファイルを分割したくなります。
しかし、app.use('/users/:id',router)だとrouterで呼ばれるミドルウェアはidにアクセスできません。

app.js
import express,{ Router } from 'express';

const app=express();
const router=Router();

const testHandler=(req,res)=>{
    const {id}=req.params;
    if(!id){
        res.send("idにアクセスできません");
        return;
    }
    res.send("id:"+id);
}

router.use('/',testHandler);

//ここのtestHandlerはreq.params.idにアクセスできる
app.use('/test/:id',testHandler);
//routerで呼ばれるtestHandlerはreq.params.idにアクセスできない
app.use('/test2/:id',router);

app.listen(8000,()=>{
    console.log("App is Running at http://localhost:8000.");
})

app.param(name,callback)

そこで、app.paramrouter.paramを使うことで下位のルータからもアクセスできるようにすることが可能です。
app.param(name,callback)は名前がnameに一致するルートパラメータに対してコールバック関数を設定するメソッドです。
下の例では、名前がidであるルートパラメータをもつパスに対してリクエストがあったときにreq.id=id;が実行される、ということになります。

app.js
...
router.param("id",(req,res,next,id)=>{
    //reqオブジェクトにルートパラメータを格納
    req.id=id;
    next();
})
...
TypeScriptの場合 TypeScriptだと、
プロパティ 'id' は型 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>' に存在しません。

のようなエラーが出ると思います。
この場合は、index.d.tsファイルに

index.d.ts
declare module "express-serve-static-core" {
  interface Request {
    id:string;
  }
}

を追加するとエラーが出なくなります。(ファイル名は拡張子がd.tsであればなんでもいいです)

続き

testHandlerを下のように書き換えると、app.use('/test2/:id',router)のミドルウェアからもidにアクセスできます。(/users/:id/hogeなど同じパラメータ名をもつパスがあるとややこしくなりそうですが...)

app.js
const testHandler=(req,res)=>{
    const {id}=req.params;
    if(!id){
        - res.send("idにアクセスできません");
        
        + //route.paramで格納したidを取り出す
        + _id=req.id;
        + res.send("id:"+_id);
        return;
    }
    res.send("id:"+id);
}

終わりに

Google検索してもGitHub Copilotに聞いても出てこなかったので苦労しました。
公式ドキュメントはやはり偉大。
あと英語読めると便利。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?