MIME タイプと Content-Type ヘッダーのクイックガイド
JavaScript アプリが {"status": "success"} を受信しても、ブラウザがそれを JSON ではなくプレーンテキストとして扱う場合、それは MIME タイプの問題に直面しています。CSS ファイルの読み込みに失敗したり、画像が表示されずにダウンロードされたり、API が予期しない形式でデータを返したりする場合も同じ問題が発生します。これらの問題は、Content-Type ヘッダーと MIME タイプの設定ミスに起因します。これらは、ブラウザが受信するすべてのデータを解釈するために使用するシステムです。
このガイドでは、HTTP メディアタイプの仕組み、モダンな Web 開発に必要なタイプ、適切なタイプ処理と X-Content-Type-Options ヘッダーによるセキュリティ脆弱性の防止方法について説明します。
重要なポイント
- ブラウザはファイル拡張子ではなく Content-Type ヘッダーに依存してレスポンスを解釈する
- 不正な MIME タイプは CSS の失敗、JavaScript のブロック、API パースエラーを引き起こす
- X-Content-Type-Options ヘッダーは危険な MIME スニッフィング攻撃を防止する
- モダンブラウザはセキュリティのために MIME タイプチェックを厳格に実施する
MIME タイプの構造を理解する
MIME タイプ(Multipurpose Internet Mail Extensions type)は、スラッシュで区切られた2つの部分で構成されます:
type/subtype
type は一般的なカテゴリ(text、image、application)を表し、subtype は正確な形式(html、jpeg、json)を指定します。オプションのパラメータで追加情報を提供できます:
text/html; charset=utf-8
application/json; charset=utf-8
重要な原則: ブラウザはファイル拡張子ではなく Content-Type ヘッダーを使用して、レスポンスの処理方法を決定します。data.txt という名前のファイルが Content-Type: application/json で提供される場合、プレーンテキストではなく JSON として解析されます。
フロントエンド開発に必須の MIME タイプ
HTML、CSS、JavaScript
- text/html - HTML ドキュメント(常に charset を含める)
- text/css - スタイルシート(
<link>タグが機能するために必要) - text/javascript - JavaScript ファイル(application/javascript に代わる最新の標準)
API とデータ形式
- application/json - JSON データ(最も一般的な API 形式)
- application/xml - XML ドキュメント
- application/x-www-form-urlencoded - 標準的なフォーム送信
- multipart/form-data - ファイルアップロードを含むフォーム
画像とメディア
- image/jpeg、image/png、image/gif - 標準的な画像形式
- image/svg+xml - SVG グラフィックス
- image/webp、image/avif - モダンな最適化形式
- video/mp4、audio/mpeg - 一般的なメディアタイプ
フォント
- font/woff2、font/woff - Web フォント形式
- font/ttf、font/otf - 従来のフォントファイル
サーバーが Content-Type ヘッダーを設定する方法
Web サーバーは複数の方法で Content-Type ヘッダーを決定します:
- ファイル拡張子のマッピング - サーバーは
.htmlをtext/htmlに、.jsonをapplication/jsonにマッピングする - 明示的な設定 - 開発者がプログラムでヘッダーを設定する
- デフォルトのフォールバック - 不明なファイルはデフォルトで
application/octet-streamになる
Node.js/Express での例:
res.setHeader('Content-Type', 'application/json; charset=utf-8');
res.json({ status: 'success' });
Nginx や Apache のような静的ファイルサーバーは、設定ファイルを使用して拡張子を MIME タイプにマッピングします。CDN やオブジェクトストレージサービス(S3、Cloudflare)は通常、ファイル拡張子に基づいてこれらを自動的に設定します。
Discover how at OpenReplay.com.
MIME タイプが間違っている場合に起こること
不正な Content-Type ヘッダーは、即座に目に見える問題を引き起こします:
- CSS が無視される: CSS を
text/plainとして提供すると、スタイルの読み込みが妨げられる - JavaScript がブロックされる: 間違ったタイプは CORS エラーや実行の失敗を引き起こす
- JSON がテキストとして解析される: API がオブジェクトではなく文字列を返す
- 画像がダウンロードされる: ブラウザが表示する代わりにファイルをダウンロードする
- セキュリティ脆弱性: 不正なタイプは XSS 攻撃を可能にする
モダンブラウザはセキュリティのために MIME タイプチェックを厳格に実施します。Chrome や Firefox は、不正な Content-Type ヘッダーを持つスタイルシートやスクリプトの実行を拒否し、「Refused to apply style from ’…’ because its MIME type (‘text/plain’) is not a supported stylesheet MIME type.」のようなコンソールエラーを表示します。
セキュリティ: MIME スニッフィングと X-Content-Type-Options
MIME スニッフィングは、ブラウザが Content-Type ヘッダーを無視し、コンテンツを調べてファイルタイプを推測する際に発生します。時には役立つこともありますが、この動作は深刻なセキュリティリスクを生み出します。
攻撃者は、HTML と JavaScript を含む image.jpg という名前のファイルをアップロードする可能性があります。サーバーが Content-Type: image/jpeg を送信しても、ブラウザが HTML コンテンツを検出してレンダリングすると、悪意のあるスクリプトが実行されます。
MIME スニッフィングの防止
常に X-Content-Type-Options ヘッダーを含めてください:
X-Content-Type-Options: nosniff
このヘッダーは、ブラウザに宣言された Content-Type を尊重するよう強制し、推測を防ぎます。特に以下の場合に重要です:
- ユーザーがアップロードしたコンテンツ
- API レスポンス
- 動的コンテンツ生成
- CDN から提供されるファイル
実装例:
// Express ミドルウェア
app.use((req, res, next) => {
res.setHeader('X-Content-Type-Options', 'nosniff');
next();
});
よくある問題のトラブルシューティング
問題: API が JSON をテキストとして返す
解決策: サーバーが Content-Type: application/json を送信することを確認する
問題: フォントがクロスオリジンで読み込めない
解決策: フォントファイルに正しい MIME タイプと CORS ヘッダーを設定する
問題: SVG 画像がテキストとして表示される
解決策: text/xml ではなく image/svg+xml を使用する
問題: 表示ではなくダウンロードがトリガーされる
解決策: Content-Disposition: attachment ヘッダーを削除し、正しい MIME タイプを使用する
デバッグツール
- ブラウザの DevTools ネットワークタブで実際の Content-Type ヘッダーを表示
curl -I [url]でレスポンスヘッダーを検査- オンライン MIME タイプバリデーターでサーバー設定を確認
まとめ
正しい MIME タイプと Content-Type ヘッダーは、Web 機能の基本です。これらは、ブラウザがコンテンツを解析、実行、またはダウンロードするかを決定します。適切な HTTP メディアタイプを設定することで、レンダリングの失敗、API エラー、セキュリティ脆弱性を防ぎます。覚えておいてください: ブラウザはファイル拡張子よりも Content-Type ヘッダーを信頼し、MIME スニッフィングはセキュリティリスクを生み出し、X-Content-Type-Options: nosniff ヘッダーは本番アプリケーションに不可欠です。
信頼性の高い Web アプリケーションのために、常に Content-Type ヘッダーを明示的に設定し、デプロイメントパイプラインで MIME タイプを検証し、異なるブラウザでテストして一貫した動作を確保してください。
よくある質問
ブラウザはファイル拡張子を無視し、Content-Type ヘッダーのみを使用します。サーバーはレスポンスヘッダーで Content-Type: application/json を明示的に送信する必要があります。サーバー設定を確認するか、バックエンドコードでプログラム的にヘッダーを追加してください。
このヘッダーがない場合、ブラウザは MIME スニッフィングを実行し、安全なファイルタイプに偽装された悪意のあるコードを実行する可能性があります。これは特にユーザーアップロードで XSS 脆弱性を生み出します。常に X-Content-Type-Options: nosniff を設定して、ブラウザに宣言された Content-Type を尊重させてください。
application/javascript はかつて推奨されていましたが、現在の HTML 仕様では JavaScript ファイルに text/javascript を推奨しています。モダンブラウザは両方を受け入れますが、text/javascript は最大限の互換性を保証し、現在の標準に従っています。
Gain control over your UX
See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.