| 1 | import { net, session, Session } from 'electron'; |
| 2 | import FormData from 'form-data'; |
| 3 | import { ipv4Regular } from '../../commont/regular'; |
| 4 | import { parseProxyString } from '../../commont/utils'; |
| 5 | import { ProxyInfo } from '@@/utils.type'; |
| 6 | |
| 7 | export interface IRequestNetResult<T> { |
| 8 | status: number; |
| 9 | headers: Record<any, any>; |
| 10 | data: T; |
| 11 | } |
| 12 | |
| 13 | export interface IRequestNetParams { |
| 14 | headers?: Record<string, string | string[]>; |
| 15 | url?: string; |
| 16 | body?: any; |
| 17 | method?: 'GET' | 'POST' | 'PUT' | 'DELETE'; |
| 18 | // 是否请求文件 |
| 19 | isReqFile?: boolean; |
| 20 | // body是否为文件 |
| 21 | isFile?: boolean; |
| 22 | formData?: FormData; |
| 23 | // 代理配置,例如 "http=proxy1.com:8080" |
| 24 | proxy?: string; |
| 25 | } |
| 26 | |
| 27 | const requestNet = <T = any>({ |
| 28 | headers, |
| 29 | body, |
| 30 | method, |
| 31 | url, |
| 32 | isFile, |
| 33 | formData, |
| 34 | isReqFile, |
| 35 | proxy, |
| 36 | }: IRequestNetParams): Promise<IRequestNetResult<T>> => { |
| 37 | let customSession: Session; |
| 38 | let proxyInfo: ProxyInfo | false; |
| 39 | return new Promise(async (resolve, reject) => { |
| 40 | try { |
| 41 | // 如果传入了代理配置,动态设置代理 |
| 42 | if (proxy) { |
| 43 | // 解析代理信息 |
| 44 | proxyInfo = parseProxyString(proxy); |
| 45 | if (proxyInfo === false || !ipv4Regular.test(proxyInfo.ipAndPort)) |
| 46 | throw new Error('代理地址不合法'); |
| 47 | customSession = session.fromPartition( |
| 48 | `persist:proxy-session-${Date.now()}`, |
| 49 | ); |
| 50 | const proxyUrl = `${proxyInfo.protocol}://${proxyInfo.ipAndPort}`; |
| 51 | const proxyRules = `http=${proxyUrl};https=${proxyUrl}`; |
| 52 | console.log(proxyRules); |
| 53 | await customSession.setProxy({ |
| 54 | proxyRules, |
| 55 | }); |
| 56 | |
| 57 | headers = { |
| 58 | ...(headers ? headers : {}), |
| 59 | ...(proxy |
| 60 | ? { |
| 61 | 'x-forwarded-for': proxyInfo.ipAndPort, |
| 62 | } |
| 63 | : {}), |
| 64 | }; |
| 65 | } |
| 66 | |
| 67 | if (formData) { |
| 68 | headers = { |
| 69 | ...(headers ? headers : {}), |
| 70 | ...formData.getHeaders(), |
| 71 | }; |
| 72 | } |
| 73 | |
| 74 | const req = net.request({ |
| 75 | method: method || 'GET', |
| 76 | url, |
| 77 | // 如果有代理,使用自定义 session |
| 78 | session: proxy ? customSession! : undefined, |
| 79 | headers, |
| 80 | }); |
| 81 | |
| 82 | // 设置请求头 |
| 83 | if (headers) { |
| 84 | Object.entries(headers).forEach(([key, value]) => { |
| 85 | req.setHeader(key, value as string); |
| 86 | }); |
| 87 | } |
| 88 | |
| 89 | // 处理响应 |
| 90 | req.on('response', (response) => { |
| 91 | const chunks: Buffer<ArrayBufferLike>[] = []; |
| 92 | let data = ''; |
| 93 | response.on('data', (chunk) => { |
| 94 | if (isReqFile) { |
| 95 | chunks.push(chunk); |
| 96 | } else { |
| 97 | data += chunk; |
| 98 | } |
| 99 | }); |
| 100 | |
| 101 | response.on('end', () => { |
| 102 | let parsedData: T; |
| 103 | if (isReqFile) { |
| 104 | const buffer = Buffer.concat(chunks); |
| 105 | parsedData = buffer as any; |
| 106 | } else { |
| 107 | try { |
| 108 | parsedData = JSON.parse(data); |
| 109 | } catch (e) { |
| 110 | parsedData = data as T; |
| 111 | } |
| 112 | } |
| 113 | resolve({ |
| 114 | status: response.statusCode, |
| 115 | headers: response.headers, |
| 116 | data: parsedData, |
| 117 | }); |
| 118 | }); |
| 119 | }); |
| 120 | |
| 121 | if (proxyInfo && typeof proxyInfo === 'object') { |
| 122 | req.on('login', (authInfo, callback) => { |
| 123 | callback( |
| 124 | (proxyInfo as ProxyInfo).username, |
| 125 | (proxyInfo as ProxyInfo).password, |
| 126 | ); |
| 127 | }); |
| 128 | } |
| 129 | |
| 130 | // 错误处理 |
| 131 | req.on('error', (error) => { |
| 132 | console.log('error:', error); |
| 133 | reject(error); |
| 134 | }); |
| 135 | |
| 136 | if (formData) { |
| 137 | formData.pipe(req as any); |
| 138 | const cReq = formData.submit(url!, (err, res) => { |
| 139 | cReq.end(); |
| 140 | }); |
| 141 | } else { |
| 142 | if (isFile) { |
| 143 | req.setHeader('Content-Type', 'application/octet-stream'); |
| 144 | req.write(body); |
| 145 | } else { |
| 146 | // 发送请求体 |
| 147 | if (body) { |
| 148 | req.setHeader('Content-Type', 'application/json'); |
| 149 | req.write(typeof body === 'string' ? body : JSON.stringify(body)); |
| 150 | } |
| 151 | } |
| 152 | req.end(); |
| 153 | } |
| 154 | } catch (error) { |
| 155 | console.log('请求失败:', error); |
| 156 | reject(error); |
| 157 | } |
| 158 | }); |
| 159 | }; |
| 160 | |
| 161 | export default requestNet; |
| 162 |