* 发起 HTTP/HTTPS 请求 * @param options - 请求选项或 URL 字符串 * @returns Promise 响应对象 * @example * // 基本用法 * const response = await request('https://api.example.com/data'); * const data = response.json(); * * // POST 请求 * const response = await request({ * url: 'https://api.example.com/u
(options: string | RequestOptions)
| 119 | * }); |
| 120 | */ |
| 121 | async function request(options: string | RequestOptions): Promise<Response> { |
| 122 | const config = normalizeOptions(options) |
| 123 | |
| 124 | return new Promise((resolve, reject) => { |
| 125 | try { |
| 126 | const req = net.request(config as ClientRequestConstructorOptions) |
| 127 | |
| 128 | // 设置请求头 |
| 129 | if (config.headers) { |
| 130 | Object.keys(config.headers).forEach((key) => { |
| 131 | req.setHeader(key, config.headers![key]) |
| 132 | }) |
| 133 | } |
| 134 | |
| 135 | // 超时处理 |
| 136 | let timeoutId: NodeJS.Timeout | null = null |
| 137 | if (config.timeout && config.timeout > 0) { |
| 138 | timeoutId = setTimeout(() => { |
| 139 | req.abort() |
| 140 | reject(new RequestError('Request timeout')) |
| 141 | }, config.timeout) |
| 142 | } |
| 143 | |
| 144 | // 处理响应 |
| 145 | req.on('response', (response: IncomingMessage) => { |
| 146 | // 清除超时定时器 |
| 147 | if (timeoutId) { |
| 148 | clearTimeout(timeoutId) |
| 149 | timeoutId = null |
| 150 | } |
| 151 | |
| 152 | let data = '' |
| 153 | |
| 154 | response.on('data', (chunk: Buffer) => { |
| 155 | data += chunk.toString() |
| 156 | }) |
| 157 | |
| 158 | response.on('end', () => { |
| 159 | const result: Response = { |
| 160 | status: response.statusCode, |
| 161 | statusText: response.statusMessage || '', |
| 162 | headers: response.headers, |
| 163 | data, |
| 164 | ok: response.statusCode >= 200 && response.statusCode < 300, |
| 165 | json: <T = any>(): T => { |
| 166 | try { |
| 167 | return JSON.parse(data) as T |
| 168 | } catch (e) { |
| 169 | throw new RequestError( |
| 170 | 'Response body is not valid JSON', |
| 171 | response.statusCode, |
| 172 | result, |
| 173 | ) |
| 174 | } |
| 175 | }, |
| 176 | text: () => data, |
| 177 | } |
| 178 |
no test coverage detected