はじめに
これは肖佳先生の書籍『HTTP抓包实战』を読んだ後にまとめた HTTP に関する学習メモです。主に HTTP メッセージ関連の内容を整理しました。(記録:読書+本記事作成に5日間かかりました)
HTTPメッセージ構造
HTTPメッセージには「リクエストメッセージ(Request)」と「レスポンスメッセージ(Response)」の2種類があります。
HTTPリクエストメッセージ(Request)
HTTPリクエストは以下の3つのパートで構成されます:
開始行(Request line):リクエストメソッド、URI、HTTPバージョン
例:GET https://blog.yexca.net/ HTTP/2
ヘッダ部(Header):追加情報や制御情報を含む
ボディ部(Body):フォームデータやファイルなどの実データ(※省略される場合もあり)
注意:ヘッダとボディの間には必ず空行が入ります。
HTTPレスポンスメッセージ(Response)
HTTPレスポンスも同様に3つのパートから成ります:
ステータス行(Response line):HTTPバージョン、ステータスコード、ステータスメッセージ
例:HTTP/2 200 OK
ヘッダ部(Header)
ボディ部(Body)
こちらもヘッダとボディの間には空行が入ります。
HTTPリクエストメソッドとステータスコード
URLの構造
URL(Uniform Resource Locator)は、インターネット上のリソースを一意に識別するためのものです。
基本構成:
|
|
項目 | 説明 |
---|---|
スキーム | http, https, ftp などの通信プロトコル |
ホスト | ドメインまたは IP アドレス |
ポート番号 | 通常 HTTP は 80、HTTPS は 443(省略可) |
パス | リソースのパス |
クエリ文字列 | ?以降のパラメータ(例:?id=1&name=test ) |
アンカー | ページ内リンク(例:#top ) |
主なHTTPメソッド
No. | メソッド | 説明 |
---|---|---|
1 | GET | サーバーからデータを取得する |
2 | HEAD | GETと似ているが、レスポンスボディは返されない(ヘッダのみ) |
3 | POST | サーバーにデータを送信(例:フォーム送信、ファイルアップロードなど) |
4 | PUT | リソースを新しく作成または完全に置き換える |
5 | DELETE | 指定したリソースを削除する |
GETとPOSTの違い
データの送信位置
GET は URL の末尾(?
以降)に付ける。POST はボディに含まれる。サイズ制限
GET は URL 長に制限あり(ブラウザ依存)。POST は基本的に制限なし。取得方法
GET はrequest.queryString
、POST はrequest.form
などを使う。
HTTPステータスコード
HTTPレスポンスの中に含まれる数字で、リクエストの結果を示すものです。
コード範囲 | 意味 |
---|---|
1XX | 情報(処理中) |
2XX | 成功 |
3XX | リダイレクト |
4XX | クライアントエラー |
5XX | サーバーエラー |
よく使われるステータスコード
コード | 説明 |
---|---|
200 OK | リクエストが成功した |
301/302 | 恒久的/一時的リダイレクト。Location ヘッダに新しいURLが含まれる |
304 | コンテンツが更新されていない(キャッシュ利用可能) |
401 | 認証が必要(Basic認証など) |
403 | アクセス禁止(アクセスは認識されたが拒否された) |
404 | リソースが見つからなかった |
500 | サーバー内部エラー(スクリプトエラーなど) |
503 | 一時的にサービス利用不可(メンテ中など) |
206 Partial Content(部分的コンテンツ)
- サーバーがリクエストされた一部のコンテンツを返した場合
- 動画のストリーミングやダウンロード再開などに使われる
- ヘッダに
Range
(要求)やContent-Range
(応答)が含まれる
301 vs 302(リダイレクト)
- 301: 永続的な移動 → 検索エンジンもリンク先を更新
- 302: 一時的な移動 → ユーザーセッションやログイン時など
304 Not Modified(未更新)
- ブラウザキャッシュが最新 → サーバーは新しいデータを送らない
400 Bad Request(不正リクエスト)
- リクエストの構文エラー(例:クッキー不正、フォーム誤送信など)
401 Unauthorized(認証エラー)
- 認証ヘッダがない/不正な場合。Basic 認証などで返される
403 Forbidden(禁止)
- サーバーがリクエストを明示的に拒否したい時に使用(理由は非公開)
404 Not Found(見つからない)
- 該当リソースなし
- 例:非ログイン状態では一部URLが 404 を返す(実際は制限付き)
500 Internal Server Error(サーバー内部エラー)
- プログラムのバグ、DB接続エラー、例外など
503 Service Unavailable(サービス一時停止)
- 過負荷やメンテナンス時など
その他のコードを見るには
HTTP ヘッダー構成
ヘッダーの形式は「キー: 値
」で 1 行ずつ記述され、それぞれが特定の機能を持ちます。
キャッシュ関連ヘッダー
HTTP リクエスト・レスポンスの両方にキャッシュ制御に関連するヘッダーがあります。
HTTP キャッシュとは、同じリソースを再び取得する際にローカルのキャッシュを使用して、再ダウンロードを避ける仕組みです。
Cookie
Cookie は HTTP のキャッシュ制御手段のひとつで、key=value
形式のデータです。
- ブラウザ → サーバー:
Cookie:
ヘッダーで Cookie を送信 - サーバー → ブラウザ:
Set-Cookie:
ヘッダーで Cookie を設定
例:ip_country=CN
Accept
Accept ヘッダーは、クライアントが受け入れ可能な MIME タイプを通知します。
例:Accept: text/html
は HTML を受信可能という意味です。
ワイルドカード(*
)を使って任意タイプを表現できます。
例:Accept: text/html, */*;q=0.8
Accept-Encoding
圧縮方式に関するヘッダーで、クライアントが対応する圧縮形式を通知します。
例:Accept-Encoding: gzip, deflate
Accept-Language
Accept-Language は、クライアントが受け入れられる言語の一覧を通知します。
例:Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4,zh-TW;q=0.2
言語(日本語、中国語など)と文字コード(UTF-8、GBK など)は別物です。
User-Agent
User-Agent は、クライアントの環境情報(OS、CPU、ブラウザバージョンなど)を通知する文字列です。
例:User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:103.0) Gecko/20100101 Firefox/103.0
これを書き換えることで、他のブラウザやデバイスを装ったリクエストも可能になります。
Referer(リファラー)
リファラーはアクセス元の URL を示し、どこから来たのかをサーバー側が判断できます。
アクセス解析や不正リンク検出などに利用されます。
Connection
HTTP/1.1 以降は、デフォルトで Connection: Keep-Alive
によって TCP 接続が継続されます。
この接続維持時間は Web サーバー側(Apache など)で設定可能です。
Host
Host ヘッダーは、リクエスト対象のホスト名とポート番号を明示します。HTTP/1.1 以降は必須です。
ポートが 80 の場合は省略可能です。
HTTP キャッシュの仕組み
HTTP のキャッシュは、主にブラウザやプロキシサーバーで動作します。
キャッシュの利点
- 不要なデータ転送の削減
- レスポンス速度の向上
- サーバー負荷の軽減
キャッシュの鮮度判断方法
方法①:If-Modified-Since / Last-Modified
クライアントが If-Modified-Since
ヘッダーでローカルの更新日時を通知します。
サーバーが Last-Modified
ヘッダーと比較し、変更がなければ 304 Not Modified
を返します。
方法②:If-None-Match / ETag
クライアントが If-None-Match
で ETag(ハッシュ値)を送信し、サーバーが照合して同一なら 304
を返します。
キャッシュ関連ヘッダー一覧
リクエスト側
ヘッダー名 | 説明 |
---|---|
Cache-Control: max-age=0 | キャッシュの有効期限(秒) |
If-Modified-Since: Tue, 28 Jun 2022 … | 最終更新日時 |
If-None-Match: “etag-value” | キャッシュの ETag |
Cache-Control: no-cache | キャッシュを使用しない |
Pragma: no-cache | 上記と同じ(HTTP/1.0 用) |
レスポンス側
ヘッダー名 | 説明 |
---|---|
Cache-Control: public | 共有キャッシュ可(プロキシ等) |
Cache-Control: private | ユーザー固有キャッシュ |
Cache-Control: no-cache | 必ず再検証 |
Cache-Control: no-store | 完全非キャッシュ(機密データ用) |
Cache-Control: max-age=60 | 相対時間での有効期限(秒) |
Date: Thu, 01 Sep 2022 … | サーバー送信日時 |
Expires: Thu, 01 Sep 2022 … | 絶対時間による有効期限 |
Last-Modified: Tue, 28 Jun 2022 … | 最終更新日時 |
ETag: “etag-value” | キャッシュ判定用の識別子 |
※ 通常は Cache-Control 優先、なければ Expires が参照されます。
ETag とは?
- 「Entity Tag」の略で、ファイル内容から生成されるハッシュ文字列です
- 内容が変われば ETag も変わるので、更新判定が高精度
ETag は、Last-Modified
では対応できない問題(ミリ秒単位の変更や内容が同じ等)を補います。
強制再読み込みとキャッシュ
Ctrl + Shift + R
:強制リロード(キャッシュ無効)Ctrl + R
:再読み込み(条件付き GET)
アドレスバーから直接 URL 入力時は、ブラウザは「キャッシュ命中(cache hit)」としてサーバーと通信せず、ローカルキャッシュを使用します。
パブリックとプライベートキャッシュ
種類 | ヘッダー | 説明 |
---|---|---|
パブリック | Cache-Control: public | 共有可能(例:プロキシキャッシュ) |
プライベート | Cache-Control: private | 個別ユーザーのローカルキャッシュ |
HTTP 圧縮と URL エンコード
HTTP 圧縮の概要
Web サーバーとブラウザ間で送受信される「テキストデータ」を圧縮する技術です。
例:HTML / CSS / JavaScript など → gzip 圧縮
圧縮とエンコードの違い
HTTP ボディの「Content-Encoding」は、単にサイズ削減の gzip 圧縮だけでなく、暗号化なども可能です。
つまり、HTTP 圧縮は HTTP エンコーディングの一種です。
圧縮の流れ
クライアントは
Accept-Encoding: gzip, deflate
で対応可圧縮形式を提示サーバー側は
- 元のレスポンスを生成
- ボディ部分を gzip 圧縮
Content-Encoding: gzip
を付与- ブラウザへ返却
ブラウザは Content-Encoding を見てデコードし、元データを表示
※リクエストの圧縮は一般的ではない
Content-Encoding 種類
エンコーディング | 内容 |
---|---|
gzip | GNU Gzip 形式 |
compress | UNIX compress |
deflate | zlib 圧縮 |
identity | 無圧縮(指定なし時のデフォルト) |
gzip / deflate は一般的な可逆圧縮で、gzip のほうが効率が良く広く使われています。
Cookieメカニズムの仕組み
HTTPはステートレスなプロトコルであり、同じブラウザからの複数のリクエストでもサーバー側では独立したものとして扱われ、関連性は持ちません。
セッションとCookie
サーバーがクライアントの識別を行うには、状態管理が必要になります。HTTPがステートレスであるため、クライアントとサーバーが共同で状態を管理する「セッションメカニズム」が使用されます。
- クライアントが初めてアクセスした際、サーバーはセッションIDを生成し、レスポンスに含めて返す
- ブラウザはセッションIDを保存し、以後のリクエストに含める
- サーバーはセッションIDによって同じクライアントかどうかを判別する
このセッションの仕組みにCookieが使われています。
Cookieとは
Cookieとは、ブラウザが少量のデータを key=value
の形式で保持する仕組みです。複数のCookieは ;
で区切られ、リクエスト時に自動的に送信されます。
主に認証情報やユーザー設定の保持、または広告追跡・ターゲティングなどに利用されます。
現在では、EUなどの国ではCookieの使用に関する法的制限があり、ユーザーの同意が必要です。
Cookieの属性
Expires
有効期限を指定。未指定の場合、ブラウザを閉じると削除されます。Path
Cookieが有効なパス範囲を指定します。例:/test/
に設定すると、/test/
配下でのみ有効。HttpOnly
JavaScript からアクセス不可にする属性で、XSS対策に効果的。ログイン用Cookieには必須。
Cookieの種類と保存場所
種類 | 説明 |
---|---|
セッションクッキー | 一時的なCookie。ブラウザを閉じると削除される |
永続クッキー | 有効期限があり、再起動しても保持される |
ブラウザごとに保存場所は異なり、例:Linux + Firefox の場合~/.mozilla/firefox/xxxxxxxx.default-release/cookies.sqlite
HTTP基本認証
HTTPはステートレスであるため、Cookieによる認証のほか、Basic認証(基本認証)も用いられます。
クライアントは ユーザー名:パスワード
をBase64でエンコードし、Authorization
ヘッダーに含めて送信します。
基本認証の流れ
- サーバーが
401 Unauthorized
を返し、WWW-Authenticate
ヘッダーで認証を要求 - ブラウザがログインダイアログを表示し、認証情報を取得
- 入力されたユーザー名とパスワードをBase64エンコードし、リクエストに含めて送信
家庭用ルーターや一部のREST APIではこの方式がよく使われます。
例:curl -u ユーザー名:パスワード https://example.com
基本認証の欠点
- ステートレスなので、リクエストごとに認証が必要
- Base64は簡単に復号できるため、パスワードが平文で送信されるのと同等。HTTPS必須
- 明示的にログアウトできない(Cookieと違って期限切れの仕組みがない)
- リプレイ攻撃 に弱い
Digest認証(要約認証)
Digest認証は、基本認証のセキュリティ上の欠点を補った改良方式です。
- パスワードの代わりにハッシュ値を送信することで、平文送信を回避
- サーバー側で nonce(ワンタイムトークン)を生成してリプレイ攻撃を防止
- クライアントも nonce を用いることでサーバー認証が可能
- コンテンツの整合性チェックにも対応