ルータは表一つだ
一言でいうと
フレームワークのルーターは魔法ではなく、1枚の表です。メソッドとパスをキーに、 ハンドラーを値にして探します。その表が何を区別するかが、APIの性格を決めます。
なぜ必要なのか: 404と405は別の出来事です
/itemsにDELETEを送ったとします。パスはあるのに、そのメソッドは受け付けていません。
ここで404を返すと、クライアントは「そんなリソースはないのだな」と読んで、パスを疑います。
405を返せば「リソースはあるが、この操作はできないのだな」と読みます。デバッグに
かかる時間はここで分かれます。
フレームワークを使えば、この区別は無料で手に入ります。だから自分で作ってみないと、 そういう区別があることにすら気づかないまま通り過ぎてしまいます。
表をどう置くのか
const routes = [
{ method: 'GET', path: /^\/healthz$/, handler: health },
{ method: 'GET', path: /^\/items$/, handler: listItems },
{ method: 'POST', path: /^\/items$/, handler: createItem },
{ method: 'GET', path: /^\/items\/(\d+)$/, handler: getItem },
];
探す順序は2段階に分かれます。まずパスが合うものをすべて集め、その中から
メソッドが合うものを選びます。パスが1つも合わなければ404、パスは合うのに
メソッドがなければ405です。一度にmethod + pathで探すと、この区別は消えてしまいます。
現場では
NestでもExpressでも、この表をデコレーターやapp.get()で埋めるだけで、構造は
同じです。だからルーティングが効かないときに見る場所も同じで、登録順序とパターンの
範囲です。広いパターン(/*)を上に置くと、下のルールには永遠に届きません。
Envoyのラボで見たのとまったく同じ落とし穴で、実際にもっとも多い報告です。
フレームワークを初めて読むときは、ルーターから見ます。それがそのフレームワークの 世界の分け方だからです。