@juzi/file-box 1.8.0 → 1.8.2

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.
Files changed (43) hide show
  1. package/README.md +3 -1
  2. package/dist/cjs/src/config.d.ts +5 -4
  3. package/dist/cjs/src/config.d.ts.map +1 -1
  4. package/dist/cjs/src/config.js +7 -7
  5. package/dist/cjs/src/config.js.map +1 -1
  6. package/dist/cjs/src/file-box.js +1 -1
  7. package/dist/cjs/src/file-box.js.map +1 -1
  8. package/dist/cjs/src/misc.d.ts.map +1 -1
  9. package/dist/cjs/src/misc.js +100 -83
  10. package/dist/cjs/src/misc.js.map +1 -1
  11. package/dist/cjs/src/misc.spec.js +6 -0
  12. package/dist/cjs/src/misc.spec.js.map +1 -1
  13. package/dist/cjs/src/version.js +1 -1
  14. package/dist/cjs/tests/chunk-download.spec.js +12 -56
  15. package/dist/cjs/tests/chunk-download.spec.js.map +1 -1
  16. package/dist/cjs/tests/misc-error-handling.spec.js +36 -26
  17. package/dist/cjs/tests/misc-error-handling.spec.js.map +1 -1
  18. package/dist/cjs/tests/network-timeout.spec.js +101 -118
  19. package/dist/cjs/tests/network-timeout.spec.js.map +1 -1
  20. package/dist/esm/src/config.d.ts +5 -4
  21. package/dist/esm/src/config.d.ts.map +1 -1
  22. package/dist/esm/src/config.js +6 -6
  23. package/dist/esm/src/config.js.map +1 -1
  24. package/dist/esm/src/file-box.js +2 -2
  25. package/dist/esm/src/file-box.js.map +1 -1
  26. package/dist/esm/src/misc.d.ts.map +1 -1
  27. package/dist/esm/src/misc.js +101 -84
  28. package/dist/esm/src/misc.js.map +1 -1
  29. package/dist/esm/src/misc.spec.js +6 -0
  30. package/dist/esm/src/misc.spec.js.map +1 -1
  31. package/dist/esm/src/version.js +1 -1
  32. package/dist/esm/tests/chunk-download.spec.js +12 -56
  33. package/dist/esm/tests/chunk-download.spec.js.map +1 -1
  34. package/dist/esm/tests/misc-error-handling.spec.js +36 -26
  35. package/dist/esm/tests/misc-error-handling.spec.js.map +1 -1
  36. package/dist/esm/tests/network-timeout.spec.js +103 -120
  37. package/dist/esm/tests/network-timeout.spec.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/config.ts +6 -9
  40. package/src/file-box.ts +2 -2
  41. package/src/misc.spec.ts +7 -0
  42. package/src/misc.ts +112 -88
  43. package/src/version.ts +1 -1
@@ -1,136 +1,119 @@
1
1
  #!/usr/bin/env -S node --no-warnings --loader ts-node/esm
2
2
  import { createServer } from 'http';
3
3
  import { setTimeout } from 'timers/promises';
4
- import { sinon, test } from 'tstest';
5
- import { HTTP_REQUEST_TIMEOUT, HTTP_RESPONSE_TIMEOUT } from '../src/config.js';
4
+ import { test } from 'tstest';
5
+ import { CONFIG } from '../src/config.js';
6
6
  import { FileBox } from '../src/mod.js';
7
- test('slow network stall HTTP_TIMEOUT', async (t) => {
8
- const sandbox = sinon.createSandbox();
9
- sandbox.useFakeTimers({
10
- now: Date.now(),
11
- shouldAdvanceTime: true,
12
- shouldClearNativeTimers: true,
13
- toFake: ['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', 'nextTick'],
7
+ test('HTTP timeout handling', async (t) => {
8
+ // 设置短超时用于快速测试
9
+ const originalRequestTimeout = CONFIG.HTTP_REQUEST_TIMEOUT;
10
+ const originalResponseTimeout = CONFIG.HTTP_RESPONSE_TIMEOUT;
11
+ CONFIG.HTTP_REQUEST_TIMEOUT = 200; // 200ms
12
+ CONFIG.HTTP_RESPONSE_TIMEOUT = 300; // 300ms
13
+ t.teardown(() => {
14
+ CONFIG.HTTP_REQUEST_TIMEOUT = originalRequestTimeout;
15
+ CONFIG.HTTP_RESPONSE_TIMEOUT = originalResponseTimeout;
14
16
  });
15
- t.jobs = 3;
16
- const port = Math.floor(Math.random() * (65535 - 49152 + 1)) + 49152;
17
- const URL = {
18
- NOT_TIMEOUT: '/not_timeout',
19
- READY: '/ready',
20
- TIMEOUT: '/timeout',
21
- };
22
- /* eslint @typescript-eslint/no-misused-promises:off */
23
- const server = createServer(async (req, res) => {
24
- if (req.method === 'HEAD') {
25
- res.writeHead(200, {
26
- 'Content-Length': '100',
27
- });
28
- res.end();
29
- return;
30
- }
31
- res.write(Buffer.from('This is the first chunk of data.'));
32
- if (req.url === URL.NOT_TIMEOUT) {
33
- await setTimeout(HTTP_REQUEST_TIMEOUT * 0.5);
34
- res.write(Buffer.from('This is the second chunk of data.'));
35
- }
36
- else if (req.url === URL.READY) {
37
- await setTimeout(HTTP_REQUEST_TIMEOUT + 100);
38
- }
39
- else if (req.url === URL.TIMEOUT) {
40
- if (req.method === 'GET') {
41
- await setTimeout(HTTP_RESPONSE_TIMEOUT + 100);
17
+ await t.test('should complete download without timeout', async (t) => {
18
+ const testData = 'Test data for no timeout';
19
+ const server = createServer((req, res) => {
20
+ if (req.method === 'HEAD') {
21
+ res.writeHead(200, { 'Content-Length': String(testData.length) });
22
+ res.end();
23
+ return;
42
24
  }
43
- }
44
- // console.debug(`${new Date().toLocaleTimeString()} call res.end "${req.url}"`)
45
- res.end(Buffer.from('All data end.'));
46
- });
47
- const host = await new Promise((resolve) => {
48
- server.listen(port, '127.0.0.1', () => {
49
- const addr = server.address();
50
- // console.debug(`Server is listening on port ${JSON.stringify(addr)}`)
51
- resolve(`http://127.0.0.1:${addr.port}`);
25
+ // 服务器不支持 Range,直接返回 200
26
+ // 快速响应,不应该超时
27
+ res.writeHead(200, { 'Content-Length': String(testData.length) });
28
+ res.end(testData);
52
29
  });
53
- });
54
- t.teardown(() => {
55
- // console.debug('teardown')
56
- server.close();
57
- sandbox.restore();
58
- });
59
- /** eslint @typescript-eslint/no-floating-promises:off */
60
- t.test('should not timeout', async (t) => {
61
- const url = `${host}${URL.NOT_TIMEOUT}`;
62
- const dataSpy = sandbox.spy();
63
- const errorSpy = sandbox.spy();
64
- // Disable chunked download for timeout tests
65
- process.env['FILEBOX_NO_SLICE_DOWN'] = 'true';
66
- // console.debug(`${new Date().toLocaleTimeString()} Start request "${url}" ...`)
67
- const start = Date.now();
68
- const stream = await FileBox.fromUrl(url).toStream();
69
- stream.once('error', errorSpy).on('data', dataSpy);
70
- await sandbox.clock.tickAsync(1);
71
- t.ok(dataSpy.calledOnce, `should get chunk 1 (${Date.now() - start} passed)`);
72
- t.ok(errorSpy.notCalled, `should not get error (${Date.now() - start} passed)`);
73
- // FIXME: tickAsync does not work on socket timeout
74
30
  await new Promise((resolve) => {
75
- stream.once('error', resolve).on('close', resolve);
76
- // resolve(setTimeout(HTTP_REQUEST_TIMEOUT))
31
+ server.listen(0, '127.0.0.1', resolve);
77
32
  });
78
- await sandbox.clock.tickAsync(1);
79
- // await sandbox.clock.tickAsync(HTTP_RESPONSE_TIMEOUT)
80
- t.comment('recv data count:', dataSpy.callCount);
81
- t.comment('recv error count:', errorSpy.callCount);
82
- t.ok(dataSpy.calledThrice, `should get chunk 3 after TIMEOUT ${HTTP_REQUEST_TIMEOUT} (${Date.now() - start} passed)`);
83
- t.ok(errorSpy.notCalled, `should not get error after TIMEOUT ${HTTP_REQUEST_TIMEOUT} (${Date.now() - start} passed)`);
33
+ const port = server.address().port;
34
+ t.teardown(() => { server.close(); });
35
+ const url = `http://127.0.0.1:${port}/test`;
36
+ const fileBox = FileBox.fromUrl(url);
37
+ const stream = await fileBox.toStream();
38
+ const chunks = [];
39
+ stream.on('data', (chunk) => chunks.push(chunk));
40
+ await new Promise((resolve, reject) => {
41
+ stream.on('end', resolve);
42
+ stream.on('error', reject);
43
+ });
44
+ const result = Buffer.concat(chunks).toString();
45
+ t.equal(result, testData, 'should receive complete data');
84
46
  t.end();
85
- }).catch(t.threw);
86
- /** eslint @typescript-eslint/no-floating-promises:off */
87
- t.test('should timeout', { skip: 'FIXME: fake timers cannot simulate socket timeout' }, async (t) => {
88
- const url = `${host}${URL.TIMEOUT}`;
89
- const dataSpy = sandbox.spy();
90
- const errorSpy = sandbox.spy();
91
- // Disable chunked download for timeout tests
92
- process.env['FILEBOX_NO_SLICE_DOWN'] = 'true';
93
- // console.debug(`${new Date().toLocaleTimeString()} Start request "${url}" ...`)
94
- const start = Date.now();
95
- const stream = await FileBox.fromUrl(url).toStream();
96
- stream.once('error', errorSpy).once('data', dataSpy);
97
- // .on('error', (e) => {
98
- // console.error(`on error for req "${url}":`, e.stack)
99
- // })
100
- // .on('data', (d: Buffer) => {
101
- // console.error(`on data for req "${url}":`, d.toString())
102
- // })
103
- await sandbox.clock.tickAsync(1);
104
- // t.comment('recv data count:', dataSpy.callCount)
105
- // t.comment('recv error count:', errorSpy.callCount)
106
- t.ok(dataSpy.calledOnce, `should get chunk 1 (${Date.now() - start} passed)`);
107
- t.ok(errorSpy.notCalled, `should not get error (${Date.now() - start} passed)`);
108
- // FIXME: tickAsync does not work on socket timeout
47
+ });
48
+ await t.test('should handle response timeout', async (t) => {
49
+ const server = createServer((req, res) => {
50
+ if (req.method === 'HEAD') {
51
+ res.writeHead(200, { 'Content-Length': '100' });
52
+ res.end();
53
+ return;
54
+ }
55
+ // 发送部分数据后停止,不调用 res.end()
56
+ // 让连接挂起,Socket 会在 HTTP_RESPONSE_TIMEOUT 后超时
57
+ res.writeHead(200, { 'Content-Length': '100' });
58
+ res.write('Partial data...');
59
+ // 不调用 res.end()
60
+ });
109
61
  await new Promise((resolve) => {
110
- stream.once('error', resolve).on('close', resolve);
111
- // resolve(setTimeout(HTTP_RESPONSE_TIMEOUT))
62
+ server.listen(0, '127.0.0.1', resolve);
112
63
  });
113
- await sandbox.clock.tickAsync(1);
114
- // await sandbox.clock.tickAsync(HTTP_RESPONSE_TIMEOUT)
115
- // t.comment('recv data count:', dataSpy.callCount)
116
- // t.comment('recv error count:', errorSpy.callCount)
117
- t.ok(errorSpy.calledOnce, `should get error after TIMEOUT ${HTTP_RESPONSE_TIMEOUT} (${Date.now() - start} passed)`);
64
+ const port = server.address().port;
65
+ t.teardown(() => { server.close(); });
66
+ const url = `http://127.0.0.1:${port}/timeout`;
67
+ try {
68
+ const fileBox = FileBox.fromUrl(url);
69
+ const stream = await fileBox.toStream();
70
+ const chunks = [];
71
+ await new Promise((resolve, reject) => {
72
+ stream.on('data', (chunk) => chunks.push(chunk));
73
+ stream.on('end', resolve);
74
+ stream.on('error', reject);
75
+ });
76
+ t.fail('should have thrown timeout error');
77
+ }
78
+ catch (error) {
79
+ const err = error;
80
+ t.ok(err.message.includes('timeout'), `should timeout with error: ${err.message}`);
81
+ }
118
82
  t.end();
119
- }).catch(t.threw);
120
- /** eslint @typescript-eslint/no-floating-promises:off */
121
- t.test('ready should timeout', { skip: 'FIXME: fake timers cannot simulate socket timeout' }, async (t) => {
122
- const url = `${host}${URL.READY}`;
123
- const errorSpy = sandbox.spy();
124
- // Disable chunked download for timeout tests
125
- process.env['FILEBOX_NO_SLICE_DOWN'] = 'true';
126
- // console.debug(`${new Date().toLocaleTimeString()} Start request "${url}" ...`)
127
- const start = Date.now();
128
- const fileBox = FileBox.fromUrl(url);
129
- await fileBox.ready().catch(errorSpy);
130
- await sandbox.clock.tickAsync(1);
131
- // t.comment('recv error count:', errorSpy.callCount)
132
- t.ok(errorSpy.calledOnce, `should get error after TIMEOUT ${HTTP_REQUEST_TIMEOUT} (${Date.now() - start} passed)`);
83
+ });
84
+ await t.test('should handle request timeout', async (t) => {
85
+ let requestReceived = false;
86
+ /* eslint @typescript-eslint/no-misused-promises:off */
87
+ const server = createServer(async (req, res) => {
88
+ if (req.method === 'HEAD') {
89
+ res.writeHead(200, { 'Content-Length': '100' });
90
+ res.end();
91
+ return;
92
+ }
93
+ requestReceived = true;
94
+ // 延迟响应超过 HTTP_REQUEST_TIMEOUT
95
+ // 在发送任何数据之前延迟,触发 request timeout
96
+ await setTimeout(CONFIG.HTTP_REQUEST_TIMEOUT + 100);
97
+ res.writeHead(200, { 'Content-Length': '10' });
98
+ res.end('Too late');
99
+ });
100
+ await new Promise((resolve) => {
101
+ server.listen(0, '127.0.0.1', resolve);
102
+ });
103
+ const port = server.address().port;
104
+ t.teardown(() => { server.close(); });
105
+ const url = `http://127.0.0.1:${port}/request-timeout`;
106
+ try {
107
+ const fileBox = FileBox.fromUrl(url);
108
+ await fileBox.toStream();
109
+ t.fail('should have thrown timeout error');
110
+ }
111
+ catch (error) {
112
+ const err = error;
113
+ t.ok(requestReceived, 'should have received request');
114
+ t.ok(err.message.includes('timeout'), `should timeout with error: ${err.message}`);
115
+ }
133
116
  t.end();
134
- }).catch(t.threw);
117
+ });
135
118
  });
136
119
  //# sourceMappingURL=network-timeout.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"network-timeout.spec.js","sourceRoot":"","sources":["../../../tests/network-timeout.spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"network-timeout.spec.js","sourceRoot":"","sources":["../../../tests/network-timeout.spec.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juzi/file-box",
3
- "version": "1.8.0",
3
+ "version": "1.8.2",
4
4
  "description": "Pack a File into Box for easy move/transfer between servers no matter of where it is.(local path, remote url, or cloud storage)",
5
5
  "type": "module",
6
6
  "exports": {
package/src/config.ts CHANGED
@@ -1,12 +1,9 @@
1
1
  /// <reference path="./typings.d.ts" />
2
2
  export { VERSION } from './version.js'
3
3
 
4
- export const HTTP_REQUEST_TIMEOUT = Number(process.env['FILEBOX_HTTP_REQUEST_TIMEOUT'])
5
- || 10 * 1000
6
-
7
- export const HTTP_RESPONSE_TIMEOUT = Number(process.env['FILEBOX_HTTP_RESPONSE_TIMEOUT'] ?? process.env['FILEBOX_HTTP_TIMEOUT'])
8
- || 60 * 1000
9
-
10
- export const NO_SLICE_DOWN = process.env['FILEBOX_NO_SLICE_DOWN'] === 'true'
11
-
12
- export const READY_RETRY = Number(process.env['FILE_BOX_READY_RETRY']) || 3
4
+ // 导出可变配置对象,支持测试时动态修改
5
+ export const CONFIG = {
6
+ HTTP_REQUEST_TIMEOUT: Number(process.env['FILEBOX_HTTP_REQUEST_TIMEOUT']) || 10 * 1000,
7
+ HTTP_RESPONSE_TIMEOUT: Number(process.env['FILEBOX_HTTP_RESPONSE_TIMEOUT'] ?? process.env['FILEBOX_HTTP_TIMEOUT']) || 60 * 1000,
8
+ READY_RETRY: Number(process.env['FILEBOX_READY_RETRY'] ?? process.env['FILE_BOX_READY_RETRY']) || 3,
9
+ }
package/src/file-box.ts CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  } from 'clone-class'
26
26
 
27
27
  import {
28
- READY_RETRY,
28
+ CONFIG,
29
29
  VERSION,
30
30
  } from './config.js'
31
31
  import {
@@ -637,7 +637,7 @@ class FileBox implements Pipeable, FileBoxInterface {
637
637
  break
638
638
  } catch (e) {
639
639
  tryCount++
640
- if (tryCount >= READY_RETRY) {
640
+ if (tryCount >= CONFIG.READY_RETRY) {
641
641
  throw e
642
642
  }
643
643
  }
package/src/misc.spec.ts CHANGED
@@ -5,6 +5,7 @@ import { createServer } from 'http'
5
5
  import type { AddressInfo } from 'net'
6
6
  import { test } from 'tstest'
7
7
 
8
+ import { CONFIG } from './config.js'
8
9
  import {
9
10
  dataUrlToBase64,
10
11
  httpHeaderToFileName,
@@ -13,6 +14,10 @@ import {
13
14
  streamToBuffer,
14
15
  } from './misc.js'
15
16
 
17
+ // 设置短超时用于测试
18
+ CONFIG.HTTP_REQUEST_TIMEOUT = 1000
19
+ CONFIG.HTTP_RESPONSE_TIMEOUT = 1000
20
+
16
21
  test('dataUrl to base64', async t => {
17
22
  const base64 = [
18
23
  'R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl',
@@ -97,6 +102,8 @@ test('httpStream', async t => {
97
102
  return
98
103
  }
99
104
 
105
+ // This server doesn't support Range, always return 200 with full content
106
+ // (ignoring any Range header)
100
107
  res.writeHead(200, {
101
108
  'Content-Length': String(content.length),
102
109
  'Content-Type': 'application/json',