import { getAccessToken, clearSession } from './session.uts'
|
import { getApiBaseUrl, isApiConfigured } from '../config/api.uts'
|
|
export type HttpError = {
|
code: string
|
message: string
|
statusCode: number
|
traceId: string
|
}
|
|
export type HttpRequestOptions = {
|
path: string
|
method?: string
|
data?: any
|
idempotencyKey?: string
|
skipAuth?: boolean
|
}
|
|
const requestTimeout = 15000
|
|
const createRequestId = (): string => 'tc-' + Date.now() + '-' + Math.floor(Math.random() * 1000000)
|
const buildUrl = (path: string): string => {
|
const baseUrl = getApiBaseUrl()
|
if (path.indexOf('http://') == 0 || path.indexOf('https://') == 0) return path
|
return baseUrl.replace(/\/$/, '') + '/' + path.replace(/^\//, '')
|
}
|
|
export const resolveApiUrl = (path: string): string => {
|
if (path.indexOf('/uploads/') == 0 || path.indexOf('/api/') == 0) return buildUrl(path)
|
return path
|
}
|
const unavailable = (): HttpError => ({ code: 'API_NOT_CONFIGURED', message: '后台服务尚未配置', statusCode: 0, traceId: '' })
|
|
export const request = <T>(options: HttpRequestOptions, onSuccess: (data: T, traceId: string) => void, onError: (error: HttpError) => void): (() => void) => {
|
if (!isApiConfigured() || options.path.length == 0) {
|
onError(unavailable())
|
return () => {}
|
}
|
const headers: any = {
|
'Content-Type': 'application/json',
|
'X-Request-Id': createRequestId()
|
}
|
if (!options.skipAuth) {
|
const token = getAccessToken()
|
if (token.length > 0) headers['Authorization'] = 'Bearer ' + token
|
}
|
if (options.idempotencyKey != null && options.idempotencyKey.length > 0) headers['X-Idempotency-Key'] = options.idempotencyKey
|
const task: any = uni.request({
|
url: buildUrl(options.path),
|
method: options.method != null ? options.method : 'GET',
|
data: options.data,
|
header: headers,
|
timeout: requestTimeout,
|
success: (response: any) => {
|
const payload: any = response.data
|
const traceId = payload != null && payload.traceId != null ? payload.traceId as string : ''
|
const businessCode = payload != null && payload.code != null ? payload.code : 0
|
if (response.statusCode == 401) {
|
clearSession()
|
onError({ code: 'UNAUTHORIZED', message: '登录已失效,请重新登录', statusCode: 401, traceId: traceId })
|
return
|
}
|
if (response.statusCode < 200 || response.statusCode >= 300) {
|
onError({ code: 'HTTP_' + response.statusCode, message: payload != null && payload.message != null ? payload.message as string : '服务暂不可用', statusCode: response.statusCode, traceId: traceId })
|
return
|
}
|
if (businessCode != 0 && businessCode != 200) {
|
onError({ code: '' + businessCode, message: payload != null && payload.message != null ? payload.message as string : '业务处理失败', statusCode: response.statusCode, traceId: traceId })
|
return
|
}
|
onSuccess((payload != null && payload.data != null ? payload.data : payload) as T, traceId)
|
},
|
fail: (error: any) => onError({ code: 'NETWORK_ERROR', message: error != null && error.errMsg != null ? error.errMsg as string : '网络连接失败,请稍后重试', statusCode: 0, traceId: '' })
|
})
|
return () => task.abort()
|
}
|