跨來源資源共用(Cross-Origin Resource Sharing (CORS))是一種使用額外 HTTP 標頭令目前瀏覽網站的使用者代理 (en-US)取得存取其他來源(網域)伺服器特定資源權限的機制。當使用者代理請求一個不是目前文件來源 — — 例如來自於不同網域(domain)、通訊協定(protocol)或通訊埠(port)的資源時,會建立一個跨來源 HTTP 請求(cross-origin HTTP request)。
通常遇到跨網域問題,大多不是前端可以解決的,當你遇到以後,能明確知道問題在哪時,再與後端夥伴溝通,可以比較快速解決問題,以下為有可能遇到的幾種跨網域情況。
情況一
If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
最常遇到的情況,請後端增加以下header,通常就可以解決:
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin
的值可以帶 *
,代表所有網域都可以通過,任何 origin 都合法,也可以帶 origin 像是 http://catcat.tw
,代表只有這個 origin 是合法的。
情況二
Access to fetch at ‘http://localhost:3000/' from origin ‘null’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check
到devtools中 network 去查看 request 的狀況,發現除了原本預期的 POST 以外,還多了一個 OPTIONS 的 request
簡單請求:基本上只要 method 是 GET、POST 或是 HEAD 然後不要帶自訂的 header,Content-Type 也不要超出:application/x-www-form-urlencoded
、multipart/form-data
或是 text/plain
這三種。
所以如果Content-Type為 application/json
就不符合簡單請求的定義了。
非簡單請求會多送出一個東西,叫做 preflight request。這個請求就是在devtools中 network 看到的那個 OPTIONS 的 request,針對這個 request,瀏覽器會幫忙帶上兩個 header:
- Access-Control-Request-Headers
- Access-Control-Request-Method
請求過程:
- 我們要送出 POST 的 request 到 http://localhost:3000/
- 瀏覽器發現是非簡單請求,因此先發出一個 preflight request
- 檢查 response,preflight 通過
- 送出 POST 的 request 到 http://localhost:3000/
所以如果 preflight 沒有過,第一個步驟的 request 是不會被送出的,所以錯誤的關鍵字中有preflight就可以優先考慮是否為非簡單請求所造成的cors問題。
解決非簡單請求的方法為,請後端增加以下header:
Access-Control-Allow-Headers: 'content-type'