iT邦幫忙

2021 iThome 鐵人賽

DAY 6
0
Modern Web

不只是串串API,新手前端30天系列 第 6

DAY06 - API串接常見問題 - CORS - 解決CORS問題篇

前面,我們知道為什麼會看到CORS的錯誤訊息,也簡單的知道如果我們要在瀏覽器上跨來源存取API資料,就要通行證,新的http header,那這個通行證是什麼呢?今天就讓我們看一下吧

其實要解決CORS的問題,正宗的解法,就是要請後端設置CORS header

後端要怎麼設定哪些通行證呢?根據不同的需求,需要不同的通行證,有哪些通行證呢?

[正規方法] 請後端設置放行通行證 - http header

  • Access-Control-Allow-Origin:
    允許哪些網址可以跨網域使用此資源。 Eg. http://web.com.tw 或 給 * 允許所有來源可以跨域存取。
    ex. Access-Control-Allow-Origin: *
  • Access-Control-Allow-Credentials
    當前端API request需要帶cookies時,就須此屬性並將值設定為true,預設為false。另外,當此屬性設定為true時,Access-Control-Allow-Origin不能設定為*
    ex. Access-Control-Allow-Credentials:true
  • Access-Control-Allow-Methods:支援的Method有哪些(POST, GET, PUT, DELETE...)
    ex. Access-Control-Allow-Methods:POST, GET, PUT, DELETE
  • Access-Control-Allow-Headers
    允許哪些自定義的header
    ex. Access-Control-Allow-Headers: Authorization
  • Access-Control-Max-Age
    preflight request的資訊(包含Access-Control-Allow-MethodsAccess-Control-Allow-Headers 可以cache的秒數上限(單位:秒)。每一個瀏覽器會有預設的最大值 ,當 Access-Control-Max-Age 大於預設值時,會優先採用預設值。
    ex. Access-Control-Max-Age: 600 // Cache results of a preflight request for 10 minutes
  • Access-Control-Expose-Headers:表示API Server允許瀏覽器存取response header的白名單
    ex. Access-Control-Expose-Headers:X-My-Custom-Header -> 表示瀏覽器能夠存取response當中的 X-My-Custom-Header

[暫時方法] 使用CORS Proxy(跨域代理伺服器): 以第三方CORS Proxy - cors-anywhere為例

如果後端暫時找找不到人,前端可以用怎麼樣的方式暫時自救一下呢...
前面有說到,跨網域的限制是因為瀏覽器所以才會有的,
如果先透過非瀏覽器的方式取的API response,加上該給的header通行證,再傳回給前端,那是不是就沒問題了!而這種方式,就叫CORS Proxy。

原理架構如下:
Browser ↔ CORS Proxy Server ↔ API
透過CORS Proxy Server的模式繞過 瀏覽器的跨域限制, 進而實踐存取API Server的response

CORS Proxy可以自己架設,也可以使用第三方的CORS Proxy,其中很方便使用的就是cors-anywhere 了~

cors-anywhere的使用方式非常簡單,直接把 https://cors-anywhere.herokuapp.com/ 加在你的API URL前就可以了,如以下的範例:

const corsURL = 'https://cors-anywhere.herokuapp.com/'; // use cors-anywhere to fetch api data
const apiURL = 'https://www.api.com/device'; // origin api url
// api call
axios
.get(`${corsURL}${apiURL}`, {

})
.then((response) => (console.log(response))) // 把结果集传到info这个数组
.catch((error) => {
    console.warn(error);
});

cros-anywhere實際加上後可能會遇到的問題

可能會在console看到這個錯誤


可以切到network後,發現API顯示的錯誤是403


再切換到response會看到以下的訊息 "See /corsdemo for more info"


在字上點選右鍵,open in new tab

會帶你到cros-anywhere的聲明頁面,點選按鈕“request temporaty access to the demo server”

按完後底下會出現一行文字,告訴你現在已經可以暫時使用這個server了


回到原本存取API的頁面,再按一下重新整理,應該就可以順利看到囉

*不過cros-anywhere在太多的request下,也會限制使用次數,所以這只是一個暫時前端開發方式,還是要請後端大大把API的header加好,通行證權限開好開滿才是正途R~~

看到這裡有發現其實這個是後端需要設定好的項目嗎?但前端為什麼要知道?
這是因為這是前端在使用時才會遇到問題(瀏覽器的限制)。因此前端必須知道這個問題的原因之後,自己遇到這個問題的時候也才能很確定該怎麼處理喔(像我一開始遇到的時候因為搞不清楚狀況很想自己解決,搞了好久QQ),知道原理後也才能與後端討論或建議應該怎麼加才能正常使用喔~~


參考資料

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age


上一篇
DAY05 - API串接常見問題 - CORS - 概念篇 (2)
下一篇
DAY07 - API架構分享
系列文
不只是串串API,新手前端30天30

尚未有邦友留言

立即登入留言