import { get, hasIn, isNil, isString, merge, omitBy } from 'lodash-es' import type { IStringifyOptions } from 'qs' import qs from 'qs' export async function defaultGetResult(response: Response) { if (response.headers.get('content-type')?.includes('application/json')) { const jsonData = await response.json() if (hasIn(jsonData, 'data')) { return jsonData.data } return jsonData } return response } export class HttpDefine implements Omit { baseURL?: string url?: string method?: string abort?: AbortController timeout?: number credentials?: RequestCredentials ignoreError?: boolean noRedirect?: boolean customErrorMessage?: string ignoreShowLimitedModal?: boolean headers?: Record = { 'Content-Type': 'application/json', } query?: Record // qs 序列化参数使用 querySerializer?: IStringifyOptions body?: Record | FormData static hasOrigin(url: string) { try { const parsedUrl = new URL(url) return parsedUrl.hostname !== '' } catch { // 如果 URL 无效,返回 false return false } } static mergeUrl(baseURL: string, url: string) { if (this.hasOrigin(url)) return url if (!baseURL) return url let prefix = baseURL let last = url if (baseURL[baseURL.length - 1] === '/') { prefix = baseURL.substring(0, baseURL.length - 1) } if (url[0] === '/') { last = url.substring(1) } return `${prefix}/${last}` } static getUrl(define: T = {} as any) { const urlObj = new URL( this.mergeUrl(define.baseURL ?? '', define.url ?? ''), typeof window === 'object' ? window.origin : undefined, ) const searchStr = urlObj.searchParams.toString() const searchObj = merge(qs.parse(searchStr), define.query) const sureSearchStr = qs.stringify(searchObj, define.querySerializer) const base = `${urlObj.origin}${urlObj.pathname}` if (sureSearchStr) { return `${base}?${sureSearchStr}` } return base } static getHeader(define: T = {} as any) { const sureHeaders = omitBy( merge({}, define.headers ?? {}), isNil, ) as Record if ( get(sureHeaders, 'Content-Type', '').includes('multipart/form-data') || define.body instanceof FormData ) { delete sureHeaders['Content-Type'] } else if (!get(sureHeaders, 'Content-Type', '')) { sureHeaders['Content-Type'] = 'application/json' } return sureHeaders } static getBody(define: T = {} as any) { if (isString(define.body)) { return define.body } if (define.body instanceof FormData) { return define.body } if (define.body == null) return null if ( get(define.headers, 'Content-Type', '').includes('multipart/form-data') ) { const formData = new FormData() Object.entries(define.body ?? []).forEach(([key, value]) => { formData.append(key, value) }) return formData } return JSON.stringify(define.body || null) } } export interface HttpInjectInfo { onRequest?: (define: HttpDefine) => Promise onResponse?: (response: Response, define: HttpDefine) => Promise onError?: (error: Error, define: HttpDefine) => void getResult?: (response: Response, define: HttpDefine) => Promise }