2022年10月12日

Fetch API

これまで、fetchについてかなり多くのことを知っています。

そのすべての機能についてカバーするために、残りのAPIを見ていきましょう。

注意

注意: これらのオプションのほとんどはめったに使用されません。この章をスキップしても、fetchをうまく使用できます。

それでも、fetchが何ができるのかを知っておくことは良いことです。必要が生じた場合に、詳細を読んで戻ることができます。

以下は、可能なすべてのfetchオプションとそのデフォルト値の完全なリストです(コメント内の代替案)。

let promise = fetch(url, {
  method: "GET", // POST, PUT, DELETE, etc.
  headers: {
    // the content type header value is usually auto-set
    // depending on the request body
    "Content-Type": "text/plain;charset=UTF-8"
  },
  body: undefined, // string, FormData, Blob, BufferSource, or URLSearchParams
  referrer: "about:client", // or "" to send no Referer header,
  // or an url from the current origin
  referrerPolicy: "strict-origin-when-cross-origin", // no-referrer-when-downgrade, no-referrer, origin, same-origin...
  mode: "cors", // same-origin, no-cors
  credentials: "same-origin", // omit, include
  cache: "default", // no-store, reload, no-cache, force-cache, or only-if-cached
  redirect: "follow", // manual, error
  integrity: "", // a hash, like "sha256-abcdef1234567890"
  keepalive: false, // true
  signal: undefined, // AbortController to abort request
  window: window // null
});

すごいリストでしょう?

methodheaders、およびbodyについては、Fetchの章で完全に説明しました。

signalオプションは、Fetch: Abortで説明されています。

次に、残りの機能を探ってみましょう。

referrer, referrerPolicy

これらのオプションは、fetchがHTTP Refererヘッダーを設定する方法を制御します。

通常、そのヘッダーは自動的に設定され、リクエストを行ったページのURLが含まれています。ほとんどの場合、それはまったく重要ではありません。セキュリティ上の理由から、それを削除または短縮することが理にかなっている場合があります。

referrerオプションを使用すると、任意のReferer(現在のオリジン内)を設定したり、削除したりできます。

リファラーを送信しない場合は、空の文字列を設定します

fetch('/page', {
  referrer: "" // no Referer header
});

現在のオリジン内の別のURLを設定するには

fetch('/page', {
  // assuming we're on https://javascriptinfo.dokyumento.jp
  // we can set any Referer header, but only within the current origin
  referrer: "https://javascriptinfo.dokyumento.jp/anotherpage"
});

referrerPolicyオプションは、Refererの一般的なルールを設定します。

リクエストは3つのタイプに分割されます。

  1. 同じオリジンへのリクエスト。
  2. 別のオリジンへのリクエスト。
  3. HTTPSからHTTPへのリクエスト(安全なプロトコルから安全でないプロトコル)。

正確なReferer値を設定できるreferrerオプションとは異なり、referrerPolicyは各リクエストタイプの一般的なルールをブラウザに指示します。

可能な値は、リファラーポリシーの仕様に記述されています。

  • "strict-origin-when-cross-origin" – デフォルト値:同じオリジンに対しては完全なRefererを送信し、クロスオリジンに対しては、HTTPS→HTTPリクエストでない限り、オリジンのみを送信し、それ以外の場合は何も送信しません。
  • "no-referrer-when-downgrade" – HTTPSからHTTP(セキュリティの低いプロトコル)へのリクエストを送信しない限り、常に完全なRefererが送信されます。
  • "no-referrer"Refererを送信しないでください。
  • "origin" – 完全なページURLではなく、Refererにオリジンのみを送信します。たとえば、http://site.com/pathではなく、http://site.comのみを送信します。
  • "origin-when-cross-origin" – 同じオリジンに対しては完全なRefererを送信しますが、クロスオリジンリクエストに対してはオリジン部分のみを送信します(上記と同様)。
  • "same-origin" – 同じオリジンに対しては完全なRefererを送信しますが、クロスオリジンリクエストに対してはRefererを送信しません。
  • "strict-origin" – HTTPS→HTTPリクエストに対しては、Refererではなくオリジンのみを送信します。
  • "unsafe-url" – HTTPS→HTTPリクエストの場合でも、常に完全なURLをRefererで送信します。

以下は、すべての組み合わせの表です。

同じオリジンへ 別のオリジンへ HTTPS→HTTP
"no-referrer" - - -
"no-referrer-when-downgrade" フル フル -
"origin" オリジン オリジン オリジン
"origin-when-cross-origin" フル オリジン オリジン
"same-origin" フル - -
"strict-origin" オリジン オリジン -
"strict-origin-when-cross-origin" または ""(デフォルト) フル オリジン -
"unsafe-url" フル フル フル

サイトの外部から知られるべきではないURL構造を持つ管理ゾーンがあるとしましょう。

fetchを送信すると、デフォルトでは、常にRefererヘッダーをページの完全なURLで送信します(HTTPSからHTTPへのリクエストを行う場合を除く。その場合はRefererは送信されません)。

例:Referer: https://javascriptinfo.dokyumento.jp/admin/secret/paths

他のウェブサイトにURLパスではなくオリジン部分のみを知ってほしい場合は、次のオプションを設定できます

fetch('https://another.com/page', {
  // ...
  referrerPolicy: "origin-when-cross-origin" // Referer: https://javascriptinfo.dokyumento.jp
});

すべてのfetch呼び出しに設定し、すべてのリクエストを実行し、内部でfetchを使用するプロジェクトのJavaScriptライブラリに統合することもできます。

デフォルトの動作と比較した唯一の違いは、別のオリジンへのリクエストの場合、fetchはURLのオリジン部分(例:パスなしのhttps://javascriptinfo.dokyumento.jp)のみを送信することです。独自のオリジンへのリクエストの場合、完全なRefererを引き続き取得します(デバッグ目的で役立つ可能性があります)。

リファラーポリシーはfetchだけのものではありません

仕様に記述されているリファラーポリシーは、fetchだけでなく、よりグローバルなものです。

特に、Referrer-Policy HTTPヘッダーを使用してページ全体のデフォルトポリシーを設定したり、<a rel="noreferrer">を使用してリンクごとに設定したりできます。

mode

modeオプションは、偶発的なクロスオリジンリクエストを防ぐための安全対策です。

  • "cors" – デフォルトでは、Fetch: クロスオリジンリクエストで説明されているように、クロスオリジンリクエストが許可されます。
  • "same-origin" – クロスオリジンリクエストは禁止されています。
  • "no-cors" – 安全なクロスオリジンリクエストのみが許可されています。

このオプションは、fetchのURLがサードパーティから提供されており、クロスオリジン機能を制限するための「電源オフスイッチ」が必要な場合に役立つ場合があります。

credentials

credentialsオプションは、fetchがリクエストとともにCookieとHTTP-Authorizationヘッダーを送信するかどうかを指定します。

  • "same-origin" – デフォルトでは、クロスオリジンリクエストには送信しません。
  • "include" – 常に送信します。JavaScriptがレスポンスにアクセスするには、クロスオリジンサーバーからのAccess-Control-Allow-Credentialsが必要です。これはFetch: クロスオリジンリクエストの章で説明しました。
  • "omit" – 同じオリジンリクエストの場合でも、決して送信しません。

cache

デフォルトでは、fetchリクエストは標準のHTTPキャッシングを利用します。つまり、ExpiresおよびCache-Controlヘッダーを尊重し、If-Modified-Sinceなどを送信します。通常のHTTPリクエストと同様です。

cacheオプションを使用すると、HTTPキャッシュを無視したり、その使用を微調整したりできます。

  • "default"fetchは標準のHTTPキャッシュルールとヘッダーを使用します。
  • "no-store" – HTTPキャッシュを完全に無視します。このモードは、If-Modified-SinceIf-None-MatchIf-Unmodified-SinceIf-Match、またはIf-Rangeヘッダーを設定した場合にデフォルトになります。
  • "reload" – HTTPキャッシュ(存在する場合)から結果を取得しませんが、レスポンス(レスポンスヘッダーがこのアクションを許可している場合)でキャッシュを埋めます。
  • "no-cache" – キャッシュされたレスポンスがある場合は条件付きリクエストを作成し、それ以外の場合は通常のリクエストを作成します。HTTPキャッシュをレスポンスで埋めます。
  • "force-cache" – HTTPキャッシュからのレスポンスを使用します。たとえそれが古いものであってもです。HTTPキャッシュに応答がない場合は、通常のHTTPリクエストを行い、通常どおり動作します。
  • "only-if-cached" – HTTPキャッシュからのレスポンスを使用します。たとえそれが古いものであってもです。HTTPキャッシュに応答がない場合は、エラーが発生します。mode"same-origin"の場合にのみ機能します。

redirect

通常、fetchは301、302などのHTTPリダイレクトを透過的に追跡します。

redirectオプションを使用すると、それを変更できます。

  • "follow" – デフォルトでは、HTTPリダイレクトに従います。
  • "error" – HTTPリダイレクトが発生した場合にエラーが発生します。
  • "manual" – HTTPリダイレクトを手動で処理できます。リダイレクトの場合、response.type="opaqueredirect"、ゼロまたは空の状態、およびその他のほとんどのプロパティを含む特別なレスポンスオブジェクトを取得します。

integrity

integrityオプションを使用すると、レスポンスが既知の事前チェックサムと一致するかどうかを確認できます。

仕様に記述されているように、サポートされているハッシュ関数はSHA-256、SHA-384、およびSHA-512であり、ブラウザによっては他のものが存在する可能性があります。

たとえば、ファイルをダウンロードしていて、そのSHA-256チェックサムが「abcdef」であるとわかっているとします(実際のチェックサムは当然もっと長いです)。

次のようにintegrityオプションにそれを入れることができます。

fetch('http://site.com/file', {
  integrity: 'sha256-abcdef'
});

次に、fetchはSHA-256を独自に計算し、それを文字列と比較します。不一致の場合、エラーがトリガーされます。

keepalive

keepaliveオプションは、リクエストが開始されたウェブページよりも「長生きする」可能性があることを示します。

例えば、現在の訪問者がページをどのように利用しているか(マウスクリック、閲覧したページの一部など)に関する統計情報を収集し、ユーザーエクスペリエンスを分析・改善します。

訪問者がページを離れる際、そのデータをサーバーに保存したいとします。

そのためにwindow.onunloadイベントを利用できます。

window.onunload = function() {
  fetch('/analytics', {
    method: 'POST',
    body: "statistics",
    keepalive: true
  });
};

通常、ドキュメントがアンロードされると、関連するすべてのネットワークリクエストは中断されます。しかし、keepaliveオプションは、ページを離れた後でもバックグラウンドでリクエストを実行するようにブラウザに指示します。そのため、このオプションはリクエストを成功させるために不可欠です。

いくつかの制限事項があります。

  • 数メガバイトのデータを送信することはできません。keepaliveリクエストのボディサイズの上限は64KBです。
    • 訪問に関する多くの統計情報を収集する必要がある場合は、最後のonunloadリクエストに大量のデータが残らないように、定期的にパケットで送信する必要があります。
    • この制限は、すべてのkeepaliveリクエストの合計に適用されます。言い換えれば、複数のkeepaliveリクエストを並行して実行できますが、それらのボディ長の合計が64KBを超えてはなりません。
  • ドキュメントがアンロードされている場合、サーバーのレスポンスを処理することはできません。したがって、この例では、fetchkeepaliveのために成功しますが、後続の関数は機能しません。
    • 統計情報を送信するなど、ほとんどの場合、これは問題ありません。サーバーはデータを受け入れるだけで、通常、そのようなリクエストに対して空のレスポンスを送信します。
チュートリアルマップ

コメント

コメントする前にこれを読んでください…
  • 改善のための提案がある場合は、コメントの代わりにGitHub issueを提出するか、プルリクエストを送ってください。
  • 記事の内容で理解できない点がある場合は、詳しく説明してください。
  • コードを数語挿入するには、<code>タグを使用し、複数行の場合は<pre>タグで囲み、10行を超える場合はサンドボックス(plnkr, jsbin, codepen…)を使用してください。