HTTP(HyperText Transfer Protocol)
Overview
HTTP(HyperText Transfer Protocol)はサーバとクライアント(ブラウザ)の間でウェブページを送受信するためのプロトコル。
また、World Wide Web上の通信方法を示すものであり、この通信はクライアントからサーバーへのリクエストとサーバーからクライアントへのレスポンスで構成される。
こうしたHTTPリクエストとHTTPレスポンスには、ヘッダーーと呼ばれる一連のキーと値のペアが追加される。
HTTP自体は**ステートレス(状態を保持せず1回で完結すること)**なプロトコル
リクエスト (GET) => レスポンス (200 OK ...) で手続きが完結。
SMTPのように複数の手続きを踏む必要はなく、その時の状態も保持していない。
HTTP 歴史
現在最新のversionは1.1
1.1になる前には0.9と1.0の2つのバージョンが存在していた。
また1.1の後継もある。
※0.9に関しては仕様書は存在しない。Berners-LeeがWebを発明していたときのプロトコルが呼ばれている。
- 0.9 : headerがなかった
- 1.0 : IETFが標準化された最初のバージョン(POST対応)
- 1.1 : HTTPの完成(バーチャルホスト対応)
- 2.0 : 2015年ほど
チャンク転送・Acceptヘッダーによるコンテントネゴシエーション・複雑なキャッシュコントロール、持続的接続などの機能。
1.1以降も議論が続けられているが、HTTPそのものの価値をRESTアーキテクチャスタイルに見出した結果、HTTP1.1を有効に活用していこう。
というのが現代的な開発スタイルとなっている。
参考
リファレンス(一番わかりやすい)
HTTP入門
冪等性について
ブラウザからサーバまでわかりやすい
プロトコル
HTTPの仕組み再入門
普及が進む「HTTP/2」の仕組みとメリットとは
HTTP仕組み
BASEとなっているのはTCP/IP
これをみて参考にする(一番いいためまとめる)
HTTPリクエストの種類
Form: 同期通信
- 説明: HTMLフォームを使用して送信されるリクエスト。通常、ページが再読み込みされる。
- 特徴:
- デフォルトでは、ページがリロードされる同期通信。
- データはURLエンコードされて送信される。
- サーバーからのレスポンスに基づいてページが更新される。
XMLHttpRequest (XHR): 非同期通信(CORS対象)
- 説明: JavaScriptを使用して非同期にサーバーと通信するためのオブジェクト。
- 特徴:
- 非同期通信をサポートし、ページの一部を更新できる。
- CORS(Cross-Origin Resource Sharing)の制約を受ける。
- レスポンス形式としてXML、JSON、HTML、テキストなどを扱える。
- 同期通信も可能だが、推奨されない。
Fetch: 非同期通信(CORS対象)
- 説明: モダンなJavaScript APIで、XHRに代わるものとして設計された。
- 特徴:
- 非同期通信をサポートし、Promiseベースのインターフェースを提供。
- CORSの制約を受ける。
- よりシンプルで直感的な構文。
- レスポンスをストリームとして扱えるため、部分的なデータ取得が可能。
JSONP
- 説明: JSON with Padding。クロスドメインリクエストを行うための古い方法。
- 特徴:
<script>
タグを使用してリクエストを送信する。- サーバーがJavaScriptの関数をラップしたJSONを返す。
- 主にGETリクエストに使用。
AJAX(Asynchronous JavaScript and XML)
- 説明: 非同期通信の総称。XMLHttpRequestやFetchを用いた通信方法を指す。
- 特徴:
- サーバーと非同期でデータのやり取りをする。ページの一部を更新できる。
- リクエストは非同期で行われるため、ページのリロードが不要。
- JSON、XML、HTMLなどさまざまな形式のデータを扱える。
通常のHTTPリクエスト
- ブラウザがHTMLをリクエストする
- ユーザーがブラウザでURLを入力するか、リンクをクリックする。
- ブラウザはDNSサーバにアクセスし、ドメイン名をIPアドレスに解決する。
- そのIPアドレスに対して、HTTPリクエストを送信する。
- サーバがリクエストを受け付け、DBに問い合わせをしHTMLを生成
- サーバがリクエストを受信する。
- リクエストに基づいて必要なデータをデータベースから取得する。
- データを基にHTMLを生成し、レスポンスとしてブラウザに返す。
- ブラウザがHTMLを受け取る
- ブラウザがサーバからのレス ポンスを受信する。
- レスポンスのHTTPステータスコードを確認し、成功(200 OK)などを確認する。
- HTMLのパースを開始
- ブラウザは受け取ったHTMLドキュメントのパースを開始する。
- JavaScriptやCSS、フォントや画像などのアセットをリクエスト
- HTML内のリンク(
<link>
タグ)、スクリプト(<script>
タグ)、画像(<img>
タグ)などを解析し、それらのアセットのリクエストを順次行う。
- HTML内のリンク(
- ブラウザがアセットを受け取る
- 各アセットのリクエストに対するレスポンスを受け取る。
- ※キャッシュが有効な場合、ブラウザはキャッシュからアセットを取得することもある。
- アセットのパース
- 受け取ったCSS、JavaScript、画像などのアセットをパースし、適用する。
- JavaScriptの実行やCSSによるスタイルの適用が行われる。
- HTMLのレンダリングが完了する
- 全てのアセットがロードされ、パースが完了すると、ブラウザは最終的なレンダリングを行います。
- ユーザーは完全にレンダリングされたウェブページを閲覧できるようになる。
補足
- キャッシュの利用: ブラウザはリソースの再取得を避けるために、キャッシュされたコンテンツを利用する場合があります。
- 非同期リクエスト: AJAXリクエストなど、ページがロードされた後にJavaScriptが追加のリソースを非同期でリクエストすることもあります。
JSやCSSなどアセットのリクエストはレスポンスを受診しHTMLのパースが始まったタイミングで実行される。
そのためHTMLのパースがどんなに早く終わってもアセットのダウンロード待ちが発生してしまうと全体の描画を効率化するためにはアセットのリクエストをもっと早くするべき。
アセットのロード開始タイミングを早める
HTTPにはpreloadという仕組みがあり、HTTPレスポンスヘッダーやHTMLのタグ中にこのアセットを先にロードしてくださいと指定ができる。
レスポンスヘッダーに次の要素を追加する。
このヘッダーを受け取るとブラウザはHTMLを取った直後、HTMLをパースする前にアセットのリクエストを開始できる。
HTTP 1.1
バーチャルホストなどに対応した「HTTP/1.1」が策定された。
HTTP/1.1ではクライアントが複数のリクエストを同時に送れるようになったが、その場合も必ずリクエストされた順でレスポンスを返すようになっている。
そのため、たとえばレスポンスとして容量の大きいファイルを返す場合や、レスポンスを返すための処理に時間がかかるような場合でも、後続のレスポンスは先のレスポンスの送信が完了するまで送信できない。
そのため、多くのWebブラウザではWebサーバーに対して同時に複数のコネクションを確立することとで、並行してコンテンツをダウンロードできるよう実装されている。
HTTP 2.0
HTTP/2は従来のHTTPを踏襲しつつも、新たな転送手段を提供することで既存の問題点を解決し、より少ない通信量でより迅速にやり取りを行えるようになっている。
HTTP/2の最大の特徴はストリームという概念を導入したこと。
これによって1つのコネクション内で同時に並行して複数のリクエスト/レスポンスを処理できるようになった。
HTTPの仕様ではステータスコードが決まるまでレスポンスを返せなかった。
つまり、application.jsを利用することが自明だったとしてもWebアプリケーション自身 がレスポンスを返すまでは待つ必要がありました。
これを解決するのがEarlyHintsと呼ばれる仕様。
ステータスコード103として、本来のレスポンスを送る前に、リソースのヒントを送ることができます。
- 上記で起きた他の言語影響
- 主要なブラウザが軒並みES6をサポートした事により、 ES6で書かれたコードをトランスパイルすることなく、そのまま動作するようになったこと。
- HTTP/2が普及したことによりwebpackでファイルを結合するメリットが薄れたこと。
HTTP 3.0
N/A
HTTPでサーバへデータを渡す
HTTP内でのクライアント
今回POSTメソッドについて言及しましたが、HTTPプロトコル(rfc2616)では、メッセージボディをセットできるメソッドについては特に言及していないため、POST以外のメソッド(たとえばGETメソッド)でもメッセージボディをセットすることはできます。 ですが、ブラウザからGETメソッドでリクエストを送信する場合、通常はメッセージボディではなくHTTPパラメータとして設定されます。 このため、サーバー側の処理としてGETメソッドの処理ではメッセージボディに何かデータが設定されてくる ということは一般的には期待しません。
クエリパラメーター
?以降のフォーマットに関してどういう値設計にするのかのルールはとくに明言されていない(RFC)
しかし,query構成要素はしばしば key=valueの対の形式で識別するための情報を運ぶために使用され、そこで頻繁に使用された値は別のURIの参照のため時にはそれあらの文字をパーセントエンコーディングすることを避ける方がユーザビリティのためには良い
とあるように一般論として key=value
の形式であるぐらいしかRFC上では語られていない。
クエリパラメーターを配列で渡したいとき
https://stg.www.yumenographia.com/tickets/?dates=2021-10-07,2021-10-10,2021-10-11,2021-10-12
?の後に ,(カンマ)
区切りで渡す。それをserver側で配列に変換するのがひとつのやり方。
クエリパラメーター変換
numberなどで送ってもどうやらstringに変換されるっぽい。
localhostのhttps化
閲覧ページのHTTP versionを調べる
HTTP content negotiation(コンテントネゴシエーション)
HTTP においてコンテンツ交渉 (content negotiation) は、同じ URI におけるさまざまな表現のリソースを提供するために使用する仕組みであり、ユーザーエージェントはどのリソースがユーザーにもっとも適しているか (例えば文書の言語はどれか、画像形式はどれか、コンテンツエンコード方式はどれか) を指定することができます。
HTTP body-parserとは
ブラウザなどのクライアントからサーバーに対して処理のリクエストを行う際に送るメッセージメッセージボディ(Message body)という。
- クライアントから一緒に送信するデータ。
- クライアントからのリクエスト応答としてサーバーからクライアントへ返信するデータ。
body-parserは、このメッセージボディを解析してプログラムで参照しやすいオブジェクトに変換してくれるライブラリ。
一番わかりやすいのはPOSTメソッドを使ったフォーム情報の送信時です。 ユーザーがブラウザに表示された入力フォームにデータを入力し、「送信」をクリックしたときにPOSTメソッドでフォームデータをサーバーに送信しますが、そのときにブラウザは入力されたデータをPOSTメソッドのメッセージボディにセットして、HTTPヘッダーーに必要な情報(メッセージボディの文字数や文字コード等)を一緒にセットしてサーバーに送信します。 サーバーは、受け取った情報からメッセージボディを特定し、HTTPヘッダーーに指定された情報をもとに復元してサーバー側で処理します。
WEBサーバーとしては、この処理は定形処理といっていいぐらい、どのようなアプリケー ションでも必要となることが予想される処理で、毎回個別にプログラムを書くのはあまりにもムダなのでbody-parserという拡張モジュールが担ってくれるということです。
HTTP上で認証を行う場合
- セッションによる認証
- リクエストボディにトークンを含める認証
- 独自ヘッダーにトークンを含める認証
- Authorizationヘッダーを用いた認証(Basic, Digest, Bearer)
- JWT認証
などがある。
Bearer認証 : bearerは担い手や使いといった意味を持つ
Authorization Bearer ヘッダを用いた認証 API の実装
Bearer認証は、トークンを利用した認証・認可に利用されることを想定しており、OAuth 2.0の仕様の一部として定義されているがその仕様内でHTTPでも使用しても良いと記述されている。
HTTPのAuthorizationヘッダーにスキームとして指定でき Authorization: Bearer <token>
のようにして指定する。
トークンの形式はtoken68の形式で指定することが定められている。
Authorization ヘッダー
Authorizationヘッダーに指定できるスキームには以下がある。
- Basic
- Digest
- Bearer これらのスキームはIANAによって管理されている。
token68
token68は1文字以上の半角英数字 -(ハイフン), . (ドット), _ (アンダーバー), ~ (チルダ), + (プラス), / (スラッシュ)から構成された文字列を指す. 文字列の末尾に任意個の = (イコール)が挿入されていても良い.
リクエストとレスポンスの流れ
まずクライアントから Authorization: Bearer <token>
を含めたリクエストが投げられる。
それを受け取ったサーバは WWW-Authenticate: Bearer realm="XXXX"
形式を返す。
又は WWW-Authenticate: Bearer error="XXXX"
形式のヘッダー を含めたレスポンスを返す。
成功パターン
とくに返したいパラメーターがない場合はrealmを空にして返す。
WWW-Authenticate: Bearer realm=""
失敗パターン
リクエストにAuthorizationヘッダーが含まれていないケース(401 Unauthorized)
WWW-Authenticate: Bearer realm="token_required"
リクエストパラメーターが不正なケース(400 Bad Request)
WWW-Authenticate: Bearer error="invalid_request"
トークンが失効、破損しているケース(401 Unauthorized)
WWW-Authenticate: Bearer error="invalid_token"
トークンのスコープが不十分なケース(403 Forbidden)
WWW-Authenticate: Bearer error="insufficient_scope"
トークン保存場所
クライアント側はlocalStorageかsessionStorage。 サーバ側はDBに保存することへなる。
トークンの有効期限
トークンが漏れてしまうと第三者がそのトークンを使ってあらゆる操作ができてしまうため, 有効期限は設けておくべき。
httpとセッション
HTTPは基本的に1つのリクエストと1つのレスポンスだけで完結する。 何度リクエストを送っても前回と同じ人のリクエストだなと認識されない。 同じユーザに対して、リクエストのたびにそのユーザ用のレスポンスを返すといった仕組みを(セッション)を作るにはサーバ側で工夫が必要になる。
URLの説明
スキーム://ホスト:Port/path
Origin(オリジン)
ウェブコンテンツのオリジンOriginは、ウェブコンテンツにアクセスするために使われる。
URLのスキーム(プロトコル)・ホスト(ドメイン)ポート
によって定義される。
スキーム、ホスト、ポートがすべて一致した場合のみ、二つのオブジェクトは同じオリジンであると言える。
操作によっては同じオリジンのコンテンツに限定されており、この制約は CORS を使用して緩和できる。
- 同一オリジンの例
# スキーム (http) およびホスト (example.com) が同じなので同一オリジン
http://example.com/app1/index.html
http://example.com/app2/index.html
- 異なるオリジンの例
# スキームが異なる
http://example.com/app1
https://example.com/app2
# ホストが異なる
http://example.com
http://www.example.com
http://myapp.example.com
# ポートが異なる
http://example.com
http://example.com:8080
クロスサイト(クロスオリジン)
スキーマ(httpやhttps)やホスト名・ポート番号のどれか1つでも異なるウェブサイトのことを「クロスサイト(またはクロスオリジン)」という。 クロスサイトな2つのサイト間では、簡単にデータがやりとりできないようになっています(セキュリティを保つため)
HTTPヘッダー
ヘッダーはコロンで区切られたキーと値のペアで構成される。 ※値はディレクティブ(指示)と呼ばれる。
# key: 値,値
cache-control: public, max-age=14400
リクエストヘッダー
-
Accept(要求) ブラウザが受信可能なデータ形式(MIMEタイプ)をサーバに伝える。 アスタリスクはすべてを意味する。
-
Accept-Encoding 参考URL
HTTPリクエストヘッダー Accept-Encoding を理解するためには、まずはHTTP通信データの圧縮について理解する必要があります。 皆さんが普段目にしているホームページは、HTMLなどのテキストで作られていることは本ページを見られている方ならご存知でしょう。 またスマートフォンアプリなども JSON や XML などのテキスト形式でサーバーとデータの受け渡しをしています。
サーバーとの通信データ量を減らしたいと考えた場合、コンテンツの内容を変えずにそれを実現するには、データを圧縮する方法が考えられます。 テキストはバイナリなどに比べて圧縮しやすく、HTML, スタイルシート(CSS), JavaScript, JSON, XML などのWEBで利用されているテキストを圧縮して送受信すれば、通信データ量を減らすことができるというわけです。 しかし、通信データを圧縮する場合に考慮すべき点もあります。 それはクライアントとサーバーが、共通の圧縮アルゴリズムをサポートしている必要がある点です。 サーバーが一方的に圧縮されたコンテンツを送りつけても、クライアントが解凍できないと意味がありません。 またデメリットとしては、データ送信前とデータ受信後に圧縮・解凍の処理が必要になるため、平文でデータを送受信するよりも処理負荷が高まることがあげられます。
ポイント
- コンテンツを圧縮して送信すれば、ネットワークを流れるデータ量を減らすことができる
- 通信データを圧縮するには、クライアントとサーバが共通した圧縮アルゴリズムをサポートする必要がある。
- 通信データを圧縮した場合、データ送信前とデータ受信後に圧縮・解答の処理を行うため処理負荷は高まる。
目的
Accept-Encodingヘッダーは、HTTPクライアントがサーバーにHTTPリクエストを送信する際に付与するヘッダー項目です。
Accept-Encodingヘッダーの目的は、クライアントがサポートしている圧縮方式をサーバーに教えることです。 サーバーは送られてきたAccept-Encodingヘッダーの値を見て、クライアントに合う圧縮アルゴリズムでコンテンツを圧縮して返却してあげれば良いというわけです。
- Allow(要求/応答) 要求URLで示すリソースに対して使用可能なメソッドの一覧を示す。下記の例ではリソースに対してGET, HEAD, PUTメソッドを使用可能 であることを示す。
Allow: GET, HEAD, PUT
- Authorization(要求)
認証が必要なリソースに対して認証情報を伝えます。たとえば、BASIC認証の場合は、Basicの文字と、ユーザ名とパスワードをコロン(:)で連結したものを
BASE64形式
にエンコードしたものを転送する。
Authorization: Basic dGFuYWthOmhpbWl0c3U=
Referer(リファラー)
Referer リクエストヘッダーには、現在リクエストされているページへのリンク先を持った直前のウェブページのアドレスが含まれています。 Referer ヘッダーにより、サーバーは人々がどこから訪問しに来たかを識別し、分析、ログ、キャッシュの最適化などに利用することができます。
ステートフルとステートレスの比較
前提 セッションの状態 一連のインタラクティブな操作(session)における各状態(state)の こと
ステートフル
サーバがクライアントのセッションの状態を保持しているという制約のこと 特徴:セッションの状態によってリクエストに対するレスポンスが変わる。 例:FTP, SMTP
ステートレス
サーバがクライアントのセッションの状態を保持しないという制約のこと 特徴:リクエストに対するレスポンスが変わらない。 例:HTTP
Bearer認証について
Webhookとは
アプリケーションの更新情報を他のアプリケーションへリアルタイム提供する仕組みや概念のこと
通知する、Webhookを送るなどの言葉はPOSTリクエストのことを指している。