Fetch&CORS的简单实验

概念

CORS, Cross-origin resource sharingjson

跨域资源共享标准新增了一组 HTTP 首部字段,容许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生反作用的 HTTP 请求方法(特别是 GET 之外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否容许该跨域请求。服务器确认容许以后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也能够通知客户端,是否须要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

Fetch跨域

Fetch API 提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的部分,例如请求和响应。它还提供了一个全局 fetch() 方法,该方法提供了一种简单,合乎逻辑的方式来跨网络异步获取资源。

均摘自中文MDN浏览器

实验

实验环境搭建

服务端

在本地搭建一个服务,返回一个 json ,代码以下缓存

const http = require('http')

http.createServer((req, res) => {
  res.writeHead(200, {
    'Content-Type': 'application/json'
  })
  res.end(JSON.stringify({
    author: 'nbb3210'
  }))
}).listen(3210)

用浏览器打开http://localhost:3210,观察到返回值服务器

clipboard.png

而后再随便找一个仍是 http 的网站,例如华为网络

clipboard.png

嗯,意料之中的情形。app

简单请求(Simple requests)

修改服务端代码,添加 Access-Control-Allow-Origin异步

res.writeHead(200, {
    'Access-Control-Allow-Origin': '*',
    'Content-Type': 'application/json'
  })

再此发送请求fetch

clipboard.png

嗯,意料之中的情形。这便完成了一次跨域请求。专业的说,完成了一次简单请求。何为简单请求?网站

  • 使用下列方法之一:

    • GET
    • HEAD
    • POST
  • 不能设置除如下集合以外的首部字段:

    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (须要额外的限制)
  • Content-Type 的值近限与下列三者之一

    • text/plain
    • Multipart/form-data
    • Application/x-www-form-urlencoded

因此若是我使用了其余的方法或添加其余的首部字段又如何?

clipboard.png

哈?还挺严格,再来看看Network

clipboard.png

怎么无故出来个 OPTIONS 请求?

预检请求(Preflighted requests)

非简单请求就是预检请求了,它会首先使用 OPTIONS 方法发起一个预检请求到服务器,以获取服务器是否容许该实际请求。注意了,浏览器本身根据请求是否为简单请求来发送预检请求,不是我们通常码农本身写的。

因此修改服务端代码,让它容许自定义头部 Access-Control-Allow-Headers, x-test

const http = require('http')

http.createServer((req, res) => {
  if (res.method === 'OPTIONS') {
    res.writeHead(200, {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Headers': 'x-test'
    })
    res.end()
  } else {
    res.writeHead(200, {
      'Access-Control-Allow-Origin': '*',
      'Content-Type': 'application/json'
    })
    res.end(JSON.stringify({
      author: 'nbb3210'
    }))
  }
}).listen(3210)

从新发送一次请求

clipboard.png

嗯,没毛病

若是是 DELETE 等其它方法,就用 Access-Control-Allow-Methods

而 Access-Control-Max-Age 则指定了预检请求的结果可以被缓存多久

小结

Access-Control-Allow-Origin, Access-Control-Expose-Headers, Access-Control-Max-Age, Access-Control-Allow-Credentials, Access-Control-Allow-Methods, Access-Control-Allow-Headers 这一系列的相应首部字段规定了哪些源站经过哪些方式有权限访问哪些资源

Origin, Access-Control-Request-Method, Access-Control-Request-Headers 这一系列请求首部字段无须手动设置,发送跨域请求时,已被自动设置好了

参考文档

相关文章
相关标签/搜索