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 這一系列請求首部字段無須手動設置,發送跨域請求時,已被自動設置好了

參考文檔

相關文章
相關標籤/搜索