content-disposition、content-type、http-errors、mime、mime-types、type-is はすべて、Node.jsアプリケーションにおけるHTTPプロトコルやMIMEタイプの扱いを補助する軽量なユーティリティパッケージです。これらのパッケージは、主にExpressなどのWebフレームワークの内部やミドルウェアで使われ、開発者が手動でHTTPヘッダーやエラーレスポンスを安全かつ正確に構築できるようにします。たとえば、content-dispositionはファイルダウンロード時のContent-Dispositionヘッダーを生成し、http-errorsはHTTPステータスコードに対応した標準的なエラーオブジェクトを提供します。これらは単体ではアプリケーションの主要機能を担いませんが、堅牢で仕様準拠のHTTP通信を実現するための重要な基盤となります。
Node.jsでWebアプリケーションを構築する際、HTTPヘッダーやMIMEタイプの扱いは意外と面倒です。手動で文字列を組み立てると、RFC違反やセキュリティ脆弱性(例:CRLFインジェクション)を引き起こすリスクがあります。content-disposition、content-type、http-errors、mime、mime-types、type-is は、こうした低レベルの処理を安全かつ正確に行うための専門的なユーティリティパッケージです。これらは互いに補完し合い、多くのWebフレームワーク(特にExpress)の内部で広く使われています。以下では、各パッケージの役割と使いどころを具体的なコードとともに解説します。
content-dispositionファイルをダウンロードさせる際、Content-Dispositionヘッダーでファイル名を指定しますが、ユーザー入力(例:ファイル名)をそのまま使うと危険です。content-dispositionは、RFC 6266に準拠した安全なヘッダー生成を提供します。
// content-disposition
const contentDisposition = require('content-disposition');
// 危険なファイル名(改行文字を含む)も安全にエスケープ
const filename = 'report\n.txt';
const header = contentDisposition(filename);
// -> 'inline; filename="report_.txt"; filename*=UTF-8\'\'report%0A.txt'
res.setHeader('Content-Disposition', header);
手動でヘッダーを組み立てると、改行文字が含まれているとCRLFインジェクション攻撃の原因になります。このパッケージを使えば、そうしたリスクを回避できます。
content-typeContent-Typeヘッダーは、MIMEタイプとパラメータ(例:charset)で構成されます。content-typeは、これを正確にパース・再構築します。
// content-type
const contentType = require('content-type');
// ヘッダーをパース
const obj = contentType.parse('text/html; charset=utf-8');
// -> { type: 'text/html', parameters: { charset: 'utf-8' } }
// オブジェクトからヘッダーを再構築
const header = contentType.format(obj);
// -> 'text/html; charset=utf-8'
自分で正規表現で分割すると、引用符や特殊文字の処理を間違えやすいですが、このパッケージはRFC 7231に完全準拠しています。
http-errorsHTTPステータスコードに対応したエラーオブジェクトを簡単に作成できます。Expressのエラーハンドリングと連携しやすい設計です。
// http-errors
const createError = require('http-errors');
// 404エラーを生成
const notFound = createError(404, 'Page not found');
// -> Errorオブジェクト(statusCode: 404, message: 'Page not found')
// 500エラーを生成
const serverError = createError.InternalServerError('Database down');
// Expressのエラーハンドラで使用
app.use((err, req, res, next) => {
res.status(err.status || 500).json({ error: err.message });
});
独自のエラークラスを定義する代わりに、このパッケージを使うことで、HTTP仕様に沿った一貫したエラーレスポンスを実装できます。
mimeファイル拡張子からMIMEタイプを取得したり、逆にMIMEタイプから拡張子を取得したりできます。
// mime
const mime = require('mime');
// 拡張子からMIMEタイプ
const type = mime.getType('file.txt');
// -> 'text/plain'
// MIMEタイプから拡張子
const ext = mime.getExtension('text/html');
// -> 'html'
静的ファイルサーバーを実装する際に、リクエストされたファイルの拡張子に基づいてContent-Typeを設定するのに便利です。
mime-typesMIMEタイプそのものに関する情報を取得するのに特化しています。拡張子操作は不要な場合に使います。
// mime-types
const mimeTypes = require('mime-types');
// MIMEタイプの標準charsetを取得
const charset = mimeTypes.charset('text/html');
// -> 'UTF-8'
// MIMEタイプがテキストベースか判定
const isText = mimeTypes.contentType('text/plain');
// -> 'text/plain; charset=utf-8'(charsetが追加される)
mimeパッケージと異なり、拡張子との双方向マッピングは提供しません。MIMEタイプの属性(例:charset)だけが必要なら、こちらの方が軽量です。
type-isリクエストのContent-Typeヘッダーを検査し、特定のMIMEタイプに一致するかを判定します。ワイルドカードやサブタイプもサポート。
// type-is
const typeis = require('type-is');
// リクエストオブジェクト(headers['content-type']を持つ)を想定
const req = { headers: { 'content-type': 'application/json' } };
// JSONかどうかを判定
if (typeis.is(req, ['json', 'urlencoded'])) {
// 処理
}
// ワイルドカードで判定
if (typeis.is(req, 'application/*')) {
// application/以下のすべてにマッチ
}
APIエンドポイントで、受け付けるボディ形式をバリデーションするミドルウェアを書く際に重宝します。
これらのパッケージは単体ではなく、組み合わせて使うことがよくあります。たとえば、ファイルアップロードAPIでは次のように連携します。
// ファイルアップロードAPIの例
const httpErrors = require('http-errors');
const typeis = require('type-is');
const mimeTypes = require('mime-types');
app.post('/upload', (req, res, next) => {
// 1. リクエストのContent-Typeを検査
if (!typeis.is(req, 'multipart/form-data')) {
return next(httpErrors.BadRequest('Expected multipart/form-data'));
}
// ...ファイル処理...
// 2. ダウンロード用のContent-Dispositionを生成
const contentDisposition = require('content-disposition');
res.setHeader('Content-Disposition', contentDisposition('uploaded-file.jpg'));
// 3. Content-Typeを設定
const contentType = require('content-type');
res.setHeader('Content-Type', contentType.format({
type: 'image/jpeg',
parameters: {}
}));
res.send(fileBuffer);
});
このように、各パッケージが得意な領域をカバーし合うことで、堅牢でメンテナンスしやすいHTTP処理が実現できます。
mime vs mime-types: 拡張子操作が必要ならmime、MIMEタイプの属性だけならmime-typesを使いましょう。両方を同時に使う必要はほとんどありません。Content-DispositionやContent-Typeを文字列連結で組み立てるのは避けましょう。必ず専用パッケージを使ってください。http-errorsを使えば、エラーオブジェクトの形式が統一され、ミドルウェアでの処理が簡単になります。| パッケージ | 主な用途 | 典型的な使用場面 |
|---|---|---|
content-disposition | 安全なContent-Dispositionヘッダー生成 | ファイルダウンロードAPI |
content-type | Content-Typeヘッダーのパース・生成 | リクエスト/レスポンスのMIME処理 |
http-errors | HTTPステータスコード付きエラー生成 | APIエラーレスポンス |
mime | 拡張子 ↔ MIMEタイプ変換 | 静的ファイルサーバー |
mime-types | MIMEタイプのメタデータ取得 | MIME属性(例:charset)の参照 |
type-is | リクエストのMIMEタイプ検査 | ボディ形式のバリデーション |
これらのパッケージはどれも非常に軽量で、目的が明確に分かれています。プロジェクトでHTTP通信を扱うなら、それぞれの役割に応じて適切に使い分けることで、バグやセキュリティ問題を未然に防げます。特に、ユーザー入力が関わるヘッダー構築(例:ファイル名)では、必ずcontent-dispositionのような専用ライブラリを使うことを強く推奨します。手動実装は一見簡単ですが、長期的に見てメンテナンスコストとリスクが高くなります。
mime-typesは、MIMEタイプに関する情報を取得する必要があるが、ファイル拡張子との双方向マッピングは不要な場合に適しています。たとえば、'text/html'の標準的なcharsetを取得するなど、MIMEタイプそのものに関するメタデータ操作に特化しています。mimeよりも軽量で、拡張子操作が不要ならこちらが効率的です。
http-errorsは、HTTPステータスコード(例:404, 500)に対応したエラーオブジェクトを一貫して生成したい場合に最適です。Expressのエラーハンドリングミドルウェアと連携しやすく、エラーメッセージやスタックトレースを含む標準化された形式を提供します。独自のエラークラスを定義する手間を省き、HTTP仕様に沿ったレスポンスを簡単に実装できます。
content-dispositionは、ファイルダウンロード時にContent-Dispositionヘッダーを安全に生成したい場合に選択します。特に、ユーザー入力(例:ファイル名)を含むヘッダー値を構築する際に、RFC 6266に準拠したエスケープ処理を自動で行う点が重要です。手動でヘッダー文字列を組み立てるよりも、セキュリティリスク(例:CRLFインジェクション)を回避できます。
content-typeは、Content-Typeヘッダーの解析または生成が必要な場合に使用します。このパッケージは、MIMEタイプとパラメータ(例:charset=utf-8)を正確に分離・再構築でき、フォーマットエラーを防ぎます。自分で正規表現でパースする代わりに、信頼性の高い標準ライブラリを使うことで、バグのリスクを減らせます。
mimeは、ファイル拡張子からMIMEタイプを取得したり、逆にMIMEタイプから拡張子を取得したりする必要がある場合に選択します。このパッケージは内部でmime-dbを使用しており、広範なMIMEタイプデータベースを備えています。ただし、静的アセット配信など、拡張子ベースのMIME推論が中心の用途に特化しています。
type-isは、リクエストのContent-Typeヘッダーを検査して、特定のMIMEタイプやワイルドカード(例:application/*)に一致するかを判定したい場合に使用します。ミドルウェア内でリクエストのボディ形式をバリデーションする際に便利で、複雑な条件分岐を簡潔に記述できます。手動でヘッダー文字列を比較するより、MIMEの階層構造を正しく考慮した判定が可能です。
The ultimate javascript content-type utility.
Similar to the mime@1.x module, except:
mime-types simply returns false, so do
var type = mime.lookup('unrecognized') || 'application/octet-stream'.new Mime() business, so you could do var lookup = require('mime-types').lookup..define() functionality.lookup(path)Otherwise, the API is compatible with mime 1.x.
This is a Node.js module available through the
npm registry. Installation is done using the
npm install command:
$ npm install mime-types
This package considers the programmatic api as the semver compatibility. Additionally, the package which provides the MIME data
for this package (mime-db) also considers it's programmatic api as the semver contract. This means the MIME type resolution is not considered
in the semver bumps.
In the past the version of mime-db was pinned to give two decision points when adopting MIME data changes. This is no longer true. We still update the
mime-db package here as a minor release when necessary, but will use a ^ range going forward. This means that if you want to pin your mime-db data
you will need to do it in your application. While this expectation was not set in docs until now, it is how the pacakge operated, so we do not feel this is
a breaking change.
If you wish to pin your mime-db version you can do that with overrides via your package manager of choice. See their documentation for how to correctly configure that.
All mime types are based on mime-db, so open a PR there if you'd like to add mime types.
var mime = require('mime-types')
All functions return false if input is invalid or not found.
Lookup the content-type associated with a file.
mime.lookup('json') // 'application/json'
mime.lookup('.md') // 'text/markdown'
mime.lookup('file.html') // 'text/html'
mime.lookup('folder/file.js') // 'application/javascript'
mime.lookup('folder/.htaccess') // false
mime.lookup('cats') // false
Create a full content-type header given a content-type or extension.
When given an extension, mime.lookup is used to get the matching
content-type, otherwise the given content-type is used. Then if the
content-type does not already have a charset parameter, mime.charset
is used to get the default charset and add to the returned content-type.
mime.contentType('markdown') // 'text/x-markdown; charset=utf-8'
mime.contentType('file.json') // 'application/json; charset=utf-8'
mime.contentType('text/html') // 'text/html; charset=utf-8'
mime.contentType('text/html; charset=iso-8859-1') // 'text/html; charset=iso-8859-1'
// from a full path
mime.contentType(path.extname('/path/to/file.json')) // 'application/json; charset=utf-8'
Get the default extension for a content-type.
mime.extension('application/octet-stream') // 'bin'
Lookup the implied default charset of a content-type.
mime.charset('text/markdown') // 'UTF-8'
A map of content-types by extension.
A map of extensions by content-type.