CORS Simple Request

如果一个请求没有包含任何自定义请求头,而且它所使用 HTTP 动词是 GETHEADPOST 之一,那么它就是一个 Simple Request。

HTTP 的头信息不超出以下几种字段

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:使用 POST 作为请求的动词时,该请求的 Content-Type 需要是 application/x-www-form-urlencodedmultipart/form-datatext/plain 之一

Request

对于简单请求,浏览器直接发出 CORS 请求。具体来说,就是在头信息之中,增加一个 Origin 字段,用来说明本次请求来自哪个源(协议 + 域名 + 端口)

Example
GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

Response

服务器根据瀏覽器發送過來的在 origin 的值,决定是否同意这次请求。

如果Origin指定的域名在许可范围内

服务器返回的响应,会多出几个头信息字段,例子:

Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8

Access-Control-Allow-Origin 该字段是必须的。它的值要么是请求时 Origin 字段的值,要么是一个 *,表示接受任意域名的请求。

Access-Control-Allow-Credentials 该字段可选。默认情况下,Cookie 不包括在 CORS 请求之中。如果此值设为 true,即表示服务器明确许可,Cookie 可以包含在请求中,一起发给服务器。 注意这个值也只能设为 true(不能設爲 false),如果服务器不要浏览器发送 Cookie,删除该字段即可。

Access-Control-Expose-Headers 该字段可选。CORS 请求时,XMLHttpRequest 对象的 getResponseHeader() 方法只能拿到6个基本字段:Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma。如果想拿到其他字段,就必须在 Access-Control-Expose-Headers 里面指定。上面的例子指定,getResponseHeader('FooBar') 可以返回 FooBar 字段的值。

如果Origin指定的源,不在许可范围内

會只回傳 Access-Control-Allow-Origin,並且聲明所允許的域名

Access-Control-Allow-Origin: http://foo.example

浏览器發現域名不一致,會抛出一个错误,被 XMLHttpRequestonerror 回调函数捕获。

注意,这种错误无法通过状态码识别,因为 HTTP 回应的状态码有可能是200。