この記事は Hiyoung が書いたものだよ
第一章:Webとネットワークの基本を知ろう
1.1 はじめに
HTTPを理解するには、まずTCP/IPプロトコルスタックについて知っておくべきだね。僕たちが普段使っているネットワーク(インターネットも含む)はTCP/IPプロトコルスタックに基づいて動いていて、HTTPはその中のサブセットなんだ。インターネット上のデバイスが相互に通信するためには、両者が同じルールに従う必要がある。これらのルールをプロトコルと呼ぶんだ。(TCP/IPは、インターネット関連の様々なプロトコルスタックの総称で、PPPoE、HTTP、TCP、IP、UDP、IEEE 802.3などが含まれるけど、これらに限らないよ。)
TCP/IPプロトコルスタックは、階層的に上から順に、アプリケーション層、トランスポート層、ネットワーク層、データリンク層に分かれているんだ。
インターネット・プロトコル・スイート - Wikipedia
TCP/IPプロトコルスタックを使って通信する時、クライアントはアプリケーション層から下に進み、サーバーはデータリンク層から上に進むんだ。クライアントが層間をデータ転送する際、各層を通過するたびにその層のヘッダー情報が付加されるよ。逆に、サーバーは層ごとにヘッダーを一つずつ取り除いていく。このようにデータ情報を包み込む方法をカプセル化と呼ぶんだ。

1.2 IP、TCP、DNS
1.2.1 IPプロトコル
IPプロトコルはネットワーク層に位置するんだ。TCP/IPのIPはIPプロトコルを指していて、IPアドレスとは別物だよ。IPプロトコルの役割は、様々なデータパケットを相手に送ること。様々なIPアドレスはMACアドレスとペアにできるんだ。IPアドレスは変わる可能性があるけど、MACアドレスは基本的には変わらない。IPアドレスはノードに割り当てられたアドレスを示し、MACアドレスはネットワークカードに属する固定アドレスを指すよ。
1.2.2 MACアドレス
IP間の通信はMACアドレスに依存するんだ。通常、 ARPプロトコル を使って、通信相手のIPアドレスから対応するMACアドレスを逆引きするよ。
1.2.3 TCPプロトコル
階層的に見ると、TCPはトランスポート層に位置していて、バイトストリームサービスを提供するんだ。これは、大きなデータを転送しやすくするために、セグメントという単位のデータパケットに分割して管理すること。簡単に言えば、TCPプロトコルは大量のデータを送りやすくするためにデータを分割するし、データが最終的に相手に届いたかどうかを確認できるんだ。
データが相手に届いたかを確認するために、TCPはスリーウェイハンドシェイクという戦略を採用しているよ。ハンドシェイクの過程では、TCPのフラグであるSYN(synchronize)とACK(acknowledgement)が使われるんだ。

1.2.4 ドメイン名解決を担うDNSサービス
コンピューターにはIPアドレスだけでなく、ホスト名やドメイン名も割り当てられるよ。DNSプロトコルは、ドメイン名からIPアドレスを検索したり、逆にIPアドレスからドメイン名を逆引きしたりするサービスを提供するんだ。

1.3 URLとURI
1.3.1 違いと関係性
URI(統一リソース識別子)に比べると、僕たちはURL(Uniform Resource Locator、統一リソースロケータ)の方に馴染みがあるよね。URLはまさにWebブラウザなどでWebページにアクセスする時に入力するウェブアドレスのこと。例えば、 https://www.bilibili.com/ はURLだよ。URIは文字列でインターネット上の特定のリソースを識別し、URLはリソースの場所(インターネット上のどこにあるか)を示す。だから、URLはURIのサブセットなんだ。URIはロケータ(URL)、名前(URN)、またはその両方と見なせる。 統一リソース名 (URN)は人の名前のようなもので、 統一リソースロケータ (URL)は人の住所を表す。言い換えれば、URNはあるもののアイデンティティを定義し、URLはそのものを見つける方法を提供するんだ。
1.3.2 URIのフォーマット
指定されたURIを表すには、必要な情報すべてを含む絶対URI、絶対URL、そして相対URLを使うんだ。
相対URLは、ブラウザの基本URIから指定されるURLで、/image/logo.gifのような形をしているよ。
絶対URIのフォーマット:

ログイン情報(認証):サーバーからリソースを取得する際に必要なログイン情報(身元認証)として、ユーザー名とパスワードを指定するよ。これはオプション項目だね。
サーバーアドレス:絶対URIを使う場合、アクセス先のサーバーアドレスを必ず指定する必要があるんだ。アドレスはhackr.jpのようなDNSで解決可能な名前でもいいし、192.168.1.1のようなIPv4アドレス名でもいいし、[0:0:0:0:0:0:0:1]のように角括弧で囲まれたIPv6アドレス名でもいいよ。
サーバーポート番号:サーバーに接続するネットワークポート番号を指定する。これもオプション項目で、省略すると自動的にデフォルトのポート番号が使われるんだ。
階層的なファイルパス:サーバー上のファイルパスを指定して、特定のリソースを特定する。これはUNIXシステムのファイルディレクトリ構造と似ているね。
クエリ文字列:指定されたファイルパス内のリソースに対して、クエリ文字列を使って任意のパラメータを渡せるよ。これはオプション項目だね。
フラグメント識別子:フラグメント識別子を使うと、通常、取得したリソース内のサブリソース(ドキュメント内の特定の位置)をマークできる。でも、 RFC ではその使用方法が明確に規定されているわけではないんだ。これもオプション項目だよ。
第二章:シンプルなHTTPプロトコル
2.1 HTTPの概要
HTTPはステートレスプロトコルだね。ステートレスというのは、HTTPプロトコル自体が、それぞれのリクエストとレスポンス間の通信状態を保存しないってこと。だから、通信状態を保存するためにCookie技術が導入されたんだ。(注:このHTTPに関する本は比較的古いから、現在使われている状態保存技術は、 Cookie、Session、Token が組み合わさって実現されているよ。)
2.2 よく使われるHTTPメソッド
GET:リソースを取得する
GETメソッドはURLで指定されたリソースをリクエストするために使われるんだ。指定されたリソースはサーバー側で解析された後、レスポンス内容が返されるよ。

POST:エンティティボディを送信する
POSTはサーバーにデータを送信するために使われるよ。取得するデータが大きすぎる場合にもPOSTメソッドが使われることがあるんだ。
GETとPOSTの違い:
結論から言うと、GETとPOSTメソッドに本質的な違いはない。ただメッセージのフォーマットが違うだけなんだ。
リクエストパラメータの長さ制限:GETリクエストの長さは最大1024KBだけど、POSTはリクエストデータに制限がないよ。
リクエストパラメータ:GETリクエストのパラメータはURLを介して渡され、複数のパラメータは&で連結される。POSTリクエストはリクエストボディに格納されるんだ。
リクエストキャッシュ:GETリクエストはキャッシュされるけど、POSTリクエストは手動で設定しない限りキャッシュされないよ。
安全性:POSTの方がGETより安全だね。GETリクエストはブラウザで戻るボタンを押しても無害だけど、POSTは再度リクエストが送信されてしまうからね。
履歴:GETリクエストのパラメータは閲覧履歴に完全に残るけど、POSTのパラメータは残らないよ。
エンコード方式:GETリクエストはURLエンコードしかできないけど、POSTは複数のエンコード方式をサポートしてるんだ。
パラメータのデータ型:GETはASCII文字しか受け付けないけど、POSTには制限がないよ。
他にも、 HTTPにはPUT、HEAD、DELETEなどのメソッドがある けど、ここでは詳しく触れないでおくね。
2.3 HTTPの持続的接続(スリーウェイハンドシェイクとフォアウェイハンドシェイク)
持続的接続の特徴は、どちらかの端が明示的に接続を切断すると言わない限り、TCP接続状態を維持することなんだ。

スリーウェイハンドシェイク:TCP接続を確立する フォアウェイハンドシェイク:TCP接続を切断する
持続的接続では、パイプライン化技術を使うことで、応答を待たずに次のリクエストを直接送信できるんだ。

2.4 Cookieを使った状態管理
Cookieは、サーバーから送られてくるレスポンスメッセージ内のSet-Cookieというヘッダーフィールド情報に基づいて、クライアントにCookieの保存を通知するんだ。次回クライアントがそのサーバーにリクエストを送る際、クライアントは自動的にリクエストメッセージにCookie値を追加して送信するよ。

Cookie情報はサーバー側で生成され、クライアントに送られて保存されるんだ。
第三章 HTTPメッセージ情報
3.1 HTTPのリクエストとレスポンスメッセージの構造
HTTPプロトコルのやり取りに使われる情報をHTTPメッセージと呼ぶよ。リクエスト側(クライアント)のHTTPメッセージはリクエストメッセージ、レスポンス側(サーバー)のHTTPメッセージはレスポンスメッセージと呼ばれるね。8ビットのバイトストリームで構成されていて、HTTP通信で転送されるんだ。
リクエストライン:リクエストに使われるメソッド、リクエストURI、HTTPバージョンを含むよ。
ステータスライン:レスポンス結果を示すステータスコード、理由フレーズ、HTTPバージョンを含むんだ。
ヘッダーフィールド:リクエストとレスポンスの様々な条件や属性を示す各種ヘッダーを含む。一般的に、汎用ヘッダー、リクエストヘッダー、レスポンスヘッダー、エンティティヘッダーの4種類があるよ。
その他:HTTPのRFCで定義されていないヘッダー(Cookieなど)が含まれることもあるね。

3.2 エンコード転送とチャンク転送
HTTPはデータ転送の過程でエンコードすることで転送速度を向上させるんだ。
3.2.1 メッセージボディとエンティティボディの違い
エンティティ:リクエストまたはレスポンスのペイロードデータ(補足項目)として転送され、その内容はエンティティヘッダーとエンティティボディで構成されるんだ。
HTTPメッセージのボディは、リクエストまたはレスポンスのエンティティボディを転送するために使われる。通常、メッセージボディはエンティティボディと同じ。転送中にエンコード操作が行われた場合にのみ、エンティティボディの内容が変化し、それがメッセージボディとの差異を生むんだ。
3.2.2 エンティティボディの分割送信
HTTP通信中に大容量データを転送する際、データを複数に分割することで、ブラウザがページを段階的に表示できるようになるんだ。エンティティボディを分割する機能をチャンク転送エンコーディングと呼ぶよ。チャンク転送エンコーディングは、エンティティボディを複数のチャンクに分割する。各チャンクは16進数でチャンクのサイズがマークされ、エンティティボディの最後のチャンクは「0(CR+LF)」でマークされるんだ。

いわゆるチャンクっていうのは、よく言うパケットのことだね。
第四章 戻り結果のHTTPステータスコード
4.1 ステータスコードの種類
ステータスコードを使えば、サーバーがリクエストを正常に処理したかどうかを知ることができるんだ。ステータスコードは種類が多いけど、よく使うのはだいたい14種類くらいだよ。

4.2 2XX 成功
4.2.1 200 OK
クライアントから送られたリクエストがサーバーで正常に処理されたことを示すんだ。レスポンスメッセージ内で、ステータスコードと一緒に返される情報は、メソッドによって変わるよ。
4.2.2 204 No Content
このステータスコードは、サーバーが受け取ったリクエストが正常に処理されたけど、返されるレスポンスメッセージにはエンティティボディの部分が含まれていないことを示すんだ。
4.3 3XX リダイレクト
ここでは301リダイレクトと302リダイレクトについて重点的に説明するね。他のステータスコードは自分で調べてみて。
4.3.1 301 Moved Permanently
301リダイレクトは恒久的なリダイレクトなんだ。このステータスコードは、リクエストされたリソースが新しいURIに割り当てられたことを示し、今後はリソースが現在指すURIを使用すべきだよってこと。例えば、以下に示すリクエストURIのように、指定されたリソースパスの最後にスラッシュ「/」を付け忘れると、301ステータスコードが生成されることがあるんだ。
http://excample.com/sample
4.3.2 302 Found
302リダイレクトは一時的なリダイレクトだよ。このステータスコードは、リクエストされたリソースが新しいURIに割り当てられたことを示し、ユーザー(今回だけ)に新しいURIでアクセスしてほしいってこと。301 Moved Permanentlyステータスコードと似てるけど、302ステータスコードが表すリソースは永久に移動したわけじゃなくて、一時的な性質のものなんだ。
4.4 4XX クライアントエラー
400 Bad Request、401 Unauthorized、403 Forbidden、404 Not Foundがあるね。ここでは404 Not Foundについて重点的に説明するよ。
4.4.1 404 Not Found
このステータスコードは、サーバー上でリクエストされたリソースが見つからなかったことを示すんだ。それ以外にも、サーバー側がリクエストを拒否したけど、理由を説明したくない場合にも使われることがあるよ。
4.5 5XX サーバーエラー
5XXのレスポンス結果は、サーバー自体でエラーが発生したことを示すんだ。
第五章 Webサーバー
5.1 通信データ転送プログラム:プロキシ、ゲートウェイ、トンネル
5.1.1 プロキシ
プロキシサーバーの基本的な動作は、クライアントから送られてきたリクエストを受け取って、それを他のサーバーに転送することだね。プロキシはリクエストURIを変更せず、直接前方にあるリソースを持つターゲットサーバーに送信するんだ。ちなみに、プロキシはクライアントに対するプロキシ(フォワードプロキシとも呼ばれる)を指すけど、リバースプロキシはサーバーに対するプロキシを指すよ。

プロキシサーバーを使うと、キャッシュ技術を利用してネットワーク帯域幅のトラフィックを削減できるし、情報セキュリティのためにプロキシを使うこともあるんだ。
- キャッシュプロキシ
プロキシが応答を転送する際、キャッシュプロキシ(Caching Proxy)は、あらかじめリソースのコピー(キャッシュ)をプロキシサーバーに保存しておくんだ。同じリソースへのリクエストが再びプロキシに届いた場合、オリジンサーバーからリソースを取得するのではなく、以前キャッシュしたリソースを応答として返すことができるんだよ。
- リバースプロキシ
リバースプロキシにはたくさんの利点があるんだ。
クライアントからサーバー(クラスター)のIPアドレスを隠せる
セキュリティ: アプリケーション層ファイアウォール として、ウェブベースの攻撃(例えば DoS / DDoS )からウェブサイトを保護し、 マルウェア などの特定を容易にする
バックエンドサーバー(クラスター)に対して、暗号化と SSL アクセラレーション(SSL終端プロキシなど)を統一的に提供する
ロードバランシング :サーバークラスター内に負荷の高いものがある場合、リバースプロキシは URL書き換え を通じて、接続リクエストに応じて負荷の低いサーバーから必要な同じリソースを取得したり、予備を提供したりする
静的コンテンツや短期間に大量のアクセスリクエストがある動的コンテンツに対して、 キャッシュサービス を提供する
いくつかのコンテンツを 圧縮 して、 帯域幅 を節約したり、ネットワーク帯域幅が不十分なネットワークにサービスを提供したりする

5.1.2 ゲートウェイ

ゲートウェイの仕組みはプロキシとすごく似てるんだ。ゲートウェイは、通信回線上のサーバーがHTTP以外のプロトコルサービスを提供できるようにするよ。