お気づきかどうかわかりませんが、バックグラウンドインターフェースを呼び出すときに、以下に示すように2回リクエストを行うことがあります
実際、最初に送信するのはプリフライト リクエスト(プリフライト リクエスト)について説明します。次に、この記事では、プリフライト リクエストが送信される理由、プリフライト リクエストが送信されるタイミング、およびプリフライト リクエストの機能について説明します
ブラウザの同一オリジン ポリシーは、セキュリティ上の理由から、XMLHttpRequest および Fetch はすべて同一オリジン ポリシーに従うことを制限します。
ブラウザがクロスドメイン リクエストを制限するには、通常 2 つの方法があります:
1. ブラウザはクロスドメイン リクエストの開始を制限します
2. クロスドメイン リクエストは通常通り開始できますが、返された結果はブラウザによってインターセプトされます
一般に、ブラウザーは 2 番目のメソッドを使用して、クロスドメイン リクエストを制限します。つまり、リクエストはサーバーに到達し、データベース内のデータを操作した可能性がありますが、返された結果はブラウザーによってインターセプトされました。返された結果を取得できません。これは 1 回限りのリクエストですが、データベース内のデータに影響を与えた可能性があります。
これが起こらないようにするために、仕様では、サーバー データに副作用をもたらす可能性があるこの HTTP リクエスト メソッドについて、ブラウザはまず OPTIONS
メソッドを使用してプリフライト リクエストを開始し、サーバーがクロスアクセスを許可するかどうかを学習する必要があります。ドメインリクエスト: 許可されている場合、データを含む実際のリクエストは送信されます。許可されていない場合、データを含む実際のリクエストは送信されません。
HTTP リクエストには次のものが含まれます: 単純なリクエストとプリフライトを必要とするリクエスト
単純なリクエストは CORS プリフライト リクエストをトリガーしません。
「単一リクエスト」という用語は、フェッチ仕様 (CORS が定義されている) には属しません。
以下の条件がすべて満たされる場合、リクエストは「単純なリクエスト」とみなされます。
- 次のいずれかの方法を使用します:
-
- GET
- HEAD
- POST
: (POST メソッドの Content-Type 値が次のいずれかに等しい場合のみ、単純な要件とみなされます)
-
-
WebKit NightlyとSafari Technology Previewは、AcceptContent-Type
、Accept-Language
、およびコンテンツランゲージヘッダーフィールドの値に追加の制限を追加しました。これらのヘッダー フィールドの値が「非標準」である場合、WebKit/Safari はこれらのリクエストを「単純なリクエスト」として扱いません。 WebKit/Safari のドキュメントにはどの値が「非標準」であるかが記載されていませんが、ここで議論を見つけることができます: 非標準の CORS セーフリスト要求ヘッダーの Accept、Accept-Language、および Content-Language にはプリフライトが必要です。単純な CORS の Accept、Accept-Language、および Content-Language リクエスト ヘッダーでカンマを許可し、単純な CORS リクエストの制限された Accept ヘッダーについてはブラックリスト モデルに切り替えます。他のブラウザでは、これらの追加の制限は仕様の一部ではないため、サポートされていません。 text/plain
2. プリフライトが必要なリクエスト multipart/form-data
「プリフライトが必要なリクエスト」では、サーバーが実際のリクエストを許可するかどうかを知るために、まず application/x-www-form-urlencoded
注意: WebKit Nightly 和 Safari Technology Preview 为Accept
, Accept-Language
, 和 Content-Language
首部字段的值添加了额外的限制。如果这些首部字段的值是“非标准”的,WebKit/Safari 就不会将这些请求视为“简单请求”。WebKit/Safari 并没有在文档中列出哪些值是“非标准”的,不过我们可以在这里找到相关讨论:Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language, Allow commas in Accept, Accept-Language, and Content-Language request headers for simple CORS, and Switch to a blacklist model for restricted Accept headers in simple CORS requests。其它浏览器并不支持这些额外的限制,因为它们不属于规范的一部分。
“需预检的请求”要求必须首先使用OPTIONS
メソッドを使用してサービス エリアへのプリフライト リクエストを開始する必要があります。 「プリフライト リクエスト」を使用すると、クロスドメイン リクエストがサーバー上のユーザー データに予期せぬ影響を与えることを回避できます。
リクエストが次の条件のいずれかを満たしている場合、最初にプリフライトリクエストを送信する必要があります:
- 次の HTTP メソッドのいずれかを使用します:
- PUT
- DELETE
- CONNECT
- OPTIONS
- TRACE
- PATCH
- CORS にとって安全なヘッダー フィールドのセット以外のヘッダー フィールドを人為的に設定します。コレクションは次のとおりです:
- 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
以下は、プリフライト リクエストを実行する必要がある HTTP リクエストです:
var invocation = new XMLHttpRequest(); var url = ' var body = '<?xml version="1.0"?><person><name>Arun</name></person>';function callOtherDomain(){ if(invocation) { invocation.open('POST', url, true); invocation.setRequestHeader('X-PRODUCT', 'H5'); invocation.setRequestHeader('Content-Type', 'application/xml'); invocation.onreadystatechange = handler; invocation.send(body); } } ......
上記のコードは、POST リクエストを使用して、カスタム ヘッダー フィールド (X-PRODUCT:H5) を含む XML ドキュメントを送信します。さらに、リクエストの Content-Type
は application/xml
です。したがって、リクエストは最初に「プリフライトリクエスト」を開始する必要があります。 Content-Type
为application/xml
。因此,该请求需要首先发起“预检请求”。
1. OPTIONS /resources/post-here/ 2. HTTP/1.13. Host: bar.other4. User-Agent: Mozilla/5.0 (Macintosh; U; 5.Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre6. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.87. Accept-Language: en-us,en;q=0.58. Accept-Encoding: gzip,deflate9. Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.710. Connection: keep-alive11. Origin: http://foo.example12. Access-Control-Request-Method: POST13. Access-Control-Request-Headers: X-PINGOTHER, Content-Type14. HTTP/1.1 200 OK15. Date: Mon, 01 Dec 2008 01:15:39 GMT16. Server: Apache/2.0.61 (Unix)17. Access-Control-Allow-Origin: http://foo.example18. Access-Control-Allow-Methods: POST, GET, OPTIONS19. Access-Control-Allow-Headers: X-PINGOTHER, Content-Type20. Access-Control-Max-Age: 8640021. Vary: Accept-Encoding, Origin22. Content-Encoding: gzip23. Content-Length: 024. Keep-Alive: timeout=2, max=10025. Connection: Keep-Alive26. Content-Type: text/plain
从上面的报文中可以看到,第1~12行发送了一个使用OPTIONS
方法的预检请求。 OPTIONS
是HTTP/1.1协议中定义的方法,用以从服务器获取更多信息。该方法不会对服务器资源产生影响。遇见请求中同时携带了下面两个首部字段:
Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PRODUCT
首部字段 Access-Control-Request-Method 告知服务器,实际请求将使用 POST 方法。首部字段 Access-Control-Request-Headers 告知服务器,实际请求将携带两个自定义请求首部字段:X-PINGOTHER 与 Content-Type。服务器据此决定,该实际请求是否被允许。
第14~26行 为预检请求的响应,表明服务器将坚守后续的实际请求。重点看第17~20行:
Access-Control-Allow-Origin: http://foo.exampleAccess-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-TypeAccess-Control-Max-Age: 86400
首部字段 Access-Control-Allow-Methods
表明服务器允许客户端使用 POST,GET 和 OPTIONS 方法发起请求。
首部字段Access-Control-Allow-Headers
表明服务器允许请求中携带字段X-PINGOTHER
与Content-Type
。与 Access-Control-Allow-Methods
一样,Access-Control-Allow-Headers
的值为逗号分割的列表。
最后,首部字段
Access-Control-Max-Age
POST /resources/post-here/ HTTP/1.1Host: bar.otherUser-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3preAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7Connection: keep-aliveX-PINGOTHER: pingpongContent-Type: text/xml; charset=UTF-8Referer: http://foo.example/examples/preflightInvocation.htmlContent-Length: 55Origin: http://foo.examplePragma: no-cacheCache-Control: no-cache<?xml version="1.0"?><person><name>Arun</name></person>HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:40 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://foo.example Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 235 Keep-Alive: timeout=2, max=99 Connection: Keep-Alive Content-Type: text/plain [Some GZIP'd payload]
OPTIONS
メソッドを使用してプリフライト リクエストを送信します。 OPTIONS
は、サーバーから詳細情報を取得するために HTTP/1.1 プロトコルで定義されたメソッドです。この方法はサーバーのリソースには影響しません。リクエストには、次の 2 つのヘッダー フィールドが同時に含まれています: rrreee
ヘッダー フィールド Access-Control-Request-Method は、実際のリクエストが POST メソッドを使用することをサーバーに伝えます。ヘッダー フィールド Access-Control-Request-Headers は、実際のリクエストに 2 つのカスタム リクエスト ヘッダー フィールド (X-PINGOTHER と Content-Type) が含まれることをサーバーに伝えます。サーバーはこれに基づいて、実際のリクエストが許可されるかどうかを決定します。 🎜🎜行 14 ~ 26 はプリフライト リクエストに対する応答で、サーバーが後続の実際のリクエストに固執することを示しています。 17 ~ 20 行目に注目してください: 🎜rrreee🎜 ヘッダー フィールドAccess-Control-Allow-Methods
は、サーバーがクライアントに POST、GET、および OPTIONS メソッドを使用してリクエストを開始することを許可していることを示します。 🎜🎜ヘッダー フィールド Access-Control-Allow-Headers
は、サーバーがフィールド X-PINGOTHER
と Content-Type
の伝送を許可することを示しますリクエストの中で。 Access-Control-Allow-Methods
と同様、Access-Control-Allow-Headers
の値はカンマ区切りのリストです。 🎜🎜最後に、ヘッダー フィールド 🎜🎜Access-Control-Max-Age
は、応答が 86400 秒、つまり 24 時間有効であることを示しています。有効期間内であれば、ブラウザは同じリクエストに対して再度プリフライト リクエストを開始する必要はありません。ブラウザ自体が最大有効時間を保持しているため、このヘッダー フィールドの値が最大有効時間を超えると有効になりません。 🎜🎜プリフライトリクエストが完了したら、実際のリクエストを送信します: 🎜rrreee以上がプリフライトリクエストに関する簡単な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。