插件系统
介绍
@cat-kit/http 的插件系统围绕 beforeRequest、afterRespond、onError 三个阶段工作。它既能做请求头注入、方法改写,也能做自动刷新 token 和错误恢复。
当前内置了两个插件:
TokenPluginMethodOverridePlugin
快速使用
ts
import { HTTPClient, TokenPlugin, MethodOverridePlugin } from '@cat-kit/http'
const http = new HTTPClient('/api', {
plugins: [
TokenPlugin({ getter: () => localStorage.getItem('token') }),
MethodOverridePlugin({ methods: ['DELETE'] })
]
})API参考
插件接口
ts
interface HTTPClientPlugin {
name: string
beforeRequest?(
context: { url: string; config: RequestConfig }
): Promise<PluginHookResult | void> | PluginHookResult | void
afterRespond?(
context: AfterRespondContext
): Promise<HTTPResponse | void> | HTTPResponse | void
onError?(
error: unknown,
context: RequestContext
): Promise<HTTPResponse | void> | HTTPResponse | void
}ts
interface PluginHookResult {
url?: string
config?: RequestConfig
}
interface AfterRespondContext {
response: HTTPResponse
/** 经插件处理后的最终 URL(含 prefix / origin / query) */
url: string
/** 经插件处理后的最终配置 */
config: RequestConfig
/** 调用 client.request / get 等方法时传入的原始 URL */
originalUrl: string
/** 合并客户端默认值后、beforeRequest 前的原始配置 */
originalConfig: RequestConfig
client: IHTTPClient
}
interface RequestContext {
url: string
config: RequestConfig
}执行顺序:
- 按注册顺序执行
beforeRequest - 调用底层引擎发送请求
- 按注册顺序执行
afterRespond - 如果流程抛错,再按注册顺序执行
onError
TokenPlugin
ts
TokenPlugin(options: TokenPluginOptions): HTTPClientPlugints
interface TokenPluginOptions {
getter: () => string | null | undefined | Promise<string | null | undefined>
headerName?: string
authType?: 'Bearer' | 'Basic' | 'Custom'
formatter?: (token: string) => string
onRefresh?: () => Promise<void>
isExpired?: () => boolean
isRefreshExpired?: () => boolean
shouldRefresh?: (response: HTTPResponse) => boolean
onRefreshExpired?: () => void
maxRetries?: number
}常见用法:
ts
TokenPlugin({ getter: () => localStorage.getItem('access_token'), authType: 'Bearer' })带刷新逻辑:
ts
TokenPlugin({
getter: () => tokenStore.accessToken,
isExpired: () => tokenStore.isExpired,
onRefresh: async () => {
await tokenStore.refresh()
},
shouldRefresh: (response) => response.code === 401
})注意点:
getter返回null/undefined时不会注入 token- 并发刷新会被串成同一个
refreshPromise shouldRefresh命中后,插件会调用client.request(originalUrl, { ...originalConfig, _retryAttempt })重试原请求,重试会重新走完整插件链maxRetries默认2(最多重试 2 次,共 3 次请求);0表示不重试
MethodOverridePlugin
ts
MethodOverridePlugin(options?: MethodOverridePluginOptions): HTTPClientPlugints
interface MethodOverridePluginOptions {
methods?: RequestMethod[]
overrideMethod?: RequestMethod
headerName?: string
}默认会把 DELETE / PUT / PATCH 改写成 POST,并加上 X-HTTP-Method-Override。
ts
MethodOverridePlugin({ methods: ['DELETE', 'PATCH'], overrideMethod: 'POST' })自定义插件
ts
const tracePlugin = {
name: 'trace',
beforeRequest({ url, config }) {
return {
url,
config: { ...config, headers: { ...config.headers, 'X-Trace-Id': crypto.randomUUID() } }
}
}
}如果你在 afterRespond 或 onError 中要“恢复”请求,返回 HTTPResponse 即可;需要重试时可通过 context.client.request(context.originalUrl, context.originalConfig) 发起。
