import { ApiStatus } from './status'
|
import { $t } from '@/locales'
|
class HttpError extends Error {
|
constructor(message, code, options) {
|
super(message)
|
this.name = 'HttpError'
|
this.code = code
|
this.data = options?.data
|
this.timestamp = /* @__PURE__ */ new Date().toISOString()
|
this.url = options?.url
|
this.method = options?.method
|
this.status = options?.status
|
this.contentType = options?.contentType
|
}
|
toLogData() {
|
return {
|
code: this.code,
|
message: this.message,
|
data: this.data,
|
timestamp: this.timestamp,
|
url: this.url,
|
method: this.method,
|
status: this.status,
|
contentType: this.contentType,
|
stack: this.stack
|
}
|
}
|
}
|
function resolveRequestUrl(config) {
|
const baseURL = String(config?.baseURL || '').trim()
|
const requestUrl = String(config?.url || '').trim()
|
if (!baseURL && !requestUrl) {
|
return void 0
|
}
|
if (!baseURL) {
|
return requestUrl || void 0
|
}
|
if (!requestUrl) {
|
return baseURL
|
}
|
const isAbsoluteBase = /^https?:\/\//i.test(baseURL)
|
if (!isAbsoluteBase) {
|
const normalizedBase = baseURL.replace(/\/+$/, '')
|
const normalizedUrl = requestUrl.replace(/^\/+/, '')
|
if (!normalizedBase) {
|
return requestUrl
|
}
|
if (!normalizedUrl) {
|
return normalizedBase
|
}
|
return `${normalizedBase}/${normalizedUrl}`
|
}
|
try {
|
const origin = globalThis?.location?.origin || 'http://localhost'
|
const normalizedBase = new URL(baseURL, origin)
|
return new URL(requestUrl, normalizedBase).toString()
|
} catch {
|
const normalizedBase = baseURL.replace(/\/+$/, '')
|
const normalizedUrl = requestUrl.replace(/^\/+/, '')
|
if (!normalizedBase) {
|
return requestUrl
|
}
|
if (!normalizedUrl) {
|
return normalizedBase
|
}
|
return `${normalizedBase}/${normalizedUrl}`
|
}
|
}
|
const getErrorMessage = (status) => {
|
const errorMap = {
|
[ApiStatus.unauthorized]: 'httpMsg.unauthorized',
|
[ApiStatus.forbidden]: 'httpMsg.forbidden',
|
[ApiStatus.notFound]: 'httpMsg.notFound',
|
[ApiStatus.methodNotAllowed]: 'httpMsg.methodNotAllowed',
|
[ApiStatus.requestTimeout]: 'httpMsg.requestTimeout',
|
[ApiStatus.internalServerError]: 'httpMsg.internalServerError',
|
[ApiStatus.badGateway]: 'httpMsg.badGateway',
|
[ApiStatus.serviceUnavailable]: 'httpMsg.serviceUnavailable',
|
[ApiStatus.gatewayTimeout]: 'httpMsg.gatewayTimeout'
|
}
|
return $t(errorMap[status] || 'httpMsg.internalServerError')
|
}
|
function isRequestCancelled(error) {
|
const message = String(error?.message || '').toLowerCase()
|
return (
|
error?.code === 'ERR_CANCELED' ||
|
error?.name === 'CanceledError' ||
|
error?.name === 'AbortError' ||
|
message.includes('canceled') ||
|
message.includes('cancelled') ||
|
message.includes('aborted') ||
|
message.includes('请求已取消')
|
)
|
}
|
function handleError(error) {
|
const requestConfig = error.config
|
if (isRequestCancelled(error)) {
|
throw new HttpError($t('httpMsg.requestCancelled'), 'REQUEST_CANCELLED', {
|
url: resolveRequestUrl(requestConfig),
|
method: requestConfig?.method?.toUpperCase()
|
})
|
}
|
const statusCode = error.response?.status
|
const errorMessage = error.response?.data?.msg || error.message
|
if (!error.response) {
|
throw new HttpError($t('httpMsg.networkError'), ApiStatus.error, {
|
url: resolveRequestUrl(requestConfig),
|
method: requestConfig?.method?.toUpperCase()
|
})
|
}
|
const message = statusCode
|
? getErrorMessage(statusCode)
|
: errorMessage || $t('httpMsg.requestFailed')
|
throw new HttpError(message, statusCode || ApiStatus.error, {
|
data: error.response.data,
|
url: resolveRequestUrl(requestConfig),
|
method: requestConfig?.method?.toUpperCase(),
|
status: statusCode,
|
contentType: error.response?.headers?.['content-type']
|
})
|
}
|
function showError(error, showMessage = true) {
|
if (error.code === 'REQUEST_CANCELLED') {
|
return
|
}
|
if (showMessage) {
|
ElMessage.error(error.message)
|
}
|
console.error('[HTTP Error]', error.toLogData())
|
}
|
function showSuccess(message, showMessage = true) {
|
if (showMessage) {
|
ElMessage.success(message)
|
}
|
}
|
const isHttpError = (error) => {
|
return error instanceof HttpError
|
}
|
export { HttpError, handleError, isHttpError, resolveRequestUrl, showError, showSuccess }
|