Skip to content

Commit

Permalink
feat: support interceptors system
Browse files Browse the repository at this point in the history
  • Loading branch information
haoziqaq committed Nov 30, 2023
1 parent 8c11b1d commit 76b5fb5
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 2 deletions.
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './instance.js'
export * from './instance.js'
export * from './interceptors'
35 changes: 34 additions & 1 deletion src/instance.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import axios from 'axios'
import qs from 'qs'
import type { AxiosInstance, AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse, HeadersDefaults, ResponseType } from 'axios'
import type {
AxiosInstance,
AxiosInterceptorOptions,
AxiosRequestConfig,
AxiosRequestHeaders,
AxiosResponse,
HeadersDefaults,
InternalAxiosRequestConfig,
ResponseType,
} from 'axios'
import { inBrowser } from '@varlet/shared'

export type AxleRequestConfig = AxiosRequestConfig & {
Expand All @@ -25,6 +34,16 @@ export type ModifyMethod = 'post' | 'put' | 'patch'

export type RunnerMethod = keyof Omit<AxleInstance, 'axios' | 'getHeaders' | 'setHeader' | 'removeHeader'>

export interface Interceptor<V> {
onFulfilled?: ((value: V) => any) | null
onRejected?: ((error: any) => any) | null
options?: AxiosInterceptorOptions
}

export type RequestInterceptor = Interceptor<InternalAxiosRequestConfig>

export type ResponseInterceptor<V = AxiosResponse<any, any>> = Interceptor<V>

export type AxleInstance = {
get: FetchRunner
getBlob: FetchRunner
Expand Down Expand Up @@ -70,6 +89,9 @@ export type AxleInstance = {
setHeader(key: string, value: string): void
removeHeader(key: string | string[]): void

useRequestInterceptor(interceptor: RequestInterceptor): void
useResponseInterceptor(interceptor: ResponseInterceptor): void

axios: AxiosInstance
}

Expand Down Expand Up @@ -143,6 +165,14 @@ export function createAxle(config: AxiosRequestConfig = {}): AxleInstance {
key.forEach((k) => Reflect.deleteProperty(service.defaults.headers['common'] as AxiosRequestHeaders, k))
}

function useRequestInterceptor(interceptor: RequestInterceptor) {
service.interceptors.request.use(interceptor.onFulfilled, interceptor.onRejected, interceptor.options)
}

function useResponseInterceptor(interceptor: ResponseInterceptor) {
service.interceptors.response.use(interceptor.onFulfilled, interceptor.onRejected, interceptor.options)
}

return {
get: createFetchRunner(service, 'get', 'json'),
getBlob: createFetchRunner(service, 'get', 'blob'),
Expand Down Expand Up @@ -188,6 +218,9 @@ export function createAxle(config: AxiosRequestConfig = {}): AxleInstance {
setHeader,
removeHeader,

useRequestInterceptor,
useResponseInterceptor,

axios: service,
}
}
2 changes: 2 additions & 0 deletions src/interceptors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './requestHeadersInterceptor'
export * from './responseBlobInterceptor'
25 changes: 25 additions & 0 deletions src/interceptors/requestHeadersInterceptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { isFunction } from '@varlet/shared'
import type { RequestInterceptor } from '../instance'

export interface RequestHeadersInterceptorOptions {
headers?: Record<string, string> | (() => Record<string, string>)
}

export function requestHeadersInterceptor(options: RequestHeadersInterceptorOptions = {}): RequestInterceptor {
const { headers: headersOrGetter } = options

return {
onFulfilled(config) {
const headers = (isFunction(headersOrGetter) ? headersOrGetter() : headersOrGetter) ?? {}

Object.entries(headers).forEach(([key, value]) => {
config.headers[key] = value
})

return config
},
onRejected(error) {
return Promise.reject(error)
}
}
}
21 changes: 21 additions & 0 deletions src/interceptors/responseBlobInterceptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { AxiosResponse } from 'axios'
import type { ResponseInterceptor } from '../instance'

export interface ResponseBlobInterceptorOptions {
data?: (response: AxiosResponse<any, any>) => any
}

export function responseBlobInterceptor(options: ResponseBlobInterceptorOptions = {}): ResponseInterceptor {
return {
onFulfilled(response) {
if (response.request.responseType === 'blob') {
return options.data?.(response) ?? response
}

return response
},
onRejected(error) {
return Promise.reject(error)
},
}
}

0 comments on commit 76b5fb5

Please sign in to comment.