概要
XMLHttpRequest
で GET メソッド
を指定しているのに OPTIONS メソッド
が送信される事がありました。
XMLHttpRequest
でパラメータなどは正しいのに、正しくリソースが取得できないときに役に立つかもしれません。
XMLHttpRequest の実装
GET メソッド
を指定しているのに OPTIONS リクエスト
が送信されるコードは下記のようなものでした。
単純に GET メソッド
で指定した URL にリクエストを送信するものです。
var request = new XMLHttpRequest();
request.open('GET', 'https://hoge');
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
var data = JSON.parse(this.response);
}
};
request.send();
しかし、上記のようなリクエストを送ると、 GET メソッド
ではなく OPTIONS メソッド
が送信されます。
これは、 プリフライトリクエスト
を行う条件を満たしているためです。
プリフライトリクエスト
プリフライトリクエストは OPTIONS メソッド
をサーバへ送信して、本来送信したいリクエストが安全かどうかを確かめるものです。
プリフライトリクエストの流れは下記のようなものです。
-
OPTIONS メソッド
をサーバへ送信 - サーバは許可しているリクエストメソッドやリクエストヘッダなどをクライアントへ返信
- 本来のリクエストを送信
プリフライトリクエストが送られる条件
下記の条件を満たすリクエストは最初にプリフライトリクエストを行います1。
- リクエストが以下のメソッドのいずれかを使用した場合。
- PUT
- DELETE
- CONNECT
- OPTIONS
- TRACE
- PATCH
- または、ユーザーエージェントによって自動的に設定されたヘッダー (たとえば Connection, User-Agent, または Fetch 仕様書で "forbidden header name" として定義されている名前のヘッダー) を除いて、 Fetch 仕様書で "CORS-safelisted request-header" として定義されている以下のヘッダー以外のヘッダーがリクエストに含まれている場合。
- Accept
- Accept-Language
- Content-Language
- Content-Type (但し、下記の要件を満たすもの)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- または、 Content-Type ヘッダーが以下の値以外の場合。
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
- または、リクエストに使用される XMLHttpRequestUpload オブジェクトに1つ以上のイベントリスナーが登録されている場合。
- または、 ReadableStream オブジェクトがリクエストで使用されている場合。
今回は、 Content-Type
を指定していないために
Content-Type ヘッダーが以下の値以外の場合。
を満たしているので OPTIONS メソッド
で送信されていました。
まとめ
仕事で GET メソッド
でリソースを取得して表示するときに、サーバからエラーが帰ってきて詰まったので書きました 。
その時は、下記のことが原因でリソースを取得できませんでした。
- サーバが
OPTIONS メソッド
を許可していなかった。 - リクエスト内容が
プリフライトリクエスト
を送信する条件を満たしていた。
みなさんも上記のようなときは、リクエスト内容やサーバの設定を確認してみてください。
参考
オリジン間リソース共有 (CORS) - HTTP | MDN
http://takapi86.hatenablog.com/entry/2017/09/18/172846