更新於 2024/05/13閱讀時間約 5 分鐘

用 axios interceptor 實作 refresh token

動機

最近筆者在專案中串接 Spotify 提供的 Web API,利用官方推薦的 PKCE flow 來做使用者驗證。在該驗證流程中,每次向 Spotify 請求 token 時,都會拿到一組 access token 和 refresh token,然後在 access token 過期時,程式就需要透過 refresh token 向 Spotify 的 API 再請求新的一組 token。


思路

在 概念驗證 (proof of concept,POC) 階段,筆者僅串接 Get New Releases API,因此首頁載入後會經過以下流程:

  • 重新導向 Spotify 頁面,使用筆者的 client id 授權,拿到 access token
  • 利用上一步驟拿到的 access token 去呼叫 Get New Releases API

從上面的流程不難想像,如果沒有對 request 或 response 做任何管控,可能會有以下問題:

  • 每次頁面 reload 時,都會再要一次 access token,造成過多不必要的請求。
  • access token 過期時,打 Get New Releases API 會收到 401 Unauthorized 回應,導致程式中斷,UI上的資料會被清空。

因此筆者需要一種機制檢查 access token 是否過期,以及 Get New Release 在 token 過期後,需要刷新 token 並重新請求 New Release 資源。

雖然可以直接對 fetch API 的邏輯進行擴充,但看到 axios 有攔截器 (interceptor) 機制,可以對 request 和 response 過程做更精準的操控後,筆者決定使用 axios 來實作。


Axios 是什麼 ?

axios 是基於 XMLHttpRequest 和 Promise 的 http request 套件


Axios 是一個基於 XMLHttpRequest 和 Promise,用來處理 http 請求的套件,相較於 fetch API,它具有以下亮點,因此廣受網頁開發者的喜愛:

  • 可以在瀏覽器 和 Node.js 裡運作。
    Node.js 直到最近的 v22.0 版才支援 fetch API,在此之前,若要發送請求,多半會使用它的 http 模組或 node-fetch 套件,而 axios 在 Node 使用時,底層便是使用 Node 的 http 模組。
  • 彈性大的 API。
    在 request 的 options 裡可以做多種配置,例如可用 transformRequesttransformResponse 將送出或取回的資料轉型,還可設定 api endpoint 的 baseURL。
  • Axios instance 讓 request 的配置可以被複用。
const instance = axios.create({
baseURL: "https://some-domain.com/api/",
timeout: 1000,
headers: { "X-Custom-Header": "foobar" },
});

instance 這個物件就可以替代原本用來發 request 的 axios 物件,並帶有以上這些預設的 config。

Axios Interceptor 是什麼?

axios instance 可以加入 interceptor,對 request 和 response 添加額外的行為。

axios.instance 提供 interceptor.use() 方法,可以在 request 發出之前、response 的 Promise resolve 之前做一些額外的操作,筆者便利用它來做 token 時效的檢查以及 token 失效後刷新 token 的功能。

實作

建立 axios instance

const instance = axios.create({
baseURL: BASE_ENDPOINT,
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
});


添加 request interceptor,在每次請求 token 時,用 localStorage 裡面存的 timestamp 檢查 access token 是否過期,若否則不請求 token,若是則用 localStorage 裡的 refresh token 重新請求 access token。

request interceptor 檢查 access token 的有效期限

添加 response interceptor,在每次請求 New Releases 得到 response 後,檢查是否有 401 錯誤,若是則重新請求 access token,並重新請求 New Releases

response interceptor 檢查 response 的 status code,判斷是否重新發送請求


總結

後來筆者在網路上發現,其實用一個 wrapper function 把 fetch API 包裝起來,也可以做到攔截 request/response 的效果,但我認為 axios 攔截器的好處在於,它將請求前後的邏輯和請求本身整合在一起,讓請求的邏輯變得更完整且可復用,若不介意需要額外安裝套件的話,axios 攔截器不失為一個好選擇。



參考資源:


分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.