[キャッチアップ] fetch API
スクラップ概要
axios をやめて fetch API を直接使用するか、あるいはラッパーライブラリを作りたいので、大まかな仕組みだけ確認する。
fetch() - Web API | MDN
サポートブラウザ
モダンブラウザはすべて対応済み。
また、Node.js でも 18.0.0 から概ねサポートしているため、 axios 同様にブラウザと Node それぞれで同じコードを動作させることが出来る。
概要
fetch() はグローバルのメソッドで、ネットワークからリソースを取得するプロセスを開始し、レスポンスが利用できるようになったら履行されるプロミスを返します。
このプロミスはそのリクエストに対するレスポンスを表す Response で解決します。
Promise ベースで Response オブジェクトを返してくれる。
Response は Readable Stream の形でボディにアクセス可能なのがポイントっぽい。
必要に応じてストリームをフェッチして任意のデータ形式で取得できるので無駄がない。
fetch() のプロミスはネットワークエラーが発生した場合(普通は権限の問題があったときなど)のみ拒否されます。 fetch() のプロミスは HTTP エラー(404 など)では拒否されません。代わりに、 then() ハンドラーで Response.ok や Response.status プロパティをチェックする必要があります。
axios と違って 4xx エラーなんかが発生しても Promise は resolve されるみたい。
個人的にはここは上手いこと隠蔽して 2xx 系のみ resolve してほしいかなぁ。
WindowOrWorkerGlobalScope は Window と WorkerGlobalScope の両方で実装されています。これはつまり fetch() メソッドは、リソースを取得したいと思うような大部分コンテキストで使用可能ということです。
window はわかるけど、 WorkerGlobalScope ってことは ServiceWorker 上でもグローバルに参照できるって話かな。
まぁ Node も含めてどこでもグローバル参照できるよぐらいの認識でいいか。
fetch() メソッドは取得するリソースのディレクティブではなく、コンテンツセキュリティポリシーの connect-src ディレクティブによって制御されます。
まず CSP は HTTP レスポンスヘッダーの一種で、参照できるリソースの種類や場所を制限することで、XSS を防いだりするための仕組み。
connect-src は CSF のディレクティブの一種で、fetch API などスクリプトインタフェースを使用して読み込める URL を制限するディレクティブ。
レスポンスヘッダーに
Content-Security-Policy: connect-src https://example.com/
が含まれている場合、スクリプトからは https://example.com ドメインにしかリクエストできない。
まぁ CORS を使用しないサイトなら、自サイトだけを指定しておくのが無難なのかな。
Twitter なんかでレスポンスヘッダー見てみたら、結構ガッツリ設定されてた。
構文
fetch(resource)
fetch(resource, options)
シンプルだねぇ。流石にラッパーライブラリかませたくなっちゃう。
resource
以下のいずれか
- URL を表す文字列または文字列化できるオブジェクト(
URLなど) -
Requestオブジェクト
options
ドキュメントだと options じゃなくて init って名前になってる。
基本的には Request オブジェクトの内容と近い用に見える。
- method: HTTPメソッド
- headers: HTTPヘッダー
- body: リクエストボディ
- mode: CORS を使用するかのモード
- same-origin: 同一オリジンリクエスト限定にする
- cors: クロスオリジンリクエストを使用する
- no-cors: CORS セーフなメソッド、ヘッダーの使用のみに制限する
- navigate: ページ遷移専用モード
- credentials: クレデンシャルを送信するか
- omit: 常にクレデンシャルを除外する
- same-origin: クロスオリジンリクエストの場合、クレデンシャルを除外する
- include: クレデンシャルを除外しない
- cache: ブラウザのキャッシュをどう扱うか
- default: 一致するキャッシュを探して利用する
- no-store: キャッシュを使用せず、更新もしない
- reload: キャッシュを使用せずに、更新はする
- no-cache: キャッシュを利用はするが、条件付きリクエストをサーバーに常に送信する
- force-cache: キャッシュが古かったとしても構わず使用する
- only-if-cached: force-cache に加え、キャッシュがなかった場合はエラーにする
- redirect: リダイレクトレスポンスの取り扱い
- follow: 従う
- error: エラーにする
- manual: 別のコンテキストで処理する
- referrer: リファラ文字列の指定
- referrerPolicy: リファラを送信するポリシー
- no-referrer: 常に送信しない
- no-referrer-when-downgrade: HTTPS から HTTP への遷移の場合は送信しない
- same-origin: 同一オリジンの場合のみ送信する
- origin: オリジン文字列のみを送信する
- origin-when-cross-origin: 同一オリジンにはすべて送信し、クロスオリジンにはオリジン文字列のみ送信する
- strict-origin: 同一オリジンかつプロトコルも一致する場合のみ送信する
- strict-origin-when-cross-origin: strict-origin + origin-when-cross-origin
- integrity: 取得したリソースとそのハッシュ値が一致することを検証するようのハッシュ値
- keepAlive: 接続を保持し続けるか
- signal: AbortSignal オブジェクト。通信を中断するために使用する。
MDN だけだとわからなかった部分は仕様書を読む。
返値
Promise で、 Response オブジェクトに解決します。
例外
エラーが発生するのは以下の場合
- AbortController によるリクエストの中止
- リクエストの型が不正
- ネットワークレベルのエラー
ざっと大枠わかったのでOK