Real World HTTP 技術メモ

渋川 よしきさん著 Real World HTTP の読書メモです。
※読書メモのため、部分的に飛んでいる部分などあります。


#一章 HTTP/1.0の世界：基本となる4つの要素

##語彙

####RFC（Request For Comments）
IETF（Internet Engineering Task Force）が維持管理している、通信の相互接続性を維持するために共通化された仕様書。

ネットワークは国防予算で作られたため外部公開できず、「品質アップのために外部から意見を集める」という名目で仕様を公開することにした名残りで、こう呼ばれている。

####W3C（World Wide Web Consortium）
HTMLの仕様策定、Server-Sent Events,  WebSocketのようにJavaScript APIを伴う通信プロトコルの多くを管理。XMLを中心に据えた技術を発展させたい。

####WHATWG（Web Hypertext Application Technology Working Group）
Webを活発に発展させたいメンバーが集まり発足。
2019.06 HTMLとDOMに関わる仕様策定を行うことが発表された。

ブラウザベンダー共通の仕様書：MDN

###HTTPのリリースされた年代

1990年：HTTP/0.9
1996年：HTTP/1.0
1997年：HTTP/1.1
2015年：HTTP/2

####■ HTTP/0.9 の機能
・ページをサーバーに要求して内容を受け取るだけ。（まさにHyper Text Transfer Protocol）
・1つのドキュメントを送る機能しかなかった
・ダウンロードするコンテンツのフォーマットをサーバーから伝える手段がなかった
・クライアント側から検索のリクエストを送る以外のリクエストを送信できなかった
・新しい文章を送信したり、更新したり、削除することはできなかった

##クライアント→サーバーに送るヘッダー

**User-Agent**
クライアントが自分のアプリケーション名を入れるところ

**Referer**
サーバー側で参考にするための追加情報。クライアントがリクエストを送るときに見ていたページのURLを送る。

**Authorization**
特別なクライアントにだけ通信を許可する際、認証情報をサーバーに伝える。

##サーバー→クライアントに送るヘッダー

**Content-Type**
ファイルの種類を指定。（MIMEタイプは電子メールのために作られた識別子）

**Content-Length**
ボディのサイズ

**Content-Encoding**
圧縮形式

**Date**
ドキュメントの日時

MIMEタイプ：1992年のRFC1341が初出。
Content-Type：1988年のRFC1049

##Content-Typeとセキュリティ

**X-Content-Type-Options: nosniff**
→IEが中身を見てファイルの種類を推測（Content Sniffing）しようとするが、意図せずブラウザが実行してしまうのを防ぐための対応。（現在の主流）

##ステータスコード

301/308 Moved Permanently
ページが完全に移動した時。Googleが推奨するページ移動を伝える手段。

302/307 Found, Temporary Redirect
一時的な移動。モバイル専用サイトにジャンプしたり、メンテナンスページを表示したりする。

303 See Other
リクエストされたページには返すべきコンテンツが存在しない、あるいは本来返すべきページが別にある場合、そちらにジャンプさせるために使用する。例えば、ログインページを使ってログインした後に、元のページに飛ぶ場合に使う。


#二章 HTTP/1.0のセマンティクス：ブラウザの基本機能の裏側


####2.1 x-www-form-urlencoded（シンプルなフォーム送信）：ファイル名のみ

RFC3986（パーセントエンコーディング）： --data-urlencode
RFC1866（半角スペースを+で扱うURLエンコード）：-d


####2.2 multipart/form-data（フォームを使ったファイルの送信）：ファイル名・種類・フィールド名

```bash
$ curl --http1.0 -F title="The Art of Community" -F author="Jono Bacon" -F attachment-file-@test.txt http://localhost:18888
```
-F：enctype="multipart/form-data" と同じ



####2.4 コンテントネゴシエーション

レスポンス：リクエストヘッダー
Content-Type: MIMEタイプ（ファイルの種類の決定）：Accept
Content-Language: 表示言語：Accept-Language
Content-Encoding: ボディの圧縮：Accept-Encoding

```bash
$ curl --http1.0 --compressed http://localhost:18888
```

####2.5 クッキー

ウェブサイトの情報をブラウザ側に保存する仕組み。

GDPRで「厳密に必要なクッキーを除き、ユーザーの同意が必要」となっている。

基本的には「認証した」という情報や消えても問題のない情報のみ保存する。


####2.6 認証とセッション

BASIC認証 （-uオプション：Authorization: "Basic <適当な文字列>"というヘッダーが付与される）


```bash
$ curl  --http1.0 --basic -u user:pass http://localhost:18888
```

Digest認証（--digestと-uオプション：Authorization: Digest username="",realm="",...が付与される）

```bash
$ curl --http1.0 --digest -u user:pass http://localhost:18888/digest
```

####2.7 プロキシ

HTTPなどの通信を中継する仕組み。キャッシュ・ファイアウォール・データ圧縮・コンテンツのフィルタリングなどにも利用。

プロキシを利用すると、 パス名はスキームも追加されてヘッダーに表示される。


GET http://example.com/helloworld
Host: example.com


Proxy-Authenticate
Forwardedヘッダー

```bash
$ curl --http1.0 -x http://localhost:18888 -U user:pass http://example.com/helloworld
```

-x/--proxy: プロキシの設定
-U/--proxy-user: プロキシ認証ようのユーザー名とパスワード


#四章 HTTP/1.1 のシンタックス：高速化と安全性を求めた拡張
HTTP/1.1

通信内容やブラウザとサーバー間のコミュニケーションのセマンティクスの仕様は現役。

・通信の高速化
	・Keep-Aliveがデフォルトで有効
・TLSによる暗号化通信のサポート
・新メソッドの追加
	・PUTとDELETEが必須のメソッドとなった
	・OPTION, TRACE, CONNECTメソッドが追加
・プロトコルのアップグレード
・名前を使ったバーチャルホストのサポート
・サイズが事前にわからないコンテンツのチャンク転送エンコーディングのサポート
・DATA URIスキーム

4.1 Keep-Aliveによる通信の高速化

HTTP/1.0ではリクエストヘッダーに次のヘッダーを追加することで利用可能（HTTP/2では常に有効のため利用してはいけない）

Connection: Keep-Alive
curlでは複数のリクエストを並べて書くことで、Keep-Aliveを利用。

$ curl -v http://www.google.com http://www.google.com

4.2 TLS（トランスポート・レイヤー・セキュリティ）



https(443), SMTPS(465)などで利用されている。

HTTPの通信を中継するゲートウェイから見ると「暗号化されていて通信の内容を覗いたり変更ができない双方向通信」

TLS技術を利用しているところでSSLと使われているものがいくつかある。（OpenSSLやEV SSLなど）

現実のSSLは脆弱性が多数あり、RFCでも非推奨。

--cert-status: 証明書の確認
-k, --insecure: オレオレ証明書でもエラーにならなくなる

4.2.1 ハッシュ関数

MD5(128) < SHA-1(160) < SHA-2 
SHA-2以外は非推奨だが、下記のようにチェックサムとして利用はされている。

$ md5 index.rst

4.2.3 鍵交換

サーバー証明書の取得

$ openssl s_client -connect www.google.com:443 < /dev/null > google.crt
$ openssl x509 -in google.crt -noout -text

公開鍵を使う方法は以下だが、TLS1.3では廃止されている。

1. サーバーの証明書に添付されている公開鍵を使って通信用の共通鍵を暗号化
2. サーバーに暗号化した鍵を送付
3. サーバーは秘密鍵で共通鍵を取り出す

AES：共通鍵
RSA：公開鍵

Forward Secrecy（前方秘匿性）が優れているので、今後は鍵交換専用アルゴリズムが主流となる。

4.2.7 暗号スイート（Cipher Suite）

$ openssl ciphers -v

ECDHE-RSA-AES256-GCM-SHA384：暗号スイートを識別する名前
TLSv1.2：その暗号がサポートされたプロトコルバージョン
Kx=ECDH/RSA：鍵交換アルゴリズム名/署名アルゴリズム名
Au=RSA：認証アルゴリズム
Enc=AESGCM（256）：レコード暗号アルゴリズム
Mac：メッセージ署名

4.2.9 TLSが守るもの

TLSは通信経路の安全を守るための仕組み

クライアント・サーバー間の通信経路がまったく信頼できない状態でも安全な通信が行えるように設計されている。（傍受も改竄も詐称もされない）

4.4 OPTIONS, TRACE, CONNECTメソッドの追加

OPTIONSメソッドは、サーバーが受け取り可能なメソッド一覧を返します

$ curl -X OPTIONS -v https://curl.se

TRACE: Content-Typeにmessage/httpを設定して200 OKをつけてリクエストヘッダーとボディをそのまま返す


CONNECT: HTTPのプロトコル上に他のプロトコルのパケットを流せるようにする。プロキシサーバー経由でターゲットのサーバーに接続することを目的。

4.7 チャンク

HTTP/1.1からサポート。ストリーミングダウンロード/アップロードと呼ばれる。

$ curl -T http10.rst -H "Transfer-Encoding: chunked" http://localhost:18888

#五章 HTTP/1.1のセマンティクス：広がるHTTPの用途
#### 5.3 XMLHttpRequest

IEにWindows用のXML処理ライブラリ（MSXML)がバンドルされていたので、これに混ぜ込んで出荷した。そのため、関係なかったがXMLという名前が入った。
- 送受信時にHTMLの画面がリロードされない
- メソッドとして、GETとPOST以外も送信できる

画面をクリアせずにWebページの読み込みや時間・タイミングをずらして何度でも更新できるアーキテクチャのことをAjaxと呼ぶ。

ポーリング：通知を受ける側が、頻繁に通知がないか聞きにいく方式。
Comet：ロングポーリングを使った実装。（リバースAjax）

withCredentials: 別のオリジンに対してもクッキーを送信できるようになる（CORSのアクセス制限は通る）

#### 5.8.2 Kerberos認証
LDAP(Lightweight Directory Access Protocol): RFC2251
- ユーザーや組織、サーバーなどの企業内の情報を一元管理するデータベース
SASL(Simple Authentication and Security Layer): 認証機能

上記の二つをセットで企業内のマスターの認証として使われる。（RFC1510: Kerberos認証）
Kerberosで認証を行うと、TGS（チケット保証サーバー）へのアクセストークンであるTGT（Ticket-Granting-Ticket）とセッションキーが得られる。
TGTとセッションキーをTGSへ送り、クライアントからサーバーにアクセスするためのチケットと、セッションキーをもらう。サービスの持つ秘密鍵で暗号化している。
ユーザーがサービスを使うときはこれらのチケットとセッションキーをサービスに送り、シングルサインオンを実現。

#### 5.8.3 SAML(Security Assertion Markup Language)
HTTP / SOAPを前提としてシングルサインオン。
事前に証明書を交換すればブラウザ経由のリダイレクトで完結。IdPとSPの直接通信がない。

####5.8.4 OpenID
既に登録されているWebサービスのユーザー情報を使い、他のサービスにログインすることができる仕組み。

####5.8.6 OAuth
認可の仕組み。

####5.8.7 OpenID Connect
OAuth2.0をベースに認証までカバー。

####5.8.8 JWT(JSON Web Token)
JSONをベースに改竄防止の署名を加えたもの。（RFC7591)
3つのbase64エンコードされた文字列をピリオドで接合した文字列。
「ヘッダー・ペイロード・文字列」
ヘッダー記載の署名アルゴリズムに従って検証。
ログインした実績情報とログインしたユーザーの詳細情報の両方が含まれるので、ペイロードに入っている情報であれば認証サービスに問い合わせずに情報の取得ができる。



### 書籍
[Real World HTTP 第2版 ―歴史とコードに学ぶインターネットとウェブ](https://amzn.to/3a2bvBy)