初めての HTTP#
入力 url -> ブラウザプロセスが入力情報を処理 -> ブラウザエンジンがサーバーにリクエストを送信 -> ブラウザエンジンがレスポンスを読み取る -> ブラウザエンジンがレンダリングを行う -> ブラウザプロセスのページが読み込まれる
-
Hyper Text Transfer Protocol (HTTP)ハイパーテキスト転送プロトコル
-
これはアプリケーション層プロトコルであり、トランスポート層の TCP プロトコルに基づいています
-
リクエスト、レスポンス
-
シンプルで拡張可能(クライアントとサーバー間で理解できる限り、リクエストヘッダーをカスタマイズ可能)
-
ステートレス
プロトコル分析#
発展の歴史#
メッセージ構造#
HTTP/1.1#
図のように、リクエストとレスポンスのリクエストヘッダー、返されたステータスコードなどが見えます。
Method | 説明 |
---|---|
GET | 指定されたリソースの表現をリクエストし、GET リクエストはデータを取得するためにのみ使用されるべきです |
POST | エンティティを指定されたリソースに送信するために使用され、通常はサーバー上の状態変化や副作用を引き起こします |
PUT | リクエストの有効ペイロードでターゲットリソースのすべての現在の表現を置き換えます |
DELETE | 指定されたリソースを削除します |
HEAD | GET リクエストのレスポンスと同じレスポンスをリクエストしますが、レスポンスボディはありません(あまり使用されません) |
CONNECT | ターゲットリソースによって識別されたサーバーへのトンネルを確立します。(あまり使用されません) |
OPTIONS | ターゲットリソースの通信オプションを説明するために使用されます。 |
TRACE | ターゲットリソースへのパスに沿ってメッセージループバックテストを実行します。(あまり使用されません) |
PATCH | リソースに部分的な変更を適用するために使用されます。 |
-
Safe(安全):サーバーデータを変更しないメソッド、例えばデータを読む GET、HEAD、OPTIONS など
-
Idempotent(冪等):同じリクエストが一度実行されるのと連続して何度も実行されるのとで効果が同じであり、サーバーの状態も同じである。すべての safe メソッドは Idempotent です。例えば GET、HEAD、OPTIONS、PUT、DELETE など
ステータスコード#
- 200 OK - クライアントのリクエストが成功しました
- 301 - リソース(ウェブページなど)が永久に移動しました他の URL に
- 302 - 一時的なリダイレクト
- 401 - Unauthorized - リクエストが未承認です
- 404 - リクエストされたリソースが存在しません、間違った URL が入力された可能性があります
- 500 - サーバー内部で予期しないエラーが発生しました
- 504 Gateway Timeout - ゲートウェイまたはプロキシサーバーが指定された時間内に要求されたレスポンスを取得できませんでした
RESTful API#
API 設計スタイルの一つ:REST - Representational State Transfer
- 各 URI は — 種のリソースを表します
- クライアントとサーバー間で、このリソースのある種の表現層を渡します
- クライアントは HTTP メソッドを使用してサーバー側のリソースを操作し、"表現層の状態変換" を実現します。
リクエスト | レスポンスコード | 意味 |
---|---|---|
GET /zoos | 200 OK | すべての動物園をリストし、サーバーが成功裏に返しました |
POST /zoos | 201 CREATED | 新しい動物園を作成し、サーバーが成功裏に作成しました |
PUT /zOos/ID | 400 INVALID REQUEST | 指定された動物園の情報を更新(その動物園の全情報を提供); ユーザーが送信したリクエストにエラーがあり、サーバーは新しいデータの作成や変更を行いませんでした |
DELETE /zoos/ID | 204 NO CONTENT | 指定された動物園を削除し、データ削除が成功しました |
よく使われるリクエストヘッダー#
リクエストヘッダー | 説明 |
---|---|
Accept | 受信タイプ、ブラウザがサポートする MIME タイプ **(サーバーが返す Content-Type に対応)** |
Content-Type | クライアントが送信するエンティティ内容のタイプ |
Cache-Control | リクエストとレスポンスが従うキャッシュメカニズムを指定します、例えば no-cache |
lf-Modified-Since | サーバーの Last-Modified に対応し、ファイルが変更されたかどうかを確認するために使用され、1 秒以内の精度しかありません |
Expires | キャッシュ制御、この時間内はリクエストせず、直接キャッシュを使用し、サーバーの時間 |
Max-age | 代表リソースがローカルで何秒間キャッシュされるか、有効時間内はリクエストせず、キャッシュを使用します |
If-None-Match | サーバーの ETag に対応し、ファイル内容が変更されたかどうかを確認するために使用されます (非常に正確) |
Cookie | Cookie があり、同じドメインにアクセスする際に自動的に持ち込まれます |
Referer | このページの出所 URL(すべてのリクエストタイプに適用され、詳細なページアドレスまで正確に、csrf 防止にこのフィールドがよく使われます) |
Origin | 最初のリクエストがどこから発信されたか(ポートまで正確に、Origin は Referer よりもプライバシーを尊重します ** |
User-Agent | ユーザークライアントの必要な情報、例えば UA ヘッダーなど |
よく使われるレスポンスヘッダー#
レスポンスヘッダー | 説明 |
---|---|
Content-Type | サーバーが返すエンティティ内容のタイプ |
Cache-Control | リクエストとレスポンスが従うキャッシュメカニズム、例えば no-cache |
Last- Modified | リクエストリソースの最終変更時間 |
Expires | 文書がいつ期限切れと見なされるべきか、キャッシュしなくなるか |
Max-age | クライアントのローカルリソースが何秒間キャッシュされるべきか、Cache-Control を有効にした後に有効 |
ETag | リソースの特定バージョンの識別子、Etags は指紋に似ています |
Set-Cookie | ページに関連付けられた cookie を設定し、サーバーがこのヘッダーを通じて cookie をクライアントに送信します |
Server | サーバーに関するいくつかの情報 |
Access-Control-Allow-Origin | サーバー側が許可するリクエスト Origin ヘッダー(例えば *) |
キャッシュ#
強いキャッシュ
ローカルにあれば直接使用すれば良い
- Expires(期限)、タイムスタンプ
- Cache-Control
- キャッシュ可能性
- no-cache:協議キャッシュの検証
- no-store:どのキャッシュも使用しない
- public、private など
- 期限
- max-age:単位は秒、保存される最大生存期間、リクエストに対しての時間
- 再検証 * 再読み込み
- must-revalidate:リソースが期限切れになった場合、元のサーバーの検証が成功するまで使用できません()
- キャッシュ可能性
協議キャッシュ
サーバー側と通信し、使用するかどうかを確認します
- Etag/If-None-Match:リソースの特定バージョンの識別子、指紋に似ています
- Last-Modified/If-Modified-Since:最終変更時間。(絶対的)
Cookie#
Set-Cookie - レスポンス
Name=value | 各種 cookie の名前と値 |
---|---|
Expires=Date | Cookie の有効期限、デフォルトでは Cookie はブラウザが閉じるまで有効です。 |
Path= Path | 指定された Cookie の送信範囲を制限するファイルディレクトリ、デフォルトは現在のディレクトリ |
Domain=domain | cookie が有効なドメインを制限し、デフォルトは cookie を作成したサービスのドメイン |
secure | HTTPS セキュア接続時のみ Cookie を送信できます |
HttpOnly | JavaScript スクリプトが Cookie を取得できません |
SameSite=[None|Strict|Lax] | None は同じサイト、クロスサイトリクエストを送信可能;Strict は同じサイトでのみ送信 ;トップレベルのナビゲーションと一緒に送信され、第三者サイトからの GET リクエストと一緒に送信されます |
発展#
HTTP/2 の概要:より速く、より安定、よりシンプル
-
フレーム (frame)
-
HTTP/2 通信の最小単位で、各フレームにはフレームヘッダーが含まれ、少なくとも現在のフレームに属するデータストリームを識別します。
-
1.0 ではテキストが転送されますが、2 ではバイナリデータが転送され、効率が向上します。新しい圧縮アルゴリズムもあります。
-
-
-
メッセージ:論理的なリクエストまたはレスポンスメッセージに対応する完全な一連のフレーム。
-
データストリーム:確立された接続内の双方向バイトストリームで、一つまたは複数のメッセージを運ぶことができます。
-
交互に送信され、受信者が再編成します。
-
-
HTTP/2 接続はすべて永続的であり、各ソースに対して 1 つの接続のみが必要です
-
ストリーム制御:送信者が受信者に大量のデータを送信するのを防ぐメカニズム
-
サーバープッシュ
HTTPS の概要#
-
HTTPS : Hypertext Transfer Protocol Secure
-
TSL/SSL で暗号化されています
-
対称暗号:暗号化と復号化は同じキーを使用します
-
非対称暗号:暗号化と復号化には異なる 2 つのキーが必要です:公開鍵(public key)と秘密鍵(private key)
一般的なシーン分析#
静的リソース#
今日頭条を例に、ネットワークパネルを開いてリクエストを確認し、css ファイルのリクエストを見つけます。
返されたステータスコードが 200 であることがわかりますが、本当にリクエストが発起されたのでしょうか(隣の括弧が示すように、ディスクキャッシュから)
上の図のレスポンスヘッダーから、以下のことがわかります:
- キャッシュ戦略?
- 強いキャッシュ(max-age=xxxxx)
- Cache-control:計算すると、1 年
- 強いキャッシュ(max-age=xxxxx)
- その他の情報?
- すべてのドメインからのアクセスを許可(access-control-allow-origin)
- リソースタイプ:css(content-type)
静的リソースの戦略:キャッシュ + CDN + ファイル名のハッシュ
- CDN:Content Delivery Network
- ユーザーの近接性とサーバーの負荷を考慮して、CDN はコンテンツを非常に効率的な方法でユーザーのリクエストに提供します
それほど長いキャッシュ期間で、どのようにしてユーザーが取得するコンテンツが最新であることを保証するのでしょうか?
ファイル名のハッシュ、ファイル内容が変更されるとファイル名が変わる / バージョン番号が追加され、これによりキャッシュ内のファイルが一致しなくなり、再リクエストが必要になります。
ログイン - クロスドメイン#
クロスドメインの問題により、リクエストメソッドが OPTION になります
プロトコル、ホスト名、ポートのいずれかが異なるとクロスドメインの問題が発生します(HTTP のデフォルトポート番号は 443 です)
クロスドメイン問題の解決#
-
クロスオリジンリソースシェアリング(CORS)( Cross-Origin Resource Sharing )
-
クロスオリジンリソースシェアリング
(CORS)(または一般的にクロスドメインリソースシェアリングと訳される)は、サーバーが自身以外の他のorigin(ドメイン、プロトコル、ポート)を示すことを許可することによって、ブラウザがこれらのリソースを読み込むことを可能にする、HTTPヘッダーに基づくメカニズムです。クロスオリジンリソースシェアリングは、サーバーが実際のリクエストを送信することを許可するかどうかを確認するためのメカニズムも提供します。このメカニズムは、ブラウザがサーバーにホストされているクロスオリジンリソースへの「プレフライト」リクエストを送信することによって行われます。プレフライトでは、ブラウザが送信するヘッダーに HTTP メソッドと実際のリクエストで使用されるヘッダーが示されます。セキュリティ上の理由から、ブラウザはスクリプト内からのクロスオリジン HTTP リクエストを制限します。たとえば、
XMLHttpRequest
やFetch APIは同一オリジンポリシーに従います。これは、これらの API を使用する Web アプリケーションが、アプリケーションを読み込んだのと同じドメインからのみ HTTP リソースをリクエストできることを意味します、レスポンスメッセージに正しい CORS レスポンスヘッダーが含まれていない限り。 -
プレリクエスト:サーバーがそのクロスオリジンリクエストを許可するかどうかを確認します(複雑なリクエスト)
-
関連するプロトコルヘッダー
- access-control-....
-
-
プロキシサーバー
- 同一オリジンポリシーはブラウザのセキュリティポリシーであり、HTTP のものではありません
-
Iframe の多くの不便
上の図のように、ログイン時にどのアドレスに対して何を行ったのでしょうか?
- POST メソッドを使用しました
- 目標ドメイン:https://sso.toutiao.com
- 目標は:path/quick_login/v2/
どのような情報を持ち運び、どのような情報が返されたのでしょうか?
- 持ち運び情報
- Post body、データ形式は form
- 希望するデータ形式は json
- 既存の cookie
- 返された情報
- データ形式 json
- cookie の情報
次回ページに入るとき、なぜログイン状態を記憶できるのでしょうか?
認証#
- セッション + cookie (ほとんどのポータルサイトでこの形式)
- ユーザーがサーバーにリクエストを送信し、ユーザー名やパスワードなどを含みます
- サーバーが処理し、その正当性を確認し、正しければセッションを返し、それを cookie に保存します(Set-Cookie = ......)
- ユーザーが再度送信する際:GET Cookie=....
- サーバーが処理し、認証後にいくつかのログイン情報を返します
- JWT(JSON Web Token)
- サーバーはローカルに保存しません
- 返されたトークンのユニーク性、ログイン時間の短さなど
- SSO:シングルサインオン(Single Sign On)
図のように、非常に明確に説明されています。
実際の応用#
XMLHttpRequest - Web API インターフェースリファレンス | MDN (mozilla.org)
AJAXのXHR#
- XHR: XMLHttpRequest
- readyState
0 | UNSENT | プロキシが作成されましたが、まだ open () メソッドは呼び出されていません。 |
1 | OPENED | open () メソッドが呼び出されました。 |
2 | HEADERS_RECEIVED | send () メソッドが呼び出され、ヘッダーとステータスが取得可能になりました。 |
3 | LOADING | ダウンロード中; responseText プロパティには部分的なデータが含まれています。 |
4 | DONE | ダウンロード操作が完了しました。 |
AJAX の Fetch#
- XMLHttpRequest のアップグレード版
- Promise を使用
- モジュール化設計、Response、Request、Header オブジェクト
- データストリーム処理オブジェクトを通じて、チャンク読み取りをサポート
Node の標準ライブラリ: HTTP/HTTPS#
- デフォルトモジュール、他の依存関係をインストールする必要はありません
機能は限られており / あまり親切ではありません
よく使われるリクエストライブラリ: axios#
- 始めに | Axios 日本語ドキュメント
- ブラウザ、nodejs 環境をサポート
- 豊富なインターセプター
//グローバル設定
axios.defaults.baseURL = "https://api.example.com";
//リクエストインターセプターを追加
axios.interceptors.request.use(function (config) {
//リクエストを送信する前に何かを行う
return config;
},function (error) {
//リクエストエラーに対して何かを行う
return Promise.reject(error );
});
//リクエストを送信
axios( {
method: 'get',
url: 'http://test.com',
responseType: 'stream
}).then( function(response) {
response.data.pipe( fs.createWriteStream('ada_lovelace.jpg'))
});
ネットワーク最適化#
-
HTTP/2 - 実世界のパフォーマンステストと分析 | CSS-Tricks - CSS-Tricks
-
プリフェッチ、プリコネクトなど
-
リトライは安定性を保証する有効な手段ですが、悪化した状況を悪化させないように注意が必要です(例えば、ネットワーク接続が切断された場合)。
-
キャッシュを合理的に使用し、最後の防衛線として機能します。
さらに詳しく#
HTTP プロトコル以外の選択肢#
拡張 - 通信方式#
WebSocket#
- ブラウザとサーバー間で全二重通信を行うネットワーク技術
- 典型的なシーン:リアルタイム性が要求される場合、例えばチャットルーム
- URL は **ws://** または wss:// などで始まります
UDP#
QUIC:Quick UDP Internet Connection は UDP に基づいています
- 0-RTT 接続(初回接続を除く)。
- TCP の信頼性のある伝送に似ています。
- TLS に似た暗号化伝送、完璧な前方セキュリティをサポート。
- ユーザースペースの輻輳制御、最新の BBR アルゴリズム。
- h2 に基づくストリームの多重化をサポートしますが、TCP の HOL 問題はありません。
- 前方誤り訂正 FEC。
- MPTCP に似た接続の移行。
- 現在のアプリケーションはあまり多くありません
まとめと感想#
今日、講師の声がとても優しく、HTTP およびその一般的なプロトコルの分析、メッセージ構造、キャッシュ戦略の分析、さらに具体的なビジネスシーンでの使用について紹介されました。
本文で引用された内容の大部分は、楊超男先生の講義 ——HTTP 実用ガイドからのものです。