UNPKG

@ithinkdt/core

Version:

iThinkDT Core

100 lines (90 loc) 2.94 kB
import { watch } from 'vue' import { HttpError } from '@ithinkdt/common' import { Route } from './router' export function jwt( router, getToken, setToken, { headerField, cookieField, cookieDomain, cookiePath = '/', tokenParser, tokenFormatter, unauthCodes, sameSite = 'Lax', }, ) { let _token, resolve const setted = new Promise((_resolve) => (resolve = _resolve)) const interceptor = async (req, next) => { if (_token) { req.headers.set(headerField, tokenFormatter(_token)) } else if (req.url.includes('/cli/') || req.url.includes('/cer/')) { await setted } try { return await next({ ...req, credentials: 'omit', }) } catch (error) { if ( error instanceof HttpError && error.code && unauthCodes.includes(error.code) && ![Route.NOT_FOUND, Route.LOGOUT, Route.LOGIN].includes(router.currentRoute.value.name) ) { console.debug('[auth] token expired') setToken() } throw error } } interceptor.setCookieByToken = (token) => { if (cookieField) { // eslint-disable-next-line unicorn/no-document-cookie document.cookie = `${cookieField}=${_token ? encodeURIComponent(tokenFormatter(token)) : ''}; ${ cookieDomain ? `domain=${cookieDomain}; ` : '' }path=${cookiePath}; ${sameSite}` } } const readPathCookie = (path, field) => { try { const url = location.href.slice(location.origin.length) // eslint-disable-next-line unicorn/no-null history.replaceState(null, '', path) const reg = new RegExp(`(^| )${field}=([^;]*)(;|$)`) const v = reg.exec(document.cookie)?.[2] // eslint-disable-next-line unicorn/no-null history.replaceState(null, '', url) return v } catch { return '' } } interceptor.getTokenFromCookie = () => { const str = readPathCookie(cookiePath, cookieField) return str && tokenParser(decodeURIComponent(str)) } const str = interceptor.getTokenFromCookie() interceptor._init = () => { setted.then((token) => { if (str && str !== token) { console.debug('[jwt]: 从 cookie 读取到的 token 不同于当前值,将替换') setToken(str) } }) watch( getToken, (token) => { _token = token interceptor.setCookieByToken(token) token && resolve(token) }, { immediate: true, flush: 'sync' }, ) } return interceptor }