HTTP
次に、Webブラウザを利用する際のデータ転送で広く使用されている HTTP(Hyper Text Transfer Protocol) について扱いましょう。
HTTPにはいくつかのバージョンが存在します。 現在、HTTP/1.1とHTTP/2が広く利用されていますが、HTTP/3の仕様策定も現在進行しています。 ここでは、最も基本となる、HTTP/1.0の仕様に基づいてクライアントプログラムの実装を行いましょう。
HTTP/1.0のRFCは以下から閲覧できます。
https://tools.ietf.org/html/rfc1945
HTTPは、実用的に広く利用されているプロトコルだけあって、Echoプロトコルと比べると遥かに膨大なルールが定められています。 HTTPに基づいてファイルの配信を行うWebサーバーや、Webサーバーからファイルを受け取ってユーザーに提示するWebブラウザは、基本的にはこれらの全てのルールに従って実装されています。 そのおかげで、Apacheやnginxといった異なるWebサーバーや、ChromeやFirefoxといった異なるブラウザでも、違いを気にすることなくファイルの送受信が可能になっています。 なお、HTTPでやり取りされるファイル等のことを リソース と呼ぶこともあります。
HTTPメッセージの構造
RFCのHTTP Messageの節によると、HTTP/1.0のメッセージは以下のような構造になっていることがわかります。
Full-Request = Request-Line *( General-Header | Request-Header | Entity-Header ) CRLF [ Entity-Body ] Full-Response = Status-Line *( General-Header | Response-Header | Entity-Header ) CRLF [ Entity-Body ]
メッセージの文法は BNF によって記述されています。 ここでは、リクエスト(要求)メッセージとレスポンス(応答)メッセージそれぞれの文法が記述されています。
これを読み取ると、リクエストメッセージは大雑把に以下のような構造になっています。
リクエスト行
ヘッダー行1
ヘッダー行2
・
・
・
ヘッダー行n
(空行)
メッセージボディ
同様に、レスポンスメッセージは以下のような構造になっています。
ステータス行
ヘッダー行1
ヘッダー行2
・
・
・
ヘッダー行n
(空行)
メッセージボディ
各行の末尾はCRLF、すなわち「\r\n
」で表される改行で終わります。
リクエスト行
リクエスト行に、「HTTPメソッド」と「リクエストURI」、「HTTPバージョン」の3つがスペース区切りで記述されます。 HTTP/1.0に記述されているHTTPメソッドは「GET」と「POST」と「HEAD」の3つですが、現実には「DELETE」や「PUT」、「OPTIONS」などより多くのHTTPメソッドが使用されています。 HTTPを用いた通常のリソース取得にはGETメソッドが使用されます。 POSTメソッドは、Webページのフォームに入力された値をサーバーに送信する場合などに使用されます。
リクエスト行の具体例は以下のようになります。
GET http://example.com/ HTTP/1.0
この例では、http://example.com/
というリソースの取得を行なっています。
リソースの所在地は URI(Uniform Resource Identifier) によって指定されます。
なお、example.com
は、このように通信先の例示などで使われる特殊なドメインです。
ヘッダー
リクエストやレスポンスに付随する補足的な情報はヘッダーに記載されます。
以下はヘッダーの具体例です。
Date: Thu, 19 Dec 2019 18:16:28 GMT
Server: Apache
Last-Modified: Tue, 09 Oct 2018 07:08:28 GMT
ヘッダーには、 ヘッダー名: 値
という形式のヘッダー行を必要なだけ繰り返して記述します。
ヘッダーは、1行も存在しない場合もあります。
メッセージボディ
メッセージボディには、HTTPで送受信されるデータの本体が入ります。
ヘッダーとメッセージボディの間はCRLFだけからなる空行で区切られます。 メッセージの受信者は、空行を読み取ることで、ヘッダーとメッセージボディの区切れ目を見つけることができます。
一般的には、HTTPクライアントからのGETリクエストではメッセージボディは空となります。 POSTメソッドによるフォームの送信では、フォームに入力された値がメッセージボディに格納されます。
HTTPメッセージの確認方法
ここでもTelnetを利用して、HTTPサーバーとの通信を行い、HTTPの挙動やHTTPメッセージの具体例を確認してみましょう。
http://virgo.is.chs.nihon-u.ac.jp/~onoue/hello.txt からリソースの取得を試みます。 まずは、WebブラウザでこのURLを開いてみましょう。 「hello」というテキストファイルの中身が表示されるはずです。
さて、以下のようにtelnetコマンドを実行します。 HTTPは、標準的には80番ポートが使用されます。 このように、主要な通信プロトコルで使用することがあらかじめ決められているポート番号のことを Well-knownポート番号 と呼びます。
telnet virgo.is.chs.nihon-u.ac.jp 80
続けて、Telnetの中で以下のように文字列を入力します。
GET /~onoue/hello.txt HTTP/1.0
一定時間が経つと、入力の途中で打ち込んでいる文字列がサーバーに送信されるため、素早く入力を行いましょう。
また、ヘッダー行の終わりには空行が必要なため、「 GET /~onoue/hello.txt HTTP/1.0
」まで打ち込んだあと、2回エンターキーを押しましょう。
正常に実行できると、以下のような結果になります。
is-user@isvm:~$ telnet virgo.is.chs.nihon-u.ac.jp 80
Trying 104.46.238.40...
Connected to nuchsvirgo-virgo.japanwest.cloudapp.azure.com.
Escape character is '^]'.
GET /~onoue/hello.txt HTTP/1.0
HTTP/1.1 200 OK
Date: Thu, 19 Dec 2019 18:16:28 GMT
Server: Apache
Last-Modified: Tue, 09 Oct 2018 07:08:28 GMT
Accept-Ranges: bytes
Content-Length: 6
X-Content-Type-Options: nosniff
X-Frame-Options: sameorigin
X-XSS-Protection: 1; mode=block
Connection: close
Content-Type: text/plain; charset=UTF-8
hello
Connection closed by foreign host.
「 HTTP/1.1 200 OK
」のステータス行から始まり、いくつかのヘッダー行が続いた後、空行の次にメッセージボディである「hello」が表示されていることが確認できます。
全てのメッセージを受信した後、コネクションが切断されて通信が終了します。