yanachuwan9sm / til

Today's I Learned for me.
0 stars 0 forks source link

Real World HTTPを読む #10

Closed yanachuwan9sm closed 6 months ago

yanachuwan9sm commented 8 months ago

理解が難しい所や今理解する必要がなさそうな所は「さら読み」 重要そうな部分は別途技術書で理解を深めるなどする。

yanachuwan9sm commented 8 months ago

1章 : HTTP/1.0の世界 : 基本となる4つの要素

RFC(Request For Comment)なのに、仕様書って何で?という疑問に早速答えてくれてる。

HTTPの仕様は後方互換性を維持するように作られていますが、セキュリティ関連のもの以外はなるべく新しい方を使う方が良いでしょう

セキュリティ関連のヘッダーイマイチ理解してないな〜〜

HTTPは、電子メールから ヘッダー + 本文 を、NNTP(Network News Transfer Protocol)からメソッドとステータスを導入したのか。そして、全ての始まりとしては電子メールから。

ステータスコード

100番台 : 処理中の情報の伝達。そこそこ特殊なユースケース。

200番台 : 成功時のレスポンス。

300番台 : サーバーからクライアントへの命令。リダイレクトやキャッシュの利用を指示。(エラーではなく、あくまで正常処理の範疇)

400番台 : クライアントから送られたリクエストに不備がある場合に渡されるもの

500番台 : サーバー内部でエラーが発生した場合にクライアントに渡されるもの

リダイレクト

ステータス メソッド変更 永続的 or 一時的 キャッシュ 説明
301 (Moved Premanently) 永続的 する ドメイン移転、ウェブサイト引っ越し、HTTPS化
302 (Found) 一時的 指示があれば 一時メンテナンス、モバイルページ転送
303 (See other) 許可 永続的 しない ログイン後のページ遷移
307 (Temporary Redirect) 一時的 指示があれば RFC7231で追加
308 (Moved Redirect) 永続的 する RFC7538で追加

301/308 -> リクエストされたページが別の場所へ移動した場合に使用する。(Googleは検索エンジン側にページ移動を伝える手段として、301を推奨)

302/307 -> 一時的な移動(モバイル専用サイトに移動、メンテナンスページの表示)

303 -> リクエストされたページには返すべきコンテンツが存在しない or 本来返すべきページが別にある場合に遷移させる。

ステータスコードが301、302、303で、GET以外のメソッドだった場合はGETメソッドでリダイレクトを送り直す。 👉 そのため、メソッド変更に許可が必要なステータスコード 307 308 が追加されている。

なぜNext.jsは307と308を使うのですか?従来、一時的なリダイレクトには302、恒久的なリダイレクトには301が使われていましたが、多くのブラウザは元のメソッドに関係なく、リダイレクトのリクエストメソッドをGETに変更しました。たとえば、ブラウザがPOST /v1/usersリクエストを行い、ステータスコード302と location/v2/users を返した場合、その後のリクエストは期待されたPOST /v2/users ではなくGET /v2/usersになるかもしれません。Next.jsは、307一時リダイレクトと308永久リダイレクトのステータスコードを使って、使用されたリクエストメソッドを明示的に保持します。

permanentをtrueにするとステータスコードは308となり、リダイレクトがキャッシュに保存されます。falseにするとステータスコードは307となり、リダイレクトはキャッシュされません。 https://nextjs.org/docs/pages/api-reference/next-config-js/redirects

URL

yanachuwan9sm commented 8 months ago

2章 : HTTP/1.0のセマンティクス・ブラウザの基本機能の裏側

シンプルなフォームの送信(x-www-form-urlencoded)

ファイル送信に必要な情報全てを送ることは出来ない。(ファイル名のみが送信されてしまう)

<from method="POST">
  <input name="title" />
  <input name="author" />
  <input name="submit />
</form>
curl --http1.0 --data-urlencode title="Head First PHP & MySQL" --data-urlencode author="Lynn Beightley, Michel Morrion" http://locahost:18888

// output
title=Head+First+PHP+%26+MySQL&author=Lynn+Beightley%2C+Michel+Morrion

フォームを使ったファイルの送信(multipart/form-data)

項目ごとに、追加のメタ情報をタグとして保持することができる。 @ファイル名は x-www-form-urlencode でも使用できる。(その場合はファイル名ではなくファイルの内容が展開されて送信される)

curl --http1.0 -F title="Head First PHP & MySQL" -F author="Lynn Beightley, Michel Morrion". -F attachment-file=@test.txt http://localhost:18888

// output
POST / HTTP/1.0
Host: localhost:18888
Connection: close
Accept: */*
Content-Length: 444
Content-Type: multipart/form-data; boundary=------------------------85380971a6fac188
User-Agent: curl/7.77.0

--------------------------85380971a6fac188
Content-Disposition: form-data; name="title"

Head First PHP & MySQL
--------------------------85380971a6fac188
Content-Disposition: form-data; name="author"

Lynn Beightley, Michel Morrion.
--------------------------85380971a6fac188
Content-Disposition: form-data; name="attachment-file"; filename="test.txt"
Content-Type: text/plain

hello
--------------------------85380971a6fac188--
yanachuwan9sm commented 8 months ago

コンテントネゴシエーション!?始めて聞きました(白目)

yanachuwan9sm commented 8 months ago

Cookie & Session

image https://zenn.dev/ritou/articles/b5cfeef911f9b3

What`s is Cookie?

(set-cookieを)送ったら次から(Cookieとして)送り返してくるヤツ。 👉 ブラウザは Set-Cookie してきたサイトを覚えておき、そのサイトにアクセスするたびに Cookie ヘッダで自動で送り返す。 👉 いわゆる画面に表示される URL だけではなく、そのサブリソース(image/JavaScript/iFlame)にも適用される。

一意な値を Cookie として付与すれば、ユーザが 区別 できるが、この時点では 識別 はしてない

最近の EC サービスは、ログインしていなくてもショッピングカートに追加でき、決済直前で認証を挟む実装が多いが、これは先にカートのための 区別 を行い、あとから 識別 していることになる。

Cookie とは必ずしも認証結果というわけではなく、ユーザ同士が 区別 できれば良いだけのユースケースもあるというのが、 Cookie の使い方を考える上で非常に大事なことだ。 3PCA 2 日目: Cookie による区別と識別 | blog.jxck.io

What`s Session?

セッション 👉 サーバー側にデータを保存する仕組み。(サーバーがユーザーの情報や状態をセッションID(番号)として記憶しておくためのもの)

Cookie と Session の違い

ヘッダの中に情報を入れて相手を識別する点では全く同じです。 それがCookieの場合は丸裸の情報になっていて、セッションの場合は受付番号になっているかの違い。

Cookie主なユースケース

クッキーを使ったセッション管理

(HTTPはその時の要求に対しての応答を返すだけで、前回の状態を保持できないステートレスなプロトコルであるため)クライアントとサーバーの間のセッション状態を保持する方式として Cookie & Sessionを用いる必要がある。

そのセッション情報(セッションID)をどこ(セッションストレージ)に保存するかで大きく三種類ある。 👉 クッキーにする?Redisにする?サーバーのメモリにする?

● CookieStore(クッキー方式)

● Redis(インメモリ方式)

● DB(データベース方式)

以下はRedis(またはDB)の場合の処理の一連の流れ。

  1. セッションを識別するためのID(セッションID)を生成する。(このセッションIDは一意の値であり、セッションを識別するためのキーとなる)
  2. レスポンス時に、セッションID(通常、暗号化や署名を行い保護する)をクライアント側の Cookie に保存する(Set-Cookie)。
  3. クライアントからの通信リクエストがあると、サーバー側はCookieからセッションIDを読み取る。
  4. 読み取ったセッションIDを使用して、サーバー側のセッションストレージ(データベースやメモリなど)からセッション情報を取得する。(セッション情報にはユーザー情報や処理状況などの様々なデータが紐付いてる)
  5. サーバー側は取得したセッション情報を利用してリクエストの処理を行います。必要に応じてセッション情報を更新または保存します。
  6. レスポンスがクライアントに返される際には、必要に応じてセッションIDをCookieに再度設定します。

Node.js Expressでの安全なセッション管理

ユーザーのセッション情報をスケーラブルに保つ 2 つの方法 #JavaScript - Qiita

署名付きクッキーによるセッションデータの保存

署名付きURL と 署名付きクッキー の違い あんまり理解してないかもしれない。

署名付きクッキー https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html#private-content-how-signed-cookies-work https://zenn.dev/tera_ny/articles/034c2cca6674b3

セッション認証とトークン認証について

3rd Party Cookie

3rd party cookieとは?については以下の記事がめちゃめちゃ分かりやすい。 https://blog.jxck.io/entries/2023-12-04/3pca-3rd-party-cookie.html

3rd party Cookie廃止するね〜(参考) これで簡単な確認はできそう。

yanachuwan9sm commented 8 months ago

HTTP Cache

HTTP キャッシュの動作は、リクエスト ヘッダーレスポンス ヘッダーの組み合わせで制御されます。ウェブ アプリケーションのコード(リクエスト ヘッダーを決定)とウェブサーバーの構成(レスポンス ヘッダーを決定)の両方を制御するのが理想的

リクエスト ヘッダーにおけるキャッシュ制御

デフォルト設定(ブラウザ)のままが一般的。

ほとんどの場合、ブラウザがリクエストを行う際に、ユーザーに代わってそれらのヘッダーを設定している。

更新頻度のチェックに影響するリクエスト ヘッダー(If-None-MatchIf-Modified-Since など)は、HTTP キャッシュ内の現在の値に対するブラウザの認識に基づいて表示されます。

レスポンスヘッダーにおけるキャッシュ制御

ウェブサーバーがレスポンスを送信する際に、明示的にヘッダーを追加し、細かく制御する必要がある。

(ちなみに、ブラウザは、そのコンテンツ タイプに最も適したキャッシュ動作のタイプを実質的に推測するため、Cache-Control レスポンス ヘッダーを省略しても HTTP キャッシュは無効にならない)

キャッシュを制御する主なヘッダーは以下の3通り。また、考慮するべき優先度は Cache Control > ETag > Last-Modified 。

Cache-Control:

サーバーは Cache-Control ディレクティブを返して、ブラウザやその他の中間キャッシュが個々のレスポンスをキャッシュに保存する方法と保存期間を指定できます。

Cache-Control 値 説明
max-age=86400 レスポンスは、最大 1 日間(60 秒 x 60 分 x 24 時間)ブラウザおよび中継キャッシュでキャッシュに保存できます。
private, max-age=600 レスポンスはブラウザで最大 10 分(60 秒 x 10 分)キャッシュに保存できますが、中継キャッシュは保存できません。
public, max-age=31536000 レスポンスは、任意のキャッシュに 1 年間保存できます。
no-store レスポンスをキャッシュに保存することはできず、リクエストごとに完全に取得する必要があります。

RFC 5861 - 古いコンテンツ用のHTTPキャッシュコントロール拡張にて追加された stale-while-revalidateを用いる事で、キャッシュが古くなった時一旦はそれをユーザーに見せながら裏で最新のデータを取得することで、サーバーへのリクエストにかかる時間をユーザーから隠蔽できるのが嬉しい。

image

しかし、主要ブラウザーにおいて、全て対応されている訳ではないことがマイナスポイント。

ETag と Last-Modified はどちらも同じ目的を果たし、期限切れのキャッシュ ファイルを再ダウンロードする必要があるかどうかをブラウザが判断する。(ETag は、精度が高いため推奨される方法)

ETag:

ブラウザは、期限切れのキャッシュされたレスポンスを見つけると、小さなトークン(通常はファイルのコンテンツのハッシュ)をサーバーに送信して、ファイルが変更されたかどうかを確認できます。サーバーから同じトークンが返された場合は、ファイルは同じであるため、再度ダウンロードする必要はありません。

Last-Modified:

1999 年当時のキャッシュ保存のデフォルト設定。 このヘッダーの目的は ETag と同じですが、ETag のコンテンツ ベースの戦略ではなく時間ベースの戦略を使用して、リソースが変更されたかどうかを判断します。


HTTPキャッシュとは異なるものとしてBFキャッシュもある。


HTTP キャッシュ - HTTP | MDN

キャッシュを大切に ❤️  |  Articles  |  web.dev

HTTP キャッシュを使用して不要なネットワーク リクエストを防止する  |  Articles  |  web.dev

yanachuwan9sm commented 8 months ago

3章 : Go言語によるHTTP/1.0クライアントの実装

1、2章の内容を実際に curlコマンド(Go言語でGET/POSTメソッドを叩く)で確認するやつ。 curlでも動作確認はできるから、GO言語を学びたい(組み込みインターフェースの説明が主)以外の理由がなければ別にさらっ〜と読み飛ばしていいかも。

Golangでここら辺を実装する際は読み直すといいのかも、、、?

yanachuwan9sm commented 8 months ago

HTTP/1.1におけるプロトコルシンタックスの変更点

4章では以下の項目の中でもTLSの説明に多くのページを割かれている。(それほどHTTP/1.1におけるTLSのサポートのインパクトが大きかったと言うこと??)

最新の仕様

yanachuwan9sm commented 8 months ago

Keep-Alive

yanachuwan9sm commented 8 months ago

TLSによる暗号化通信

13 にて別途切り出し

概要だけは復習したけど、TLS 1.3 の TLSハンドシェイクのシーケンスやら鍵交換アルゴリズム周りには全く触れていないので、ガッツリ学ぶまで行かなくとも、HTTP/3 における TLS の立ち位置やらセキュリティの部分は普段からアンテナを立てておく必要があるな〜と思った。

yanachuwan9sm commented 8 months ago

OPTIONとCONNECTメソッドっていつ使うんですか、、、?

yanachuwan9sm commented 8 months ago

5章 : HTTP/1.1のセマンティクス : 広がるHTTPの用途

XMLHttpRequest

これが誕生するまでは、デフォルトのHTTPリクエストしか無かった。(裏技的なものはあった) これにより以下のメリットが生まれた。

ただし、便利な反面セキュリティの強化する観点から、Sama Origin Policy や CORS が生まれた。

XMLと何が関係あるん?ってずっと疑問に思ってたけど、 IEに無理やり組み込むために、XML処理ライブラリのリリースと被せるにあたって HTTP用途のものなのに、便宜上「XML」と言う名前がついたものがリリースされたのか。 歴史を知るとなかなか面白い由来。

RPC

そこまで深くない、これまでのRPCの歴史がさらっ〜と書いてある程度。 そんなにしっかりではなくゆるく読んだぐらい。 HTTP 1.1 が出来たぐらいに生まれたもので歴史があるんだな〜と言う温度感。 XML-RPC > SOAP > JSON-RPC

WebDAV

HTTPプロトコルを拡張した分散ファイルサービスの事らしい。(知らんかった)

この技術を活用して現在普及しているサービスで言うと、Googleドライブなどのオンラインストレージ・サービス(クラウド上で複数の利用者が、ファイル共有とその場での編集作業を比較的安全に行うことが可能)

HTTPは、自組織への不正侵入を防ぐためにプロトコルに応じて出入りを許可したり禁止したりすることでセキュリティレベルを維持する仕組み(ファイアウォール)を通過できるから、HTTPを拡張し、WebDAVでファイル共有という機能を実現しちゃおぜ!的なモチベなのかな???

認証・認可プラットフォーム

HTTPプロトコルに機能が増えてリッチなアプリケーションになるにあたって、 アプリケーションとして出来ることが増えた = 認証・認可の重要性が高まってきたからこの章で紹介されてる感じ??とりあえず今現在でもマストで抑えている必要がある部分ではある。

↓ OpenID関連技術仕様の日本語訳や、プレゼンテーション資料、その他各種文書 https://openid.or.jp/document/

認証・認可プラットフォームに関しては、ざっくり読んで別途ちゃんとやる!!

↓OAuth、OpenID Connect についてはScrapboxでまとめた↓ https://scrapbox.io/trashbox97/OAuth https://scrapbox.io/trashbox97/OpenID_Connect

yanachuwan9sm commented 7 months ago

6章 : GO言語によるHTTP/1.1クライアントの実装

とりあえず後回し。(後でやる)

yanachuwan9sm commented 7 months ago

7章 : HTTP/2、HTTP/3のシンタックス : プロトコルの再定義

HTTP/2の大きな目的は「通信の高速化」。HTTP/1.1からの変更点は以下の通り。

・ストリームを使ってバイナリデータを多重に送受信する仕組みに変更 ・ストリーム内での優先順位や、サーバーサイドからデータ通信を行うサーバーサイドプッシュを実装 ・ヘッダー部が圧縮されるようになった。