2019年鐵人賽
、 web-server
在接別人API時會出現這個錯誤回應,是因為瀏覽器基於同源政策的規範,有一些對請求的限制。
同源政策出發點是為了防止CSRF誇站請求偽造的惡意攻擊,所以發出請求的來源要遵守以下三點
同源政策限制了程式碼和不同 domain 的資料傳送,不同源會被擋下來
那怎麼串接成功?
幾乎不太可能跟要接的 API 在同一 domain 下,所以為了讓不同源之間可以傳輸資料,又有另外一個規範叫 CORS。
CORS規範說,如果想開啟跨來源 HTTP 請求的話,Server 必須在 Response 的 Header 裡面加上 Access-Control-Allow-Origin
的設定。
錯誤回應裡有提到
設定成功在Devtools會看到Access-Control-Allow-Origin: *
表示允許任何來源
另外,也可以定義接受哪些請求的 Header 或 Method Access-Control-Allow-Headers
、Access-Control-Allow-Methods
。
成功接上API後,會發現我們只有發送一個 POST 請求,但怎麼先傳了 OPTIONS ?
CORS把請求分為兩種,簡單請求跟預檢(preflight)請求。
簡單請求
要滿足所有判斷條件,最容易分辨的是沒有自定義 Header,而且又是 GET 。
//範例
GET https://api.users.com/user/1 HTTP/1.1
預檢(preflight)請求
//範例
var xhr = new XMLHttpRequest()
xhr.open("POST","http://api") //用post方法發請求到api網址
xhr.addEventListener('readystatechange', function(e) {
if (e.target.readyState === 4 && e.target.status === 200) {
//....
} else if (e.target.readyState === 4) {
//....
}
});
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
因為不是簡單請求,所以瀏覽器會先送出 HTTP 的 OPTIONS 方法,確認 Server 的 Response 是否有 Access- Control-Allow-Origin
,確認有之後才會把我們的請求送出。
How CORS works
圖片來源:wikipedia
http://test.you.com/dir/page.html
表格都是和以上這一個URL比較
URL | 比較結果 | 原因 |
---|---|---|
http://test.you.com/watch/page.html | 同源 | |
http://test.you.com:87/dir/page.html | 不同源 | 不同 port |
https://test.you.com/dir/page.html | 不同源 | 不同協議 |
http://fined.you.com/dir/page.html | 不同源 | 不同 domain |