一文带你了解 HTTP 黑科技( 八 )

上面的事例创建了一个 XML 请求体用来和 POST 请求一起发送 。此外 , 设置了非标准请求头 X-PINGOTHER  , 这个标头不是 HTTP/1.1 的一部分 , 但通常对 Web 程序很有用 。由于请求的 Content-Type 使用 application/xml , 并且设置了自定义标头 , 因此该请求被预检 。如下图所示

一文带你了解 HTTP 黑科技

文章插图
 
如下所述 , 实际的 POST 请求不包含 Access-Control-Request- * 标头;只有 OPTIONS 请求才需要它们 。
下面我们来看一下完整的客户端/服务器交互 , 首先是预检请求/响应
OPTIONS /resources/post-here/ HTTP/1.1Host: bar.otherUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateConnection: keep-aliveOrigin: http://foo.exampleAccess-Control-Request-Method: POSTAccess-Control-Request-Headers: X-PINGOTHER, Content-TypeHTTP/1.1 204 No ContentDate: Mon, 01 Dec 2008 01:15:39 GMTServer: Apache/2Access-Control-Allow-Origin: https://foo.exampleAccess-Control-Allow-Methods: POST, GET, OPTIONSAccess-Control-Allow-Headers: X-PINGOTHER, Content-TypeAccess-Control-Max-Age: 86400Vary: Accept-Encoding, OriginKeep-Alive: timeout=2, max=100Connection: Keep-Alive上面的1 -11 行代表预检请求 , 预检请求使用 OPYIIONS 方法 , 浏览器根据上面的 JavaScript 代码段所使用的请求参数确定是否需要发送此请求 , 以便服务器可以响应是否可以使用实际请求参数发送请求 。OPTIONS 是一种 HTTP / 1.1方法 , 用于确定来自服务器的更多信息 , 并且是一种安全的方法 , 这意味着它不能用于更改资源 。请注意 , 与 OPTIONS 请求一起 , 还发送了另外两个请求标头(分别是第9行和第10行)
Access-Control-Request-Method: POSTAccess-Control-Request-Headers: X-PINGOTHER, Content-TypeAccess-Control-Request-Method 标头作为预检请求的一部分通知服务器 , 当发送实际请求时 , 将使用POST 请求方法发送该请求 。
Access-Control-Request-Headers 标头通知服务器 , 当发送请求时 , 它将与X-PINGOTHER 和 Content-Type 自定义标头一起发送 。服务器可以确定这种情况下是否接受请求 。
下面的 1 - 11行是服务器发回的响应 , 表示POST 请求和 X-PINGOTHER 是可以接受的 , 我们着重看一下下面这几行
Access-Control-Allow-Origin: http://foo.exampleAccess-Control-Allow-Methods: POST, GET, OPTIONSAccess-Control-Allow-Headers: X-PINGOTHER, Content-TypeAccess-Control-Max-Age: 86400服务器完成响应表明源 http://foo.example 是可以接受的 URL , 能够允许 POST、GET、OPTIONS 进行请求 , 允许自定义标头 X-PINGOTHER, Content-Type 。最后 , Access-Control-Max-Age 以秒为单位给出一个值 , 这个值表示对预检请求的响应可以缓存多长时间 , 在此期间内无需发送其他预检请求 。
完成预检请求后 , 将发送实际请求:
POST /resources/post-here/ HTTP/1.1Host: bar.otherUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: en-us,en;q=0.5Accept-Encoding: gzip,deflateConnection: keep-aliveX-PINGOTHER: pingpongContent-Type: text/xml; charset=UTF-8Referer: https://foo.example/examples/preflightInvocation.htmlContent-Length: 55Origin: https://foo.examplePragma: no-cacheCache-Control: no-cache<person><name>Arun</name></person>HTTP/1.1 200 OKDate: Mon, 01 Dec 2008 01:15:40 GMTServer: Apache/2Access-Control-Allow-Origin: https://foo.exampleVary: Accept-Encoding, OriginContent-Encoding: gzipContent-Length: 235Keep-Alive: timeout=2, max=99Connection: Keep-AliveContent-Type: text/plain[Some GZIP'd payload]正式响应中很多标头我们在之前的文章已经探讨过了 , 本篇不再做详细的介绍 , 读者可以参考你还在为 HTTP 的这些概念头疼吗? 查阅
带凭证的请求XMLHttpRequest 或 Fetch 和 CORS 最有趣的功能就是能够发出知道 HTTP Cookie 和 HTTP 身份验证的 凭证 请求 。默认情况下 , 在跨站点 XMLHttpRequest 或 Fetch 调用中 , 浏览器将不发送凭据 。调用 XMLHttpRequest对象或 Request 构造函数时必须设置一个特定的标志 。
在下面这个例子中 , 最初从 http://foo.example 加载的内容对设置了 Cookies 的 http://bar.other 上的资源进行了简单的 GET 请求 ,  foo.example 上可能的代码如下


推荐阅读