クロスオリジンリクエストは、ブラウザがリクエストがサーバーサイドの変更を引き起こす可能性があると思う場合にのみプリフライトされます。クロスオリジンのXMLHttpRequest
/ fetch
リクエストを行う場合、それは「シンプル」または「プリフライト」の 2 つのカテゴリに分類されます。
シンプルなリクエストは、CORS ポリシーを決定するために実際のリクエストに乗っかることが(慣習的に)安全なものです。REST/HTTP では、GET
リクエストのみ読み取ることや、PUT
が作成または置換を行うことを強制していません。これは単なる慣習です。
とにかく、リクエストがHEAD
/ GET
メソッドを持つ場合、ブラウザはこのリクエストを処理する際にオリジンサーバーが変更を行わないと仮定し、実際のリクエストのレスポンスでAccess-Control-Allow-Origin
ヘッダーを探します。つまり、CORS ポリシーは実際のリクエストから推測されます。これは安全な操作とされ、ラウンドトリップを 1 回節約できます。
ただし、PUT
/ DELETE
の場合、実際のリクエストを送信するとサーバーサイドの変更(データベース内の行の作成や削除など)がトリガーされる可能性があるため、ブラウザは実際のリクエストを行う前にこのリクエストを行うオリジンが許可されていることを確認する必要があります。実際のリクエストから CORS ポリシーを推測することはできません。なぜなら、それは CORS の目的を破壊してしまうからです - オリジンは明示的な許可なしにホストを変更できました。確かに、オリジンはホストのレスポンスを見ることはできないかもしれませんが、すでに損害は発生しています。これがブラウザが実際のリクエストを「プリフライト」する必要がある理由です。つまり、リクエストを送信する前にホストに対して別個の(OPTIONS
)リクエストを送信し、送信するリクエストが許可されているかどうかを明示的に尋ねます。この(プリフライト)OPTIONS
リクエストには、実際のリクエストのメソッドを示すAccess-Control-Request-Method
ヘッダーと、実際のリクエストが持つヘッダーをリストアップするAccess-Control-Request-Headers
ヘッダーが含まれます。ホストサーバーがAccess-Control-Request-Method
で指定されたメソッドとAccess-Control-Request-Headers
で指定されたヘッダーでリクエストを送信することを許可する場合にのみ、実際のリクエストが送信されます。
リクエストをプリフライトするかどうかの決定は、クライアント(ほとんどの場合、ウェブブラウザ)に完全に委ねられています。CORS 契約の範囲内で、追加のリクエストを送信しないように最善を尽くします。残念ながら、この決定は単にリクエストメソッドに基づいているわけではありません。いくつかのエッジケースによって、GET
リクエストでさえもプリフライトされる場合があります。
MDN の CORS ドキュメントは実際には素晴らしい読み物であり、リクエストがプリフライトされる必要があるかどうかについて詳しく説明しています。