更新构建流程,集成 undici 库并优化请求处理

This commit is contained in:
lyswhut
2025-12-12 12:28:04 +08:00
parent a546b75986
commit c40168cacd
10 changed files with 600 additions and 145 deletions
+38 -4
View File
@@ -94,12 +94,46 @@ jobs:
name: lx-music-desktop-win_arm64-green
path: build/*win_arm64-green.7z
- name: Generate file MD5
run: |
cd build
Get-FileHash *.exe,*.7z -Algorithm MD5 | Format-List
- name: Install old electron
run: npm install electron@22
Windows_7:
name: Windows_7
runs-on: windows-latest
env:
BUILD_WIN7: true
# needs: CheckCode
steps:
- name: Check out git repository
uses: actions/checkout@v4
- name: Install python setuptools
run: pip.exe install setuptools
- name: Get npm cache directory
shell: pwsh
run: echo "NPM_CACHE=$(npm config get cache)" >> $env:GITHUB_ENV
- name: Setup Node Env
env:
NPM_CACHE: ${{ env.NPM_CACHE }}
uses: ./.github/actions/setup
- name: Prepare win7 undici env
run: |
npm install undici@5
Set-Content -Path .\src\common\utils\request.ts -Value "export * from './request_node16'"
- name: Build src code
env:
BUILD_WIN7: true
run: |
git status --porcelain
npm run build
- name: Prepare win7 electron env
run: |
npm install electron@22
pip.exe install setuptools
- name: Build Package win7 Setup x64
run: npm run pack:win7:setup:x64
+7
View File
@@ -98,7 +98,14 @@ jobs:
NPM_CACHE: ${{ env.NPM_CACHE }}
uses: ./.github/actions/setup
- name: Prepare win7 undici env
run: |
npm install undici@5
Set-Content -Path .\src\common\utils\request.ts -Value "export * from './request_node16'"
- name: Build src code
env:
BUILD_WIN7: true
run: |
git status --porcelain
npm run build
+7 -1
View File
@@ -19,7 +19,13 @@ const gitInfo = {
}
try {
if (!execSync('git status --porcelain').toString().trim()) {
let isClean = !execSync('git status --porcelain').toString().trim()
if (process.env.BUILD_WIN7) {
console.warn('BUILD_WIN7 is set, skipping git status check.')
console.log('Workspace status:', execSync('git status --porcelain').toString().trim())
isClean = true
}
if (isClean) {
gitInfo.commit_id = execSync('git log -1 --pretty=format:"%H"').toString().trim()
gitInfo.commit_date = execSync('git log -1 --pretty=format:"%ad" --date=iso-strict').toString().trim()
} else if (process.env.IS_CI) {
+13 -3
View File
@@ -27,6 +27,7 @@
"node-id3": "^0.2.9",
"sortablejs": "^1.15.6",
"tunnel": "^0.0.6",
"undici": "^7.16.0",
"utf-8-validate": "^6.0.5",
"vue": "~3.3.13",
"vue-router": "^4.5.1",
@@ -7297,9 +7298,9 @@
}
},
"node_modules/electron/node_modules/@types/node": {
"version": "22.17.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.17.0.tgz",
"integrity": "sha512-bbAKTCqX5aNVryi7qXVMi+OkB3w/OyblodicMbvE38blyAz7GxXf6XYhklokijuPwwVg9sDLKRxt0ZHXQwZVfQ==",
"version": "22.19.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.2.tgz",
"integrity": "sha512-LPM2G3Syo1GLzXLGJAKdqoU35XvrWzGJ21/7sgZTUpbkBaOasTj8tjwn6w+hCkqaa1TfJ/w67rJSwYItlJ2mYw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -17208,6 +17209,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/undici": {
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz",
"integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==",
"license": "MIT",
"engines": {
"node": ">=20.18.1"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+1
View File
@@ -193,6 +193,7 @@
"node-id3": "^0.2.9",
"sortablejs": "^1.15.6",
"tunnel": "^0.0.6",
"undici": "^7.16.0",
"utf-8-validate": "^6.0.5",
"vue": "~3.3.13",
"vue-router": "^4.5.1",
+274
View File
@@ -0,0 +1,274 @@
import qs from 'node:querystring'
import {
FormData,
getGlobalDispatcher,
interceptors,
request as nodeRrequest,
ProxyAgent,
setGlobalDispatcher,
type Dispatcher,
} from 'undici'
const defaultOptions: Options = {
timeout: 15000,
headers: {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
},
maxRedirect: 5,
} as const
const redirectDispatcher = interceptors.redirect({ maxRedirections: defaultOptions.maxRedirect })
const dispatchers = [
interceptors.retry({
maxRetries: 3,
minTimeout: 1000,
maxTimeout: 10000,
timeoutFactor: 2,
retryAfter: true,
}),
// interceptors.responseError(),
] as const
let proxyAgent: ProxyAgent | null = null
let globalDispatcher = getGlobalDispatcher()
const buildDispatcher = (redirectDispatcher: Dispatcher.DispatcherComposeInterceptor | null, retryNum = 3) => {
const otherInterceptors =
retryNum == 3
? dispatchers
: [
interceptors.retry({
maxRetries: retryNum,
minTimeout: 1000,
maxTimeout: 6000,
timeoutFactor: 2,
retryAfter: true,
}),
]
if (redirectDispatcher) {
return (proxyAgent ?? globalDispatcher).compose(redirectDispatcher, ...otherInterceptors)
}
return (proxyAgent ?? globalDispatcher).compose(...otherInterceptors)
}
setGlobalDispatcher(buildDispatcher(redirectDispatcher))
export const setProxy = (url?: string) => {
proxyAgent = url ? new ProxyAgent(url) : null
setGlobalDispatcher(buildDispatcher(redirectDispatcher))
}
export const setProxyByHost = (host?: string, port?: string) => {
setProxy(host ? `http://${host}:${port}` : undefined)
}
const CONTENT_TYPE = {
json: 'application/json',
form: 'application/x-www-form-urlencoded',
text: 'text/plain',
formdata: 'multipart/form-data',
xml: 'application/xml',
binary: 'application/octet-stream',
}
type ParamsData = Record<string, string | number | null | undefined | boolean>
export interface Options {
method?:
| 'GET'
| 'HEAD'
| 'POST'
| 'PUT'
| 'DELETE'
| 'OPTIONS'
| 'PATCH'
| 'PROPFIND'
| 'COPY'
| 'MOVE'
| 'MKCOL'
| 'PROPPATCH'
| 'QUOTA'
query?: ParamsData
headers?: Record<string, string | string[]>
timeout?: number
maxRedirect?: number
signal?: AbortController['signal']
json?: Record<string, unknown>
form?: ParamsData
binary?: Buffer | Uint8Array
text?: string
formdata?: Record<string, string | Buffer | Uint8Array>
xml?: string
needBody?: boolean
needRaw?: boolean
retryNum?: number
}
export interface Response<Res> {
headers: {
accept?: string | undefined
'accept-language'?: string | undefined
'accept-patch'?: string | undefined
'accept-ranges'?: string | undefined
'access-control-allow-credentials'?: string | undefined
'access-control-allow-headers'?: string | undefined
'access-control-allow-methods'?: string | undefined
'access-control-allow-origin'?: string | undefined
'access-control-expose-headers'?: string | undefined
'access-control-max-age'?: string | undefined
'access-control-request-headers'?: string | undefined
'access-control-request-method'?: string | undefined
age?: string | undefined
allow?: string | undefined
'alt-svc'?: string | undefined
authorization?: string | undefined
'cache-control'?: string | undefined
connection?: string | undefined
'content-disposition'?: string | undefined
'content-encoding'?: string | undefined
'content-language'?: string | undefined
'content-length'?: string | undefined
'content-location'?: string | undefined
'content-range'?: string | undefined
'content-type'?: string | undefined
cookie?: string | undefined
date?: string | undefined
etag?: string | undefined
expect?: string | undefined
expires?: string | undefined
forwarded?: string | undefined
from?: string | undefined
host?: string | undefined
'if-match'?: string | undefined
'if-modified-since'?: string | undefined
'if-none-match'?: string | undefined
'if-unmodified-since'?: string | undefined
'last-modified'?: string | undefined
location?: string | undefined
origin?: string | undefined
pragma?: string | undefined
'proxy-authenticate'?: string | undefined
'proxy-authorization'?: string | undefined
'public-key-pins'?: string | undefined
range?: string | undefined
referer?: string | undefined
'retry-after'?: string | undefined
'sec-websocket-accept'?: string | undefined
'sec-websocket-extensions'?: string | undefined
'sec-websocket-key'?: string | undefined
'sec-websocket-protocol'?: string | undefined
'sec-websocket-version'?: string | undefined
'set-cookie'?: string[] | undefined
'strict-transport-security'?: string | undefined
tk?: string | undefined
trailer?: string | undefined
'transfer-encoding'?: string | undefined
upgrade?: string | undefined
'user-agent'?: string | undefined
vary?: string | undefined
via?: string | undefined
warning?: string | undefined
'www-authenticate'?: string | undefined
}
body: Res
raw: Uint8Array
statusCode?: number
statusMessage?: string
}
const buildRequestBody = (options: Options) => {
let contentType: string | undefined
let body: string | Buffer | Uint8Array | FormData | undefined
if (options.json != null) {
contentType = CONTENT_TYPE.json
body = JSON.stringify(options.json)
} else if (options.form != null) {
contentType = CONTENT_TYPE.form
body = qs.stringify(options.form)
} else if (options.binary != null) {
contentType = CONTENT_TYPE.binary
body = options.binary
} else if (options.formdata != null) {
const formdata = new FormData()
// eslint-disable-next-line guard-for-in
for (const key in options.formdata) {
formdata.append(key, options.formdata[key])
}
contentType = CONTENT_TYPE.formdata
body = formdata
} else if (options.xml != null) {
contentType = CONTENT_TYPE.xml
body = options.xml
} else if (options.text != null) {
contentType = CONTENT_TYPE.text
body = options.text
}
const headers = options.headers ?? {}
if (headers['Content-Type']) {
contentType = headers['Content-Type'] as string
}
const finalHeaders: NonNullable<Options['headers']> = { ...defaultOptions.headers, ...headers }
if (contentType) finalHeaders['Content-Type'] = contentType
return [finalHeaders, body] as const
}
const buildRequestDispatcher = (options: Options) => {
let dispatcher: Dispatcher.ComposedDispatcher | undefined
if (options.maxRedirect != null) {
if (options.maxRedirect != defaultOptions.maxRedirect) {
if (options.maxRedirect) {
dispatcher = buildDispatcher(interceptors.redirect({ maxRedirections: options.maxRedirect }), options.retryNum)
} else {
dispatcher = buildDispatcher(null, options.retryNum)
}
}
}
return dispatcher
}
export const request = async <T = unknown>(url: string, options: Options = {}): Promise<Response<T>> => {
const method = options.method?.toUpperCase() ?? 'GET'
const timeout = options.timeout ?? defaultOptions.timeout
const [headers, body] = buildRequestBody(options)
// console.log(url, {
// method,
// bodyTimeout: timeout,
// headersTimeout: timeout,
// headers,
// query: options.query,
// body,
// signal: options.signal,
// dispatcher: buildRequestDispatcher(options),
// })
return nodeRrequest(url, {
method,
bodyTimeout: timeout,
headersTimeout: timeout,
headers,
query: options.query,
body,
signal: options.signal,
dispatcher: buildRequestDispatcher(options),
}).then(async(response) => {
if (options.needBody) {
return {
headers: response.headers,
statusCode: response.statusCode,
body: response.body as unknown as T,
} satisfies Omit<Response<T>, 'raw'> as Response<T>
}
if (options.needRaw) {
return {
headers: response.headers,
statusCode: response.statusCode,
raw: await response.body.bytes(),
} satisfies Omit<Response<T>, 'body'> as Response<T>
}
// console.log(response)
let body = (await response.body.text()) as T
if (!headers['Content-Type'] || headers['Content-Type'].includes(CONTENT_TYPE.json)) {
try {
body = JSON.parse(body as string) as T
} catch {}
}
return {
body,
headers: response.headers,
statusCode: response.statusCode,
} satisfies Omit<Response<T>, 'raw'> as Response<T>
})
}
+237
View File
@@ -0,0 +1,237 @@
import qs from 'node:querystring'
import {
FormData,
getGlobalDispatcher,
request as nodeRrequest,
ProxyAgent,
setGlobalDispatcher,
type Dispatcher,
} from 'undici'
const defaultOptions: Options = {
timeout: 15000,
headers: {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
},
maxRedirect: 5,
} as const
let proxyAgent: ProxyAgent | null = null
let globalDispatcher = getGlobalDispatcher()
const buildDispatcher = () => {
return proxyAgent ?? globalDispatcher
}
setGlobalDispatcher(buildDispatcher())
export const setProxy = (url?: string) => {
proxyAgent = url ? new ProxyAgent(url) : null
setGlobalDispatcher(buildDispatcher())
}
export const setProxyByHost = (host?: string, port?: string) => {
console.log(host)
setProxy(host ? `http://${host}:${port}` : undefined)
}
const CONTENT_TYPE = {
json: 'application/json',
form: 'application/x-www-form-urlencoded',
text: 'text/plain',
formdata: 'multipart/form-data',
xml: 'application/xml',
binary: 'application/octet-stream',
}
type ParamsData = Record<string, string | number | null | undefined | boolean>
export interface Options {
method?:
| 'GET'
| 'HEAD'
| 'POST'
| 'PUT'
| 'DELETE'
| 'OPTIONS'
| 'PATCH'
| 'PROPFIND'
| 'COPY'
| 'MOVE'
| 'MKCOL'
| 'PROPPATCH'
| 'QUOTA'
query?: ParamsData
headers?: Record<string, string | string[]>
timeout?: number
maxRedirect?: number
signal?: AbortController['signal']
json?: Record<string, unknown>
form?: ParamsData
binary?: Buffer | Uint8Array
text?: string
formdata?: Record<string, string | Buffer | Uint8Array>
xml?: string
needBody?: boolean
needRaw?: boolean
retryNum?: number
}
export interface Response<Res> {
headers: {
accept?: string | undefined
'accept-language'?: string | undefined
'accept-patch'?: string | undefined
'accept-ranges'?: string | undefined
'access-control-allow-credentials'?: string | undefined
'access-control-allow-headers'?: string | undefined
'access-control-allow-methods'?: string | undefined
'access-control-allow-origin'?: string | undefined
'access-control-expose-headers'?: string | undefined
'access-control-max-age'?: string | undefined
'access-control-request-headers'?: string | undefined
'access-control-request-method'?: string | undefined
age?: string | undefined
allow?: string | undefined
'alt-svc'?: string | undefined
authorization?: string | undefined
'cache-control'?: string | undefined
connection?: string | undefined
'content-disposition'?: string | undefined
'content-encoding'?: string | undefined
'content-language'?: string | undefined
'content-length'?: string | undefined
'content-location'?: string | undefined
'content-range'?: string | undefined
'content-type'?: string | undefined
cookie?: string | undefined
date?: string | undefined
etag?: string | undefined
expect?: string | undefined
expires?: string | undefined
forwarded?: string | undefined
from?: string | undefined
host?: string | undefined
'if-match'?: string | undefined
'if-modified-since'?: string | undefined
'if-none-match'?: string | undefined
'if-unmodified-since'?: string | undefined
'last-modified'?: string | undefined
location?: string | undefined
origin?: string | undefined
pragma?: string | undefined
'proxy-authenticate'?: string | undefined
'proxy-authorization'?: string | undefined
'public-key-pins'?: string | undefined
range?: string | undefined
referer?: string | undefined
'retry-after'?: string | undefined
'sec-websocket-accept'?: string | undefined
'sec-websocket-extensions'?: string | undefined
'sec-websocket-key'?: string | undefined
'sec-websocket-protocol'?: string | undefined
'sec-websocket-version'?: string | undefined
'set-cookie'?: string[] | undefined
'strict-transport-security'?: string | undefined
tk?: string | undefined
trailer?: string | undefined
'transfer-encoding'?: string | undefined
upgrade?: string | undefined
'user-agent'?: string | undefined
vary?: string | undefined
via?: string | undefined
warning?: string | undefined
'www-authenticate'?: string | undefined
}
body: Res
raw: Uint8Array
statusCode?: number
statusMessage?: string
}
const buildRequestBody = (options: Options) => {
let contentType: string | undefined
let body: string | Buffer | Uint8Array | FormData | undefined
if (options.json != null) {
contentType = CONTENT_TYPE.json
body = JSON.stringify(options.json)
} else if (options.form != null) {
contentType = CONTENT_TYPE.form
body = qs.stringify(options.form)
} else if (options.binary != null) {
contentType = CONTENT_TYPE.binary
body = options.binary
} else if (options.formdata != null) {
const formdata = new FormData()
// eslint-disable-next-line guard-for-in
for (const key in options.formdata) {
formdata.append(key, options.formdata[key])
}
contentType = CONTENT_TYPE.formdata
body = formdata
} else if (options.xml != null) {
contentType = CONTENT_TYPE.xml
body = options.xml
} else if (options.text != null) {
contentType = CONTENT_TYPE.text
body = options.text
}
const headers = options.headers ?? {}
if (headers['Content-Type']) {
contentType = headers['Content-Type'] as string
}
const finalHeaders: NonNullable<Options['headers']> = { ...defaultOptions.headers, ...headers }
if (contentType) finalHeaders['Content-Type'] = contentType
return [finalHeaders, body] as const
}
const buildRequestDispatcher = (options: Options) => {
return buildDispatcher()
}
export const request = async <T = unknown>(url: string, options: Options = {}): Promise<Response<T>> => {
const method = (options.method?.toUpperCase() ?? 'GET') as Dispatcher.RequestOptions['method']
const timeout = options.timeout ?? defaultOptions.timeout
const [headers, body] = buildRequestBody(options)
// console.log(url, {
// method,
// bodyTimeout: timeout,
// headersTimeout: timeout,
// headers,
// query: options.query,
// body,
// signal: options.signal,
// dispatcher: buildRequestDispatcher(options),
// })
return nodeRrequest(url, {
method,
bodyTimeout: timeout,
headersTimeout: timeout,
headers,
query: options.query,
body,
signal: options.signal,
dispatcher: buildRequestDispatcher(options),
}).then(async(response) => {
if (options.needBody) {
return {
headers: response.headers,
statusCode: response.statusCode,
body: response.body as unknown as T,
} satisfies Omit<Response<T>, 'raw'> as Response<T>
}
if (options.needRaw) {
return {
headers: response.headers,
statusCode: response.statusCode,
raw: new Uint8Array(await response.body.arrayBuffer()),
} satisfies Omit<Response<T>, 'body'> as unknown as Response<T>
}
// console.log(response)
let body = (await response.body.text()) as T
if (!headers['Content-Type'] || headers['Content-Type'].includes(CONTENT_TYPE.json)) {
try {
body = JSON.parse(body as string) as T
} catch {}
}
return {
body,
headers: response.headers,
statusCode: response.statusCode,
} satisfies Omit<Response<T>, 'raw'> as Response<T>
})
}
+18 -4
View File
@@ -2,7 +2,7 @@ import path from 'node:path'
import { existsSync, mkdirSync, renameSync } from 'fs'
import { app, shell, screen, nativeTheme, dialog } from 'electron'
import { URL_SCHEME_RXP } from '@common/constants'
import { getTheme, initHotKey, initSetting, parseEnvParams } from './utils'
import { getProxy, getTheme, initHotKey, initSetting, parseEnvParams } from './utils'
import { navigationUrlWhiteList } from '@common/config'
import defaultSetting from '@common/defaultSetting'
import { isExistWindow as isExistMainWindow, showWindow as showMainWindow } from './modules/winMain'
@@ -11,6 +11,7 @@ import { isMac, log } from '@common/utils'
import createWorkers from './worker'
import { migrateDBData } from './utils/migrate'
import { openDirInExplorer } from '@common/utils/electron'
import { setProxyByHost } from '@common/utils/request'
export const initGlobalData = () => {
const envParams = parseEnvParams()
@@ -236,14 +237,27 @@ export const listenerAppEvent = (startApp: () => void) => {
global.lx?.event_app.system_theme_change(shouldUseDarkColors)
})
global.lx.event_app.on('updated_config', (config, setting) => {
if (config.includes('player.volume')) {
const setProxy = () => {
const proxy = getProxy()
if (proxy) {
setProxyByHost(proxy.host, proxy.port ? String(proxy.port) : undefined)
} else setProxyByHost()
}
global.lx.event_app.on('updated_config', (keys, setting) => {
if (keys.includes('network.proxy.enable') || (global.lx.appSetting['network.proxy.enable'] && keys.some(k => k.includes('network.proxy.')))) {
setProxy()
}
if (keys.includes('player.volume')) {
global.lx.event_app.player_status({ volume: Math.trunc(setting['player.volume']! * 100) })
}
if (config.includes('player.isMute')) {
if (keys.includes('player.isMute')) {
global.lx.event_app.player_status({ mute: setting['player.isMute'] })
}
})
global.lx.event_app.on('app_inited', () => {
setProxy()
})
}
const initTheme = () => {
+1 -2
View File
@@ -3,10 +3,9 @@ import { httpFetch, type RequestOptions } from '@main/utils/request'
import { decodeData, encodeData } from '../utils'
export const request = async(url: string, options: RequestOptions = { }) => {
return httpFetch(url, {
return httpFetch<string>(url, {
...options,
timeout: options.timeout ?? 10000,
follow_max: 5,
}).then(response => {
return {
text: response.body,
+4 -131
View File
@@ -1,8 +1,5 @@
import needle, { type NeedleHttpVerbs, type NeedleOptions, type BodyData, type NeedleCallback, type NeedleResponse } from 'needle'
// import progress from 'request-progress'
import { httpOverHttp, httpsOverHttp } from 'tunnel'
import { type ClientRequest } from 'node:http'
import { getProxy } from './index'
import { request, type Options } from '@common/utils/request'
// import fs from 'fs'
export const requestMsg = {
@@ -14,53 +11,6 @@ export const requestMsg = {
cancelRequest: '取消http请求',
} as const
const httpsRxp = /^https:/
const getRequestAgent = (url: string) => {
const proxy = getProxy()
return proxy ? (httpsRxp.test(url) ? httpsOverHttp : httpOverHttp)({ proxy }) : undefined
}
export interface RequestOptions extends NeedleOptions {
method?: NeedleHttpVerbs
body?: BodyData
form?: BodyData
formData?: BodyData
}
export type RequestCallback = NeedleCallback
type RequestResponse = NeedleResponse
const request = (url: string, options: RequestOptions, callback: RequestCallback): ClientRequest => {
let data: BodyData = null
if (options.body) {
data = options.body
} else if (options.form) {
data = options.form
// data.content_type = 'application/x-www-form-urlencoded'
options.json = false
} else if (options.formData) {
data = options.formData
// data.content_type = 'multipart/form-data'
options.json = false
}
options.response_timeout = options.timeout
return needle.request(options.method ?? 'get', url, data, options, (err, resp, body) => {
if (!err) {
body = resp.body = resp.raw.toString()
try {
resp.body = JSON.parse(resp.body)
} catch (_) {}
body = resp.body
}
callback(err, resp, body)
// @ts-expect-error
}).request
}
const defaultHeaders = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
}
// var proxyUrl = "http://" + user + ":" + password + "@" + host + ":" + port;
// var proxiedRequest = request.defaults({'proxy': proxyUrl});
@@ -68,70 +18,13 @@ const defaultHeaders = {
// abort: () => void
// }
/**
* promise 形式的请求方法
* @param {*} url
* @param {*} options
*/
const buildHttpPromose = async(url: string, options: RequestOptions): Promise<RequestResponse> => {
return new Promise((resolve, reject) => {
void fetchData(url, options.method, options, (err, resp, body) => {
// options.isShowProgress && window.api.hideProgress()
// debugRequest && console.log(`\n---response------${url}------------`)
// debugRequest && console.log(body)
// obj.requestObj = null
// obj.cancelFn = null
if (err) {
reject(err)
return
}
resolve(resp)
})
// .then(request => {
// // obj.requestObj = ro
// // if (obj.isCancelled) obj.cancelHttp()
// promise.abort = () => {
// request.destroy(new Error('cancelled'))
// }
// })
})
// let obj = {
// isCancelled: false,
// cancelHttp: () => {
// if (!obj.requestObj) return obj.isCancelled = true
// cancelHttp(obj.requestObj)
// obj.requestObj = null
// obj.promise = obj.cancelHttp = null
// obj.cancelFn(new Error(requestMsg.cancelRequest))
// obj.cancelFn = null
// },
// }
// obj.promise = new Promise((resolve, reject) => {
// obj.cancelFn = reject
// debugRequest && console.log(`\n---send request------${url}------------`)
// fetchData(url, options.method, options, (err, resp, body) => {
// // options.isShowProgress && window.api.hideProgress()
// debugRequest && console.log(`\n---response------${url}------------`)
// debugRequest && console.log(body)
// obj.requestObj = null
// obj.cancelFn = null
// if (err) { reject(err); return }
// resolve(resp)
// }).then(ro => {
// obj.requestObj = ro
// if (obj.isCancelled) obj.cancelHttp()
// })
// })
// return obj
}
/**
* 请求超时自动重试
* @param {*} url
* @param {*} options
*/
export const httpFetch = async(url: string, options: RequestOptions = { method: 'get' }) => {
return buildHttpPromose(url, options).catch(async(err: any) => {
export const httpFetch = async<T = unknown> (url: string, options: Options) => {
return request<T>(url, options).catch(async(err: any) => {
// console.log('出错', err)
if (err.message === 'socket hang up') {
// window.globalObj.apiSource = 'temp'
@@ -166,24 +59,4 @@ export const httpFetch = async(url: string, options: RequestOptions = { method:
// return requestPromise
}
const fetchData = async(url: string, method: RequestOptions['method'], {
headers = {},
format = 'json',
timeout = 15000,
...options
}, callback: RequestCallback) => {
// console.log(url, options)
console.log('---start---', url)
headers = Object.assign({}, headers)
return request(url, {
...options,
method,
headers: Object.assign({}, defaultHeaders, headers),
timeout,
agent: getRequestAgent(url),
json: format === 'json',
}, (err, resp, body) => {
callback(err, resp, body)
})
}
export type RequestOptions = Options