ただの技術メモ

個人備忘録

HTTP/1.1の通信の生データを見る

HTTP通信は以下の図のように、開始行・HTTPヘッダー・改行を挟んでbodyというような形式でやり取りをします。

f:id:chann_r:20211212172404p:plain
HTTPリクエスト・レスポンス

このHTTPメッセージの形式自体は分かっていますが、実際にどうやって通信しているのか気になったので、それを追ってみます。

MDNのドキュメントによると、HTTP1.1以前までは全てのやり取りがASCIIでエンコードされたテキスト情報で行われるようです。

HTTP メッセージは ASCII でエンコードされたテキスト情報で構成されており、複数の行にまたがります。

developer.mozilla.org

ASCIIについて確認しておきます。

ASCIIコードとはアルファベットや数字、記事などを記録した文字コードの1つです。

0番目から127番目までの番号(16進数に変換して表すこともある)について、各番号がどの文字を意味するかという対応関係を定めている。

f:id:chann_r:20211213142104j:plain
ASCIIコード表

このコードに従い、文字などを変換することで通信・文字情報の処理が容易になります。

実際にHTTP1.1の通信がASCIIコードでエンコードされたテキスト情報でやり取りされていることをパケットをキャプチャして確認してみます。

ツールにはWiresharkというパケットキャプチャツールを使います。

Macの場合、以下でインストールできるかと思います。

brew install --cask wireshark

Wiresharkを開いて、使用中のネットワーク環境がWi-Fiであれば「Wi-Fi」を選択します。

f:id:chann_r:20211212173857p:plain
インターフェースの選択画面

すると、キャプチャが始まるので、ターミナルでCurlを使ってPOSTリクエストを送ります。

curl -X POST  -d "foo=bar" http://httpbin.org/post

再度Wiresharkに戻り、左上の赤いボタンからパケットキャプチャを止めます。

f:id:chann_r:20211212174342p:plain

検索窓から「http」を検索して、該当するパケットを探します。

画面上部の2つがCurlで行ったリクエストとレスポンスです。 今リクエストを選択しているので、画面中部にはリクエストでキャプチャした各プロトコルとデコードされた内容が表示されています。

f:id:chann_r:20211212174702p:plain
リクエストのパケット

画面下部にはリクエストされる時に実際使われているASCIIでエンコードされた文字列が表示されています。

画面中部と画面下部でそれぞれ青くハイライトされている部分は連動していて、それぞれデコードされた文字列と該当するASCIIでエンコードされた文字列になっています。

画面中部の「Hypertext Transfer Protocol」と「HTML Form URL Encoded: application/x-www-form-urlencoded」をそれぞれ選択して、「コピー」>「16進数ストリームとして」を選択して繋げると、以下のような16進数文字列が取得できます。

504f5354202f706f737420485454502f312e310d0a486f73743a206874747062696e2e6f72670d0a557365722d4167656e743a206375726c2f372e37372e300d0a4163636570743a202a2f2a0d0a436f6e74656e742d4c656e6774683a20370d0a436f6e74656e742d547970653a206170706c69636174696f6e2f782d7777772d666f726d2d75726c656e636f6465640d0a0d0a666f6f3d626172

これを16進数からデコードすると以下のように見たことのある形式になります。

POST /post HTTP/1.1
Host: httpbin.org
User-Agent: curl/7.77.0
Accept: */*
Content-Length: 7
Content-Type: application/x-www-form-urlencoded

foo=bar