當fetch遇到302狀態碼,會發生什麼?
昨天,我正在把SSO整合到專案中。起初,在使用者未登入的時候,後端會返回302狀態碼,瀏覽器根據響應頭的設定跳轉到SSO頁面。重定向到正確的登入頁面來讓使用者登入,這似乎並沒有什麼問題。然而,當我需要用fetch從後端請求一些資料的時候,請求會失敗並且重定向並沒有發生。
所以,第一個問題是:
當fetch遇到302狀態碼,會發生什麼?
我僅僅用koa寫了一個小例子來測試fetch的302狀態碼。在後端,當介面 /bait 接受一個請求,會設定一個302狀態碼並且在響應頭中增加重定向的位置資訊:/gotcha。程式碼如下:
const app = new Koa(); const bait = ctx => { ctx.response.redirect('/gotcha'); }; const gotcha = ctx => { ctx.response.type = 'json'; ctx.response.body = { data: 'Gotcha!' }; }; app.use(route.get('/gotcha', gotcha)); app.use(route.get('/bait', bait));
現在,如果我向 /bait 發起一個請求,/gotcha 會返回響應資訊:
檢查網路請求發現,第一個請求 /bait 返回了302,然後發起了第二個請求 /gotcha:
所以302是透明的:我們發起請求,後端返回302,然後瀏覽器會幫助重定向到新的介面,並返回最終的資料。這裡的“透明”指,我們可以檢視被重定向的介面以及最終返回資料的介面。
這些程式碼可以在我的 github 上檢視,你可以克隆這個倉庫並執行這些程式碼。
下個問題是:
處理這些需要認證的介面最好的方法是什麼?
雖然fetch不能攔截302狀態碼,但是它可以處理401和403狀態碼。所以可以讓介面返回401,響應如下:
fetch('http://www.somecompany.com/someapi').then(response => { if (response.ok) { // process the data } else if (response.status == 401) { // something bad happened... // do something like throwing an Error, or making a jump } else { // some other status like 400, 403, 500, etc // take proper actions } }).catch(error => { // do some clean-up job });
在大多數情況下,fetch取得的資訊會很多,不可能每個人都會考慮這些情況,因此,最好的辦法是封裝一個公共的方法,把回撥函式作為引數,來處理不同的情況。
總結
針對兩個問題,總結出兩點內容:
- fetch不能攔截302,瀏覽器會自動從302響應的頭資訊的重定向地址中取到資料。
- 針對認證的情況,後端可以返回401狀態碼,讓前端去檢查返回的狀態碼並據此執行相應操作。