Closed5
Express調査メモ
-
https://github.com/okunokentaro/koa-poc/tree/express-poc
- koaが業務要件に合致しなかったのでExpressを調査する
- バージョンは大人の事情でNode
12.18.3
、Express4.17.11
に固定
200を返す最小構成
-
app.use
コールバックの中でreq, res, next
引数が得られるので、それでよしなにやる-
res.status(200).end()
で200を返却
-
res
とnext
を使わない複数のmiddleware
-
https://github.com/okunokentaro/koa-poc/blob/552a6304471c0cf80ad265e482a2f0562f773383/src/main.ts#L6-L12
-
middleware 100
を出力したまま返ってこない
-
res.status(n).end()
-
https://github.com/okunokentaro/koa-poc/blob/add45bd6ab313e530c7644465e3c6041dd81bb51/src/main.ts#L6-L13
- 後続のmiddlewareは機能しない
-
https://github.com/okunokentaro/koa-poc/blob/6bffd2cdc0a1142e10a1c89989f36f7480995b52/src/main.ts#L6-L13
- 先行のmiddlewareで
next()
していないため、後続でres.status(n).end()
を呼んでもmiddleware自体が発火しない
- 先行のmiddlewareで
-
https://github.com/okunokentaro/koa-poc/blob/db136b4bb57a39775d2d41caed7d3a4e973427fa/src/main.ts#L6-L14
- 先行middlewareで
next()
が呼ばれているのでログ出力は下記となる
- 先行middlewareで
middleware 100
middleware 200
-
https://github.com/okunokentaro/koa-poc/blob/b1f59bb3ebcb0352fd3324f8ab34e588c1cf0102/src/main.ts#L8
-
end()
を呼ばないと、後続のres.status(500).end()
で上書きして500にできる
-
エラーの扱い
-
https://github.com/okunokentaro/koa-poc/blob/5493a91d190cadd908bfcf738be5ec8afdb5c81f/src/main.ts#L8
- middleware内の例外はそのままUncaught扱いになる
- これが500になったりはしない
-
https://github.com/okunokentaro/koa-poc/blob/express-poc/src/main.ts#L15-L27
-
next()
をnext(error)
にすると、後続のmiddlewareはreq, res, next
の引数順がerr, req, res, next
になる - TypeScript的にはアノテーションなしで推論ができないので好きじゃないシグネチャデザイン
-
- 複数のmiddlewareがあって最初にエラーが出た場合後続のエラーハンドリング以外のmiddlewareはどうなるのか
-
req
がerr
になると困る
-
middleware 100
middleware 300
Error: middleware 110 Error
-
https://github.com/okunokentaro/koa-poc/blob/7788a2d526dd57acbfe124dd3a640729070b2fd2/src/main.ts#L11
-
next()
に戻すと正常時処理として扱われる
-
middleware 100
middleware 200
middleware 300
Error: middleware 220 Error
- 複数エラーハンドラーがある場合は?
- https://github.com/okunokentaro/koa-poc/blob/cb65c2ad3270f036385ab847c7412fffa055e7a4/src/main.ts#L15-L36
-
next()
だと、もう後続のエラーハンドラーには処理が送られない - エラーハンドラー内の
next()
はエラーハンドリング続行を希望するのであれば必ずnext(err)
にする必要がある- この場合の処理順は下記
middleware 100
middleware 200
Error: middleware 110 Error
middleware 300
Error: middleware 110 Error
- エラーハンドリングmiddlewareと正常系middlewareの登録混在について
- https://github.com/okunokentaro/koa-poc/blob/32894b46a44cf4971ac2abe771adb62745cd5c44/src/main.ts#L6-L43
-
app.use()
に混ぜて登録するとどうなるか-
next()
の場合は引数3種の後続middlewareへ進む -
next(err)
の場合は引数4種の後続middlewareへ進む- 後続がないのであれば終了
- エラーハンドラー→正常系、正常系→エラーハンドラーへの行き来は
next()
の引数有無と後続middleware引数記述数で決定する- TypeScript的にはかなり気持ち悪いが、まぁ10年前のデザインなのでそういうもんということで
-
結論
-
try catch
を書いただけでいい感じにInternal Server Errorにしてくれたりはしない- そういうmiddlewareを探すか自作して
app.use()
に登録しておくかしないといけない
- そういうmiddlewareを探すか自作して
- ザックリとトップレベルでの
catch
をして、それによってcatch(e) { next(e) }
するのがよさそう-
catch(e) { /* ここ */ }
でのハンドリングをするより、さっさとnext(e)
で飛ばして、エラーハンドリング用middlewareに任せたほうが、それぞれの記述はすっきりする - トップレベルcatchはどうやら必要そう(OSSなどの野良middlewareを探せばなんかあるかもしれないが、それなら自作したほうがトータルで把握しやすい)
- middleware内で400とか500分岐をすると
.end()
管理やnext()
管理(next呼ぶ呼ばない)が発生してつらいので、一律でnext()
するルールに倒して、末端middlewareでエラーあれば4xx, 5xx, なければ2xxという倒し方にしたほうがそれぞれのエンドポイントごとの責務がはっきりする
- middleware内で400とか500分岐をすると
-
- API単位で
res.status(404).end(); return;
とかしている部分はさっさとthrow new NotFoundError()
とかにするのがよい気がした
このスクラップは2021/07/13にクローズされました