A brief discussion about preflight requests

一个新手
Release: 2017-09-18 10:24:31
Original
4556 people have browsed it


A brief discussion about preflight requests

Background

I don’t know if you have noticed that sometimes when we call the background interface, we will request it twice. As shown below

A brief discussion about preflight requests

#In fact, the first time sent is the preflight request (preflight request), so this article will talk about why and when to send the preflight request A preflight request will be sent, and what is done with the preflight request

1. Why send a preflight request

We all know the same-origin policy of the browser, which is for security reasons. The server will restrict cross-domain HTTP requests initiated from scripts, such as XMLHttpRequest and Fetch, which follow the same-origin policy.
There are generally two ways for browsers to restrict cross-domain requests:
1. The browser restricts the initiation of cross-domain requests
2. Cross-domain requests can be initiated normally, but the returned results are intercepted by the browser

Generally, browsers restrict cross-domain requests in the second way, which means that the request has reached the server and may have operated on the data in the database, but the returned result was intercepted by the browser, then we The return result cannot be obtained. This is a failed request, but it may have an impact on the data in the database.

In order to prevent this from happening, the specification requires that for this HTTP request method that may have side effects on server data, the browser must first initiate a preflight request using the OPTIONS method. Thus, it is known whether the server allows the cross-domain request: if allowed, the real request with data is sent; if not, the real request with data is prevented from being sent.

2. When to send a preflight request

HTTP requests include: simple requests and requests requiring preflight

1. Simple requests

Simple requests CORS preflight request will not be triggered, "Jane belongs to
The term "single request" does not belong to the Fetch (where CORS is defined) specification.
If all of the following conditions are met, the request can be considered a "simple request":
- Use one of the following methods:
- GET
- HEAD
- POST
- Content-Type: (Only when the Content-Type value of the POST method is equal to one of the following is it considered a simple requirement)
                                                                                                                                                                                                                                                                                                                                                                                    - application/x-www-form-urlencoded

Note: WebKit Nightly and Safari Technology Preview are Accept , Accept-Language

, and Content-Language
add additional restrictions on the values ​​of header fields. If the values ​​of these header fields are "non-standard", WebKit/Safari will not treat these requests as "simple requests". WebKit/Safari does not list which values ​​are "non-standard" in the documentation, but we can find a discussion here: 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. Other browsers do not support these additional restrictions because they are not part of the specification.

2. Requests requiring preflight

"Requests requiring preflight" requires that you must first use the
OPTIONS

method to initiate a preflight request to the service area. to know whether the server allows the actual request. The use of "preflight request" can avoid cross-domain requests from having unexpected effects on user data on the server.
When the request meets any of the following conditions, the preflight request should be sent first:
- Used any of the following HTTP methods:

- PUT

-

DELETE

- CONNECT
- OPTIONS
- TRACE
- PATCH
- Artificially set header fields other than the set of header fields that are safe for CORS. The collection is: - Accept
- Accept-Language

- Content-Language
- Content-Type
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- The value of Content-Type does not belong to one of the following:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain

如下是一个需要执行预检请求的HTTP请求:

var invocation = new XMLHttpRequest();
var url = ' 
var body = &#39;<?xml version="1.0"?><person><name>Arun</name></person>&#39;;function callOtherDomain(){
  if(invocation)
    {
      invocation.open(&#39;POST&#39;, url, true);
      invocation.setRequestHeader(&#39;X-PRODUCT&#39;, &#39;H5&#39;);
      invocation.setRequestHeader(&#39;Content-Type&#39;, &#39;application/xml&#39;);
      invocation.onreadystatechange = handler;
      invocation.send(body); 
    }
}
......
Copy after login

上面的代码使用POST请求发送一个XML文档,该请求包含了一个自定义的首部字段(X-PRODUCT:H5)。另外,该请求的Content-Typeapplication/xml。因此,该请求需要首先发起“预检请求”。
A brief discussion about preflight requests

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
Copy after login

从上面的报文中可以看到,第1~12行发送了一个使用OPTIONS方法的预检请求。 OPTIONS是HTTP/1.1协议中定义的方法,用以从服务器获取更多信息。该方法不会对服务器资源产生影响。遇见请求中同时携带了下面两个首部字段:

Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PRODUCT
Copy after login

首部字段 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
Copy after login

首部字段 Access-Control-Allow-Methods 表明服务器允许客户端使用 POST,GET 和 OPTIONS 方法发起请求。

首部字段Access-Control-Allow-Headers 表明服务器允许请求中携带字段X-PINGOTHERContent-Type。与 Access-Control-Allow-Methods一样,Access-Control-Allow-Headers的值为逗号分割的列表。

最后,首部字段

Access-Control-Max-Age 表明该响应的有效时间为 86400 秒,也就是 24 小时。在有效时间内,浏览器无须为同一请求再次发起预检请求。请注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效。

预检请求完成之后,发送实际请求:

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&#39;d payload]
Copy after login

The above is the detailed content of A brief discussion about preflight requests. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!