koa-files 4.0.6 → 4.1.0
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/README.md +7 -3
- package/cjs/ReadStream.cjs +38 -40
- package/cjs/ReadStream.d.cts +5 -4
- package/cjs/Service.cjs +16 -18
- package/cjs/Service.d.cts +5 -9
- package/cjs/index.cjs +1 -1
- package/cjs/utils/fs.cjs +1 -1
- package/cjs/utils/hash.cjs +1 -1
- package/cjs/utils/http.cjs +1 -1
- package/cjs/utils/http.d.cts +1 -1
- package/cjs/utils/path.cjs +1 -1
- package/cjs/utils/type.cjs +1 -1
- package/esm/ReadStream.d.ts +5 -4
- package/esm/ReadStream.js +38 -40
- package/esm/Service.d.ts +5 -9
- package/esm/Service.js +16 -18
- package/esm/index.js +1 -1
- package/esm/utils/fs.js +1 -1
- package/esm/utils/hash.js +1 -1
- package/esm/utils/http.d.ts +1 -1
- package/esm/utils/http.js +1 -1
- package/esm/utils/path.js +1 -1
- package/esm/utils/type.js +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -29,6 +29,10 @@ interface IgnoreFunction {
|
|
|
29
29
|
(path: string): boolean | Promise<boolean>;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
interface HighWaterMarkFunction {
|
|
33
|
+
(path: string, stats: Stats): Promise<number> | number;
|
|
34
|
+
}
|
|
35
|
+
|
|
32
36
|
interface HeadersFunction {
|
|
33
37
|
(path: string, stats: Stats): Promise<Headers | void> | Headers | void;
|
|
34
38
|
}
|
|
@@ -41,14 +45,14 @@ export interface FileSystem {
|
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
export interface Options {
|
|
44
|
-
fs?: FileSystem;
|
|
45
|
-
defer?: boolean;
|
|
46
48
|
etag?: boolean;
|
|
49
|
+
defer?: boolean;
|
|
50
|
+
fs?: FileSystem;
|
|
47
51
|
acceptRanges?: boolean;
|
|
48
52
|
lastModified?: boolean;
|
|
49
|
-
highWaterMark?: number;
|
|
50
53
|
ignore?: IgnoreFunction;
|
|
51
54
|
headers?: Headers | HeadersFunction;
|
|
55
|
+
highWaterMark?: number | HighWaterMarkFunction;
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
export function server(root: string, options?: Options): Middleware;
|
package/cjs/ReadStream.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @package koa-files
|
|
3
3
|
* @license MIT
|
|
4
|
-
* @version 4.0
|
|
4
|
+
* @version 4.1.0
|
|
5
5
|
* @author nuintun <nuintun@qq.com>
|
|
6
6
|
* @description A static files serving middleware for koa.
|
|
7
7
|
* @see https://github.com/nuintun/koa-files#readme
|
|
@@ -70,20 +70,19 @@ class ReadStream extends stream.Readable {
|
|
|
70
70
|
}
|
|
71
71
|
/**
|
|
72
72
|
* @private
|
|
73
|
-
* @method
|
|
73
|
+
* @method readPadding
|
|
74
74
|
* @param fd The file descriptor.
|
|
75
75
|
* @param range The current range.
|
|
76
76
|
* @param size The number of bytes to read.
|
|
77
77
|
*/
|
|
78
|
-
|
|
78
|
+
readPadding(fd, range, size) {
|
|
79
79
|
let bytesRead = 0;
|
|
80
80
|
const padding = this.getPadding(range);
|
|
81
|
-
const hasRangePadding = padding != null;
|
|
82
81
|
// If padding exists.
|
|
83
|
-
if (
|
|
82
|
+
if (padding != null) {
|
|
84
83
|
const { length } = padding;
|
|
85
84
|
const begin = this.bytesRead;
|
|
86
|
-
if (
|
|
85
|
+
if (begin < length) {
|
|
87
86
|
bytesRead = Math.min(size, length - begin);
|
|
88
87
|
const end = begin + bytesRead;
|
|
89
88
|
this.push(padding.subarray(begin, end));
|
|
@@ -91,14 +90,13 @@ class ReadStream extends stream.Readable {
|
|
|
91
90
|
}
|
|
92
91
|
}
|
|
93
92
|
// If no padding or read completed.
|
|
94
|
-
if (bytesRead
|
|
93
|
+
if (bytesRead < size) {
|
|
95
94
|
this.bytesRead = 0;
|
|
96
|
-
const { readState } = this;
|
|
97
95
|
// Change read state.
|
|
98
|
-
switch (readState) {
|
|
96
|
+
switch (this.readState) {
|
|
99
97
|
case 0 /* ReadState.PREFIX */:
|
|
100
98
|
this.readState = 1 /* ReadState.RANGE */;
|
|
101
|
-
this.readFileRange(fd, range, size);
|
|
99
|
+
this.readFileRange(fd, range, size - bytesRead);
|
|
102
100
|
break;
|
|
103
101
|
case 2 /* ReadState.SUFFIX */:
|
|
104
102
|
this.currentRangeIndex++;
|
|
@@ -107,7 +105,7 @@ class ReadStream extends stream.Readable {
|
|
|
107
105
|
if (nextRange == null) {
|
|
108
106
|
this.push(null);
|
|
109
107
|
} else {
|
|
110
|
-
this.
|
|
108
|
+
this.readPadding(fd, nextRange, size - bytesRead);
|
|
111
109
|
}
|
|
112
110
|
break;
|
|
113
111
|
}
|
|
@@ -121,39 +119,40 @@ class ReadStream extends stream.Readable {
|
|
|
121
119
|
* @param size The number of bytes to read.
|
|
122
120
|
*/
|
|
123
121
|
readFileRange(fd, range, size) {
|
|
124
|
-
|
|
122
|
+
const { length } = range;
|
|
125
123
|
const { bytesRead } = this;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
124
|
+
// File range not finished.
|
|
125
|
+
if (bytesRead < length) {
|
|
126
|
+
this.reading = true;
|
|
127
|
+
const bytesToRead = Math.min(size, length - bytesRead);
|
|
128
|
+
const buffer$1 = buffer.Buffer.allocUnsafeSlow(bytesToRead);
|
|
129
|
+
const position = range.offset + bytesRead;
|
|
130
|
+
// Read file range.
|
|
131
|
+
this.fs.read(fd, buffer$1, 0, bytesToRead, position, (readError, bytesRead, buffer) => {
|
|
132
|
+
this.reading = false;
|
|
133
|
+
// Tell ._destroy() that it's safe to close the fd now.
|
|
134
|
+
if (this.destroyed) {
|
|
135
|
+
this.emit(DISPOSE_EVENT, readError);
|
|
136
|
+
} else if (readError != null) {
|
|
136
137
|
this.destroy(readError);
|
|
138
|
+
} else if (bytesRead !== bytesToRead) {
|
|
139
|
+
this.destroy(new RangeError('invalid read operation'));
|
|
137
140
|
} else {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
// large backing buffer for small reads.
|
|
143
|
-
const chunk = buffer.Buffer.allocUnsafeSlow(bytesRead);
|
|
144
|
-
buffer$1.copy(chunk, 0, 0, bytesRead);
|
|
145
|
-
buffer$1 = chunk;
|
|
146
|
-
}
|
|
147
|
-
this.push(buffer$1);
|
|
148
|
-
this.bytesRead += bytesRead;
|
|
149
|
-
} else {
|
|
141
|
+
this.push(buffer);
|
|
142
|
+
this.bytesRead += bytesRead;
|
|
143
|
+
// file range read completed.
|
|
144
|
+
if (bytesRead < size) {
|
|
150
145
|
this.bytesRead = 0;
|
|
151
146
|
this.readState = 2 /* ReadState.SUFFIX */;
|
|
152
|
-
this.
|
|
147
|
+
this.readPadding(fd, range, size - bytesRead);
|
|
153
148
|
}
|
|
154
149
|
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
150
|
+
});
|
|
151
|
+
} else {
|
|
152
|
+
this.bytesRead = 0;
|
|
153
|
+
this.readState = 2 /* ReadState.SUFFIX */;
|
|
154
|
+
this.readPadding(fd, range, size);
|
|
155
|
+
}
|
|
157
156
|
}
|
|
158
157
|
/**
|
|
159
158
|
* @override
|
|
@@ -168,12 +167,11 @@ class ReadStream extends stream.Readable {
|
|
|
168
167
|
if (fd == null || range == null) {
|
|
169
168
|
this.push(null);
|
|
170
169
|
} else {
|
|
171
|
-
const { readState } = this;
|
|
172
170
|
// Read bytes from range.
|
|
173
|
-
switch (readState) {
|
|
171
|
+
switch (this.readState) {
|
|
174
172
|
case 0 /* ReadState.PREFIX */:
|
|
175
173
|
case 2 /* ReadState.SUFFIX */:
|
|
176
|
-
this.
|
|
174
|
+
this.readPadding(fd, range, size);
|
|
177
175
|
break;
|
|
178
176
|
case 1 /* ReadState.RANGE */:
|
|
179
177
|
this.readFileRange(fd, range, size);
|
package/cjs/ReadStream.d.cts
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
* @module ReadStream
|
|
3
3
|
*/
|
|
4
4
|
import { PathLike } from 'fs';
|
|
5
|
+
import { Readable } from 'stream';
|
|
5
6
|
import { Range } from './utils/http.cjs';
|
|
6
7
|
import { FileSystem } from './utils/fs.cjs';
|
|
7
|
-
|
|
8
|
-
export interface Options extends Pick<ReadableOptions, 'highWaterMark'> {
|
|
8
|
+
export interface Options {
|
|
9
9
|
fs: FileSystem;
|
|
10
|
+
highWaterMark?: number;
|
|
10
11
|
}
|
|
11
12
|
interface Callback {
|
|
12
13
|
(error?: Error | null): void;
|
|
@@ -46,12 +47,12 @@ export declare class ReadStream extends Readable {
|
|
|
46
47
|
private getPadding;
|
|
47
48
|
/**
|
|
48
49
|
* @private
|
|
49
|
-
* @method
|
|
50
|
+
* @method readPadding
|
|
50
51
|
* @param fd The file descriptor.
|
|
51
52
|
* @param range The current range.
|
|
52
53
|
* @param size The number of bytes to read.
|
|
53
54
|
*/
|
|
54
|
-
private
|
|
55
|
+
private readPadding;
|
|
55
56
|
/**
|
|
56
57
|
* @private
|
|
57
58
|
* @method readFileRange
|
package/cjs/Service.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @package koa-files
|
|
3
3
|
* @license MIT
|
|
4
|
-
* @version 4.0
|
|
4
|
+
* @version 4.1.0
|
|
5
5
|
* @author nuintun <nuintun@qq.com>
|
|
6
6
|
* @description A static files serving middleware for koa.
|
|
7
7
|
* @see https://github.com/nuintun/koa-files#readme
|
|
@@ -38,20 +38,15 @@ class Service {
|
|
|
38
38
|
* @param root The file service root.
|
|
39
39
|
* @param options The file service options.
|
|
40
40
|
*/
|
|
41
|
-
constructor(root, options) {
|
|
41
|
+
constructor(root, options = {}) {
|
|
42
|
+
var _a;
|
|
42
43
|
this.root = path.unixify(path$1.resolve(root));
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
* @param path The path to check.
|
|
50
|
-
*/
|
|
51
|
-
async isIgnore(path) {
|
|
52
|
-
const { ignore } = this.options;
|
|
53
|
-
const isIgnored = type.isFunction(ignore) ? await ignore(path) : false;
|
|
54
|
-
return isIgnored === true;
|
|
44
|
+
const { ignore, highWaterMark = 65536 } = options;
|
|
45
|
+
this.options = Object.assign(Object.assign({}, options), {
|
|
46
|
+
fs: (_a = options.fs) !== null && _a !== void 0 ? _a : fs__default.default,
|
|
47
|
+
ignore: type.isFunction(ignore) ? ignore : () => false,
|
|
48
|
+
highWaterMark: type.isFunction(highWaterMark) ? highWaterMark : () => highWaterMark
|
|
49
|
+
});
|
|
55
50
|
}
|
|
56
51
|
/**
|
|
57
52
|
* @private
|
|
@@ -131,12 +126,12 @@ class Service {
|
|
|
131
126
|
if (path.isOutRoot(path$2, root)) {
|
|
132
127
|
return false;
|
|
133
128
|
}
|
|
129
|
+
// Get options.
|
|
130
|
+
const { options } = this;
|
|
134
131
|
// Is ignore path or file (403).
|
|
135
|
-
if (await
|
|
132
|
+
if (await options.ignore(path$2)) {
|
|
136
133
|
return false;
|
|
137
134
|
}
|
|
138
|
-
// Get options.
|
|
139
|
-
const { options } = this;
|
|
140
135
|
// File stats.
|
|
141
136
|
const stats = await fs$1.stat(options.fs, path$2);
|
|
142
137
|
// Check file stats.
|
|
@@ -193,7 +188,10 @@ class Service {
|
|
|
193
188
|
return context.throw(400);
|
|
194
189
|
}
|
|
195
190
|
// Set response body.
|
|
196
|
-
response.body = new ReadStream.ReadStream(path$2, ranges,
|
|
191
|
+
response.body = new ReadStream.ReadStream(path$2, ranges, {
|
|
192
|
+
fs: options.fs,
|
|
193
|
+
highWaterMark: await options.highWaterMark(path$2, stats)
|
|
194
|
+
});
|
|
197
195
|
// File found.
|
|
198
196
|
return true;
|
|
199
197
|
}
|
package/cjs/Service.d.cts
CHANGED
|
@@ -10,17 +10,20 @@ interface Headers {
|
|
|
10
10
|
interface IgnoreFunction {
|
|
11
11
|
(path: string): boolean | Promise<boolean>;
|
|
12
12
|
}
|
|
13
|
+
interface HighWaterMarkFunction {
|
|
14
|
+
(path: string, stats: Stats): Promise<number> | number;
|
|
15
|
+
}
|
|
13
16
|
interface HeadersFunction {
|
|
14
17
|
(path: string, stats: Stats): Promise<Headers | void> | Headers | void;
|
|
15
18
|
}
|
|
16
19
|
export interface Options {
|
|
17
|
-
fs?: FileSystem;
|
|
18
20
|
etag?: boolean;
|
|
21
|
+
fs?: FileSystem;
|
|
19
22
|
acceptRanges?: boolean;
|
|
20
23
|
lastModified?: boolean;
|
|
21
|
-
highWaterMark?: number;
|
|
22
24
|
ignore?: IgnoreFunction;
|
|
23
25
|
headers?: Headers | HeadersFunction;
|
|
26
|
+
highWaterMark?: number | HighWaterMarkFunction;
|
|
24
27
|
}
|
|
25
28
|
/**
|
|
26
29
|
* @class Service
|
|
@@ -35,13 +38,6 @@ export declare class Service {
|
|
|
35
38
|
* @param options The file service options.
|
|
36
39
|
*/
|
|
37
40
|
constructor(root: string, options?: Options);
|
|
38
|
-
/**
|
|
39
|
-
* @private
|
|
40
|
-
* @method isIgnore
|
|
41
|
-
* @description Check if path is ignore.
|
|
42
|
-
* @param path The path to check.
|
|
43
|
-
*/
|
|
44
|
-
private isIgnore;
|
|
45
41
|
/**
|
|
46
42
|
* @private
|
|
47
43
|
* @method setupHeaders
|
package/cjs/index.cjs
CHANGED
package/cjs/utils/fs.cjs
CHANGED
package/cjs/utils/hash.cjs
CHANGED
package/cjs/utils/http.cjs
CHANGED
package/cjs/utils/http.d.cts
CHANGED
|
@@ -34,4 +34,4 @@ export declare function isPreconditionFailed({ request, response }: Context): bo
|
|
|
34
34
|
* @param context The koa context.
|
|
35
35
|
* @param stats The file stats.
|
|
36
36
|
*/
|
|
37
|
-
export declare function parseRanges(context: Context, stats: Stats):
|
|
37
|
+
export declare function parseRanges(context: Context, stats: Stats): -1 | -2 | Range[];
|
package/cjs/utils/path.cjs
CHANGED
package/cjs/utils/type.cjs
CHANGED
package/esm/ReadStream.d.ts
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
* @module ReadStream
|
|
3
3
|
*/
|
|
4
4
|
import { PathLike } from 'fs';
|
|
5
|
+
import { Readable } from 'stream';
|
|
5
6
|
import { Range } from './utils/http.js';
|
|
6
7
|
import { FileSystem } from './utils/fs.js';
|
|
7
|
-
|
|
8
|
-
export interface Options extends Pick<ReadableOptions, 'highWaterMark'> {
|
|
8
|
+
export interface Options {
|
|
9
9
|
fs: FileSystem;
|
|
10
|
+
highWaterMark?: number;
|
|
10
11
|
}
|
|
11
12
|
interface Callback {
|
|
12
13
|
(error?: Error | null): void;
|
|
@@ -46,12 +47,12 @@ export declare class ReadStream extends Readable {
|
|
|
46
47
|
private getPadding;
|
|
47
48
|
/**
|
|
48
49
|
* @private
|
|
49
|
-
* @method
|
|
50
|
+
* @method readPadding
|
|
50
51
|
* @param fd The file descriptor.
|
|
51
52
|
* @param range The current range.
|
|
52
53
|
* @param size The number of bytes to read.
|
|
53
54
|
*/
|
|
54
|
-
private
|
|
55
|
+
private readPadding;
|
|
55
56
|
/**
|
|
56
57
|
* @private
|
|
57
58
|
* @method readFileRange
|
package/esm/ReadStream.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @package koa-files
|
|
3
3
|
* @license MIT
|
|
4
|
-
* @version 4.0
|
|
4
|
+
* @version 4.1.0
|
|
5
5
|
* @author nuintun <nuintun@qq.com>
|
|
6
6
|
* @description A static files serving middleware for koa.
|
|
7
7
|
* @see https://github.com/nuintun/koa-files#readme
|
|
@@ -68,20 +68,19 @@ class ReadStream extends Readable {
|
|
|
68
68
|
}
|
|
69
69
|
/**
|
|
70
70
|
* @private
|
|
71
|
-
* @method
|
|
71
|
+
* @method readPadding
|
|
72
72
|
* @param fd The file descriptor.
|
|
73
73
|
* @param range The current range.
|
|
74
74
|
* @param size The number of bytes to read.
|
|
75
75
|
*/
|
|
76
|
-
|
|
76
|
+
readPadding(fd, range, size) {
|
|
77
77
|
let bytesRead = 0;
|
|
78
78
|
const padding = this.getPadding(range);
|
|
79
|
-
const hasRangePadding = padding != null;
|
|
80
79
|
// If padding exists.
|
|
81
|
-
if (
|
|
80
|
+
if (padding != null) {
|
|
82
81
|
const { length } = padding;
|
|
83
82
|
const begin = this.bytesRead;
|
|
84
|
-
if (
|
|
83
|
+
if (begin < length) {
|
|
85
84
|
bytesRead = Math.min(size, length - begin);
|
|
86
85
|
const end = begin + bytesRead;
|
|
87
86
|
this.push(padding.subarray(begin, end));
|
|
@@ -89,14 +88,13 @@ class ReadStream extends Readable {
|
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
90
|
// If no padding or read completed.
|
|
92
|
-
if (bytesRead
|
|
91
|
+
if (bytesRead < size) {
|
|
93
92
|
this.bytesRead = 0;
|
|
94
|
-
const { readState } = this;
|
|
95
93
|
// Change read state.
|
|
96
|
-
switch (readState) {
|
|
94
|
+
switch (this.readState) {
|
|
97
95
|
case 0 /* ReadState.PREFIX */:
|
|
98
96
|
this.readState = 1 /* ReadState.RANGE */;
|
|
99
|
-
this.readFileRange(fd, range, size);
|
|
97
|
+
this.readFileRange(fd, range, size - bytesRead);
|
|
100
98
|
break;
|
|
101
99
|
case 2 /* ReadState.SUFFIX */:
|
|
102
100
|
this.currentRangeIndex++;
|
|
@@ -105,7 +103,7 @@ class ReadStream extends Readable {
|
|
|
105
103
|
if (nextRange == null) {
|
|
106
104
|
this.push(null);
|
|
107
105
|
} else {
|
|
108
|
-
this.
|
|
106
|
+
this.readPadding(fd, nextRange, size - bytesRead);
|
|
109
107
|
}
|
|
110
108
|
break;
|
|
111
109
|
}
|
|
@@ -119,39 +117,40 @@ class ReadStream extends Readable {
|
|
|
119
117
|
* @param size The number of bytes to read.
|
|
120
118
|
*/
|
|
121
119
|
readFileRange(fd, range, size) {
|
|
122
|
-
|
|
120
|
+
const { length } = range;
|
|
123
121
|
const { bytesRead } = this;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
122
|
+
// File range not finished.
|
|
123
|
+
if (bytesRead < length) {
|
|
124
|
+
this.reading = true;
|
|
125
|
+
const bytesToRead = Math.min(size, length - bytesRead);
|
|
126
|
+
const buffer = Buffer.allocUnsafeSlow(bytesToRead);
|
|
127
|
+
const position = range.offset + bytesRead;
|
|
128
|
+
// Read file range.
|
|
129
|
+
this.fs.read(fd, buffer, 0, bytesToRead, position, (readError, bytesRead, buffer) => {
|
|
130
|
+
this.reading = false;
|
|
131
|
+
// Tell ._destroy() that it's safe to close the fd now.
|
|
132
|
+
if (this.destroyed) {
|
|
133
|
+
this.emit(DISPOSE_EVENT, readError);
|
|
134
|
+
} else if (readError != null) {
|
|
134
135
|
this.destroy(readError);
|
|
136
|
+
} else if (bytesRead !== bytesToRead) {
|
|
137
|
+
this.destroy(new RangeError('invalid read operation'));
|
|
135
138
|
} else {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
// large backing buffer for small reads.
|
|
141
|
-
const chunk = Buffer.allocUnsafeSlow(bytesRead);
|
|
142
|
-
buffer.copy(chunk, 0, 0, bytesRead);
|
|
143
|
-
buffer = chunk;
|
|
144
|
-
}
|
|
145
|
-
this.push(buffer);
|
|
146
|
-
this.bytesRead += bytesRead;
|
|
147
|
-
} else {
|
|
139
|
+
this.push(buffer);
|
|
140
|
+
this.bytesRead += bytesRead;
|
|
141
|
+
// file range read completed.
|
|
142
|
+
if (bytesRead < size) {
|
|
148
143
|
this.bytesRead = 0;
|
|
149
144
|
this.readState = 2 /* ReadState.SUFFIX */;
|
|
150
|
-
this.
|
|
145
|
+
this.readPadding(fd, range, size - bytesRead);
|
|
151
146
|
}
|
|
152
147
|
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
148
|
+
});
|
|
149
|
+
} else {
|
|
150
|
+
this.bytesRead = 0;
|
|
151
|
+
this.readState = 2 /* ReadState.SUFFIX */;
|
|
152
|
+
this.readPadding(fd, range, size);
|
|
153
|
+
}
|
|
155
154
|
}
|
|
156
155
|
/**
|
|
157
156
|
* @override
|
|
@@ -166,12 +165,11 @@ class ReadStream extends Readable {
|
|
|
166
165
|
if (fd == null || range == null) {
|
|
167
166
|
this.push(null);
|
|
168
167
|
} else {
|
|
169
|
-
const { readState } = this;
|
|
170
168
|
// Read bytes from range.
|
|
171
|
-
switch (readState) {
|
|
169
|
+
switch (this.readState) {
|
|
172
170
|
case 0 /* ReadState.PREFIX */:
|
|
173
171
|
case 2 /* ReadState.SUFFIX */:
|
|
174
|
-
this.
|
|
172
|
+
this.readPadding(fd, range, size);
|
|
175
173
|
break;
|
|
176
174
|
case 1 /* ReadState.RANGE */:
|
|
177
175
|
this.readFileRange(fd, range, size);
|
package/esm/Service.d.ts
CHANGED
|
@@ -10,17 +10,20 @@ interface Headers {
|
|
|
10
10
|
interface IgnoreFunction {
|
|
11
11
|
(path: string): boolean | Promise<boolean>;
|
|
12
12
|
}
|
|
13
|
+
interface HighWaterMarkFunction {
|
|
14
|
+
(path: string, stats: Stats): Promise<number> | number;
|
|
15
|
+
}
|
|
13
16
|
interface HeadersFunction {
|
|
14
17
|
(path: string, stats: Stats): Promise<Headers | void> | Headers | void;
|
|
15
18
|
}
|
|
16
19
|
export interface Options {
|
|
17
|
-
fs?: FileSystem;
|
|
18
20
|
etag?: boolean;
|
|
21
|
+
fs?: FileSystem;
|
|
19
22
|
acceptRanges?: boolean;
|
|
20
23
|
lastModified?: boolean;
|
|
21
|
-
highWaterMark?: number;
|
|
22
24
|
ignore?: IgnoreFunction;
|
|
23
25
|
headers?: Headers | HeadersFunction;
|
|
26
|
+
highWaterMark?: number | HighWaterMarkFunction;
|
|
24
27
|
}
|
|
25
28
|
/**
|
|
26
29
|
* @class Service
|
|
@@ -35,13 +38,6 @@ export declare class Service {
|
|
|
35
38
|
* @param options The file service options.
|
|
36
39
|
*/
|
|
37
40
|
constructor(root: string, options?: Options);
|
|
38
|
-
/**
|
|
39
|
-
* @private
|
|
40
|
-
* @method isIgnore
|
|
41
|
-
* @description Check if path is ignore.
|
|
42
|
-
* @param path The path to check.
|
|
43
|
-
*/
|
|
44
|
-
private isIgnore;
|
|
45
41
|
/**
|
|
46
42
|
* @private
|
|
47
43
|
* @method setupHeaders
|
package/esm/Service.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @package koa-files
|
|
3
3
|
* @license MIT
|
|
4
|
-
* @version 4.0
|
|
4
|
+
* @version 4.1.0
|
|
5
5
|
* @author nuintun <nuintun@qq.com>
|
|
6
6
|
* @description A static files serving middleware for koa.
|
|
7
7
|
* @see https://github.com/nuintun/koa-files#readme
|
|
@@ -29,20 +29,15 @@ class Service {
|
|
|
29
29
|
* @param root The file service root.
|
|
30
30
|
* @param options The file service options.
|
|
31
31
|
*/
|
|
32
|
-
constructor(root, options) {
|
|
32
|
+
constructor(root, options = {}) {
|
|
33
|
+
var _a;
|
|
33
34
|
this.root = unixify(resolve(root));
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
* @param path The path to check.
|
|
41
|
-
*/
|
|
42
|
-
async isIgnore(path) {
|
|
43
|
-
const { ignore } = this.options;
|
|
44
|
-
const isIgnored = isFunction(ignore) ? await ignore(path) : false;
|
|
45
|
-
return isIgnored === true;
|
|
35
|
+
const { ignore, highWaterMark = 65536 } = options;
|
|
36
|
+
this.options = Object.assign(Object.assign({}, options), {
|
|
37
|
+
fs: (_a = options.fs) !== null && _a !== void 0 ? _a : fs,
|
|
38
|
+
ignore: isFunction(ignore) ? ignore : () => false,
|
|
39
|
+
highWaterMark: isFunction(highWaterMark) ? highWaterMark : () => highWaterMark
|
|
40
|
+
});
|
|
46
41
|
}
|
|
47
42
|
/**
|
|
48
43
|
* @private
|
|
@@ -122,12 +117,12 @@ class Service {
|
|
|
122
117
|
if (isOutRoot(path, root)) {
|
|
123
118
|
return false;
|
|
124
119
|
}
|
|
120
|
+
// Get options.
|
|
121
|
+
const { options } = this;
|
|
125
122
|
// Is ignore path or file (403).
|
|
126
|
-
if (await
|
|
123
|
+
if (await options.ignore(path)) {
|
|
127
124
|
return false;
|
|
128
125
|
}
|
|
129
|
-
// Get options.
|
|
130
|
-
const { options } = this;
|
|
131
126
|
// File stats.
|
|
132
127
|
const stats = await stat(options.fs, path);
|
|
133
128
|
// Check file stats.
|
|
@@ -184,7 +179,10 @@ class Service {
|
|
|
184
179
|
return context.throw(400);
|
|
185
180
|
}
|
|
186
181
|
// Set response body.
|
|
187
|
-
response.body = new ReadStream(path, ranges,
|
|
182
|
+
response.body = new ReadStream(path, ranges, {
|
|
183
|
+
fs: options.fs,
|
|
184
|
+
highWaterMark: await options.highWaterMark(path, stats)
|
|
185
|
+
});
|
|
188
186
|
// File found.
|
|
189
187
|
return true;
|
|
190
188
|
}
|
package/esm/index.js
CHANGED
package/esm/utils/fs.js
CHANGED
package/esm/utils/hash.js
CHANGED
package/esm/utils/http.d.ts
CHANGED
|
@@ -34,4 +34,4 @@ export declare function isPreconditionFailed({ request, response }: Context): bo
|
|
|
34
34
|
* @param context The koa context.
|
|
35
35
|
* @param stats The file stats.
|
|
36
36
|
*/
|
|
37
|
-
export declare function parseRanges(context: Context, stats: Stats):
|
|
37
|
+
export declare function parseRanges(context: Context, stats: Stats): -1 | -2 | Range[];
|
package/esm/utils/http.js
CHANGED
package/esm/utils/path.js
CHANGED
package/esm/utils/type.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koa-files",
|
|
3
|
-
"version": "4.0
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "A static files serving middleware for koa.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "cjs/index.cjs",
|
|
@@ -48,17 +48,17 @@
|
|
|
48
48
|
"tslib": "^2.8.1"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@rollup/plugin-typescript": "^12.1.
|
|
51
|
+
"@rollup/plugin-typescript": "^12.1.4",
|
|
52
52
|
"@types/etag": "^1.8.4",
|
|
53
53
|
"@types/koa": "^2.15.0",
|
|
54
|
-
"@types/node": "^24.0
|
|
54
|
+
"@types/node": "^24.1.0",
|
|
55
55
|
"@types/range-parser": "^1.2.7",
|
|
56
|
-
"dts-paths": "^1.1.
|
|
57
|
-
"koa": "^3.0.
|
|
56
|
+
"dts-paths": "^1.1.10",
|
|
57
|
+
"koa": "^3.0.1",
|
|
58
58
|
"magic-string": "^0.30.17",
|
|
59
|
-
"prettier": "^3.
|
|
59
|
+
"prettier": "^3.6.2",
|
|
60
60
|
"rimraf": "^6.0.1",
|
|
61
|
-
"rollup": "^4.
|
|
61
|
+
"rollup": "^4.46.1",
|
|
62
62
|
"typescript": "^5.8.3"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
@@ -71,8 +71,8 @@
|
|
|
71
71
|
"build:cjs": "rollup -c tools/rollup.cjs.js",
|
|
72
72
|
"build:esm": "rollup -c tools/rollup.esm.js",
|
|
73
73
|
"build:fix-types": "node tools/fix-types.js",
|
|
74
|
+
"build": "pnpm clean && pnpm build:main && pnpm format",
|
|
74
75
|
"format": "prettier --write . --ignore-path .prettierignore",
|
|
75
|
-
"build": "
|
|
76
|
-
"build:main": "npm run build:cjs && npm run build:esm && npm run build:fix-types"
|
|
76
|
+
"build:main": "pnpm build:cjs && pnpm build:esm && pnpm build:fix-types"
|
|
77
77
|
}
|
|
78
78
|
}
|