@juzi/file-box 1.8.6 → 1.8.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/src/file-box.d.ts.map +1 -1
- package/dist/cjs/src/file-box.js +4 -1
- package/dist/cjs/src/file-box.js.map +1 -1
- package/dist/cjs/src/misc.d.ts.map +1 -1
- package/dist/cjs/src/misc.js +29 -14
- package/dist/cjs/src/misc.js.map +1 -1
- package/dist/cjs/src/misc.spec.js +39 -4
- package/dist/cjs/src/misc.spec.js.map +1 -1
- package/dist/cjs/src/version.js +1 -1
- package/dist/cjs/tests/misc-error-handling.spec.js +34 -8
- package/dist/cjs/tests/misc-error-handling.spec.js.map +1 -1
- package/dist/esm/src/file-box.d.ts.map +1 -1
- package/dist/esm/src/file-box.js +4 -1
- package/dist/esm/src/file-box.js.map +1 -1
- package/dist/esm/src/misc.d.ts.map +1 -1
- package/dist/esm/src/misc.js +29 -14
- package/dist/esm/src/misc.js.map +1 -1
- package/dist/esm/src/misc.spec.js +39 -4
- package/dist/esm/src/misc.spec.js.map +1 -1
- package/dist/esm/src/version.js +1 -1
- package/dist/esm/tests/misc-error-handling.spec.js +34 -8
- package/dist/esm/tests/misc-error-handling.spec.js.map +1 -1
- package/package.json +1 -1
- package/src/file-box.ts +4 -1
- package/src/misc.spec.ts +45 -4
- package/src/misc.ts +29 -14
- package/src/version.ts +1 -1
package/src/misc.ts
CHANGED
|
@@ -91,6 +91,15 @@ export async function httpHeadHeader (url: string, headers: http.OutgoingHttpHea
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
const res = await fetchHead(url, headers, proxyUrl)
|
|
94
|
+
|
|
95
|
+
// HEAD 返回 4xx 时,服务器可能违规携带 body(如 425 返回 HTML),
|
|
96
|
+
// 这些 body 字节会残留在 keep-alive socket 中,污染连接池。
|
|
97
|
+
// 直接销毁 socket 并抛错,让 httpStream 走非 Range 模式用新连接。
|
|
98
|
+
if (res.statusCode && res.statusCode >= 400) {
|
|
99
|
+
res.socket?.destroy()
|
|
100
|
+
res.destroy()
|
|
101
|
+
throw new Error(`HEAD returned ${res.statusCode}`)
|
|
102
|
+
}
|
|
94
103
|
res.destroy()
|
|
95
104
|
|
|
96
105
|
if (!/^3/.test(String(res.statusCode))) {
|
|
@@ -127,8 +136,15 @@ export function httpHeaderToFileName (headers: http.IncomingHttpHeaders): null |
|
|
|
127
136
|
}
|
|
128
137
|
|
|
129
138
|
export async function httpStream (url: string, headers: http.OutgoingHttpHeaders = {}, proxyUrl?: string): Promise<Readable> {
|
|
130
|
-
|
|
131
|
-
|
|
139
|
+
let headHeaders: http.IncomingHttpHeaders | undefined
|
|
140
|
+
try {
|
|
141
|
+
headHeaders = await httpHeadHeader(url, headers, proxyUrl)
|
|
142
|
+
} catch {
|
|
143
|
+
// HEAD 完全失败(如 HPE 解析错误 + Range probe 也失败)
|
|
144
|
+
// 跳过 HEAD 阶段,直接以非 Range 模式下载
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (headHeaders?.location) {
|
|
132
148
|
url = headHeaders.location
|
|
133
149
|
}
|
|
134
150
|
const { protocol, hostname, port } = new URL(url)
|
|
@@ -143,20 +159,18 @@ export async function httpStream (url: string, headers: http.OutgoingHttpHeaders
|
|
|
143
159
|
const defaultPort = protocol === 'https:' ? '443' : '80'
|
|
144
160
|
const hostKey = `${hostname}:${port || defaultPort}`
|
|
145
161
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
162
|
+
if (headHeaders) {
|
|
163
|
+
// A2:若 HEAD 明确声明 Accept-Ranges: none,记录到运行期黑名单
|
|
164
|
+
const acceptRangesRaw = headHeaders['accept-ranges']
|
|
165
|
+
const acceptRanges = Array.isArray(acceptRangesRaw) ? acceptRangesRaw[0] : acceptRangesRaw
|
|
166
|
+
if (typeof acceptRanges === 'string' && acceptRanges.trim().toLowerCase() === 'none') {
|
|
167
|
+
addUnsupportedRangeDomain(hostKey)
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
// HEAD 失败:加入黑名单,downloadFileInChunks 将直接以非 Range 模式发起
|
|
152
171
|
addUnsupportedRangeDomain(hostKey)
|
|
153
172
|
}
|
|
154
173
|
|
|
155
|
-
// 直接尝试分片下载,不检查 fileSize
|
|
156
|
-
// 原因:
|
|
157
|
-
// 1. 有些服务器 HEAD 不返回 Accept-Ranges 但实际支持分片
|
|
158
|
-
// 2. 有些服务器 HEAD 返回 fileSize=0 但实际支持分片
|
|
159
|
-
// downloadFileInChunks 内部有完善的回退机制处理不支持的情况(见 B1)
|
|
160
174
|
const result = await downloadFileInChunks(url, options, proxyUrl, hostKey)
|
|
161
175
|
return result
|
|
162
176
|
}
|
|
@@ -243,8 +257,9 @@ async function fetch (url: string, options: http.RequestOptions, proxyUrl?: stri
|
|
|
243
257
|
async function fetchHead (url: string, headers: http.OutgoingHttpHeaders = {}, proxyUrl?: string): Promise<http.IncomingMessage> {
|
|
244
258
|
try {
|
|
245
259
|
return await fetch(url, {
|
|
246
|
-
headers,
|
|
260
|
+
headers: { ...headers, Connection: 'close' },
|
|
247
261
|
method: 'HEAD',
|
|
262
|
+
agent: false,
|
|
248
263
|
}, proxyUrl)
|
|
249
264
|
} catch (error) {
|
|
250
265
|
if (!shouldFallbackHeadToRangeGet(error)) {
|
package/src/version.ts
CHANGED