Node.js 24.21.0 の MIMEType.parse で Content-Type を try/catch なしに扱う
外部から受け取った Content-Type をパースする処理は、地味に例外源になります。Node.js には標準で util.MIMEType がありますが、コンストラクタは不正な入力で TypeError を投げるため、素直に書くと必ず try / catch が付きます。
2026年9月8日にリリースされた Node.js 24.21.0 (LTS) で、これを投げない形に書き換えられる静的メソッドが入りました。リリースノートの Notable Changes に次の1行があります。
1 | |
何が変わるのか
公式 API ドキュメントによれば、MIMEType.parse(string) の戻り値は <MIMEType> | <null> で、不正な入力では例外ではなく null を返します。コンストラクタ側の挙動は従来どおりで、不正な入力には TypeError が投げられます。
つまり書き分けはこうなります。
1 | |
差は小さく見えますが、例外を制御フローに使わずに済むのが効きます。とくにリクエストごとに未検証のヘッダを見るサーバ側では、try ブロックが入れ子になるのを避けられます。
まず手元の版で挙動を確かめる
いきなり parse を書く前に、自分の Node にその静的メソッドがあるかを確認してください。筆者の環境は v24.11.1 で、次のようになりました。
1 | |
実行結果です。
1 | |
クラス自体はあるのに、静的メソッド parse は undefined です。24.21.0 で追加されたものなので、同じ 24 系でもそれ以前のパッチ版には入っていません。ここを確かめずに MIMEType.parse(...) と書くと TypeError: util.MIMEType.parse is not a function になり、「不正な MIME だったのか、メソッドが無かったのか」が区別しにくい形で落ちます。
同じ v24.11.1 でコンストラクタ側を試すと、想定どおりの挙動でした。
1 | |
注目したいのは正規化です。入力の text/html; charset=utf-8 は、文字列化すると text/html;charset=utf-8(セミコロン後の空白が落ちる) になります。ヘッダ値を比較したり、そのまま別のレスポンスへ転記したりするときに、元の文字列とは一致しないことを見込んでおいてください。
エラーメッセージが invalid at 3 と位置まで出すのも実測で分かった点です。ログに出す場合、この位置情報は入力のどこで壊れたかの手がかりになります。
版差を吸収して書く
24.21.0 未満も動かす必要があるなら、片方向のフォールバックで吸収できます。parse があればそれを、無ければコンストラクタを囲って null に寄せる形です。
1 | |
このコードは v24.11.1 で実行し、上記の出力になることを確認しています。呼び出し側は常に null 判定だけを書けばよくなるので、後日ランタイムを上げたときに呼び出し側を直す必要がありません。
使いどころと、使わないほうがよいところ
使いどころは、外から来る値を扱うときです。アップロードされたファイルの Content-Type、fetch のレスポンスヘッダ、設定ファイルに書かれた MIME 文字列など、壊れていることが想定内の入力に向きます。
逆に、自分が定数として持っている MIME 文字列にまで parse を使って null 分岐を書くのは過剰です。そこが null になるのはコードのバグであって、実行時に握りつぶすべき状況ではありません。コンストラクタが投げてくれたほうが、原因に早く辿り着けます。
もう1点。MIMEType は MIME の構文を検証するだけで、その MIME が実在するタイプかどうかは見ません。foo/bar は構文としては妥当なので、parse は null を返さずにオブジェクトを返します。実在タイプの検証が必要なら、それは別の層の仕事です。
まとめ
new MIMEType()は不正入力でTypeError、MIMEType.parse()はnullparseは Node.js 24.21.0 (LTS, 2026-09-08) で追加された(PR #64965)。同じ 24 系でも v24.11.1 には無い- 導入前に
typeof MIMEType.parse === 'function'で存在確認をする。無い版で呼ぶと、原因の分かりにくいTypeErrorになる - 文字列化ではセミコロン後の空白が落ちるため、元のヘッダ文字列との一致は前提にしない
まずやることは1つです。node -e "console.log(typeof require('node:util').MIMEType.parse)" を実行して、自分の環境が function を返すかを確かめてください。undefined なら、この記事のフォールバック版から入るのが安全です。
このバージョンはその範囲に入るのか
依存の話でいちばん間違えやすいのは ^1.2.3 や ~1.2.3 がどこまでを許すかです(^0.2.3 のようにメジャーが 0 のときは規則が変わります)。範囲とバージョンを貼ると、下限・上限に展開したうえで一致・不一致とその理由を表示するsemver 範囲判定ツールを置いています。ブラウザの中だけで動き、入力はどこにも送信しません。