@fastify/static 8.0.3 → 8.0.4
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 +25 -16
- package/eslint.config.js +1 -0
- package/index.js +2 -2
- package/package.json +36 -7
- package/test/content-type.test.js +97 -127
- package/test/dir-list.test.js +264 -369
- package/test/static.test.js +1753 -2363
- package/types/index.d.ts +1 -1
- package/types/index.test-d.ts +20 -20
- package/.eslintrc.json +0 -31
- package/.taprc +0 -2
package/README.md
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
# @fastify/static
|
|
2
2
|
|
|
3
|
-
](https://github.com/fastify/fastify-static/actions/workflows/ci.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/@fastify/static)
|
|
5
|
-
[](https://github.com/neostandard/neostandard)
|
|
6
6
|
|
|
7
|
-
Plugin for serving static files as fast as possible.
|
|
8
|
-
|
|
9
|
-
| Fastify version | branch |
|
|
10
|
-
| --------------- | -------------------------------------------------------------------- |
|
|
11
|
-
| `^4.x` | This branch |
|
|
12
|
-
| `^3.x` | [`v5.x`](https://github.com/fastify/fastify-static/tree/v5.x) |
|
|
13
|
-
| `^2.x` | [`2.x`](https://github.com/fastify/fastify-static/tree/2.x) |
|
|
14
|
-
| `^1.11.x` | [`1.x`](https://github.com/fastify/fastify-static/tree/1.x) |
|
|
7
|
+
Plugin for serving static files as fast as possible.
|
|
15
8
|
|
|
16
9
|
## Install
|
|
10
|
+
```
|
|
11
|
+
npm i @fastify/static
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Compatibility
|
|
15
|
+
|
|
16
|
+
| Plugin version | Fastify version |
|
|
17
|
+
| ---------------|-----------------|
|
|
18
|
+
| `^8.x` | `^5.x` |
|
|
19
|
+
| `^7.x` | `^4.x` |
|
|
20
|
+
| `^5.x` | `^3.x` |
|
|
21
|
+
| `^2.x` | `^2.x` |
|
|
22
|
+
| `^1.x` | `^1.x` |
|
|
23
|
+
|
|
17
24
|
|
|
18
|
-
|
|
25
|
+
Please note that if a Fastify version is out of support, then so are the corresponding versions of this plugin
|
|
26
|
+
in the table above.
|
|
27
|
+
See [Fastify's LTS policy](https://github.com/fastify/fastify/blob/main/docs/Reference/LTS.md) for more details.
|
|
19
28
|
|
|
20
29
|
## Usage
|
|
21
30
|
|
|
@@ -136,7 +145,7 @@ If set to false prefix will get trailing "/" at the end. If set to true, prefix
|
|
|
136
145
|
|
|
137
146
|
Default: `true`
|
|
138
147
|
|
|
139
|
-
A flag that
|
|
148
|
+
A flag that defines if the fastify route hide-schema attribute is hidden or not
|
|
140
149
|
|
|
141
150
|
#### `setHeaders`
|
|
142
151
|
|
|
@@ -207,7 +216,7 @@ If the function returns `false`, Fastify's 404 handler will be called.
|
|
|
207
216
|
|
|
208
217
|
Default: `undefined`
|
|
209
218
|
|
|
210
|
-
Under the hood we use [send](https://
|
|
219
|
+
Under the hood we use [`@fastify/send`](https://www.npmjs.com/package/@fastify/send) lib that by default supports "index.html" files.
|
|
211
220
|
To disable this set false or to supply a new index pass a string or an array in preferred order.
|
|
212
221
|
|
|
213
222
|
#### `serveDotFiles`
|
|
@@ -422,7 +431,7 @@ This option determines the output format when `json` is selected.
|
|
|
422
431
|
|
|
423
432
|
Default: `false`
|
|
424
433
|
|
|
425
|
-
Try to send the brotli encoded asset first (when supported within the `Accept-Encoding` headers), retry for gzip, then
|
|
434
|
+
Try to send the brotli encoded asset first (when supported within the `Accept-Encoding` headers), retry for gzip, and then fall back to the original `pathname`. You may choose to skip compression for smaller files that do not benefit from it.
|
|
426
435
|
|
|
427
436
|
Assume this structure with the compressed asset as a sibling of the un-compressed counterpart:
|
|
428
437
|
|
|
@@ -453,7 +462,7 @@ If a request matches the URL `prefix` but a file cannot be found for the
|
|
|
453
462
|
request, Fastify's 404 handler will be called. You can set a custom 404
|
|
454
463
|
handler with [`fastify.setNotFoundHandler()`](https://fastify.dev/docs/latest/Reference/Server/#setnotfoundhandler).
|
|
455
464
|
|
|
456
|
-
When registering `@fastify/static` within an encapsulated context, the `wildcard` option may need to be set to `false`
|
|
465
|
+
When registering `@fastify/static` within an encapsulated context, the `wildcard` option may need to be set to `false` to support index resolution and nested not-found-handler:
|
|
457
466
|
|
|
458
467
|
```js
|
|
459
468
|
const app = require('fastify')();
|
|
@@ -491,4 +500,4 @@ fastify.addHook('onSend', function (req, reply, payload, next) {
|
|
|
491
500
|
|
|
492
501
|
## License
|
|
493
502
|
|
|
494
|
-
Licensed under [MIT](./LICENSE)
|
|
503
|
+
Licensed under [MIT](./LICENSE).
|
package/eslint.config.js
CHANGED
package/index.js
CHANGED
|
@@ -77,7 +77,7 @@ async function fastifyStatic (fastify, opts) {
|
|
|
77
77
|
if (opts.decorateReply !== false) {
|
|
78
78
|
fastify.decorateReply('sendFile', function (filePath, rootPath, options) {
|
|
79
79
|
const opts = typeof rootPath === 'object' ? rootPath : options
|
|
80
|
-
const root = typeof rootPath === 'string' ? rootPath : opts
|
|
80
|
+
const root = typeof rootPath === 'string' ? rootPath : opts?.root
|
|
81
81
|
pumpSendToReply(
|
|
82
82
|
this.request,
|
|
83
83
|
this,
|
|
@@ -443,7 +443,7 @@ function checkRootPathForErrors (fastify, rootPath) {
|
|
|
443
443
|
|
|
444
444
|
function checkPath (fastify, rootPath) {
|
|
445
445
|
if (typeof rootPath !== 'string') {
|
|
446
|
-
throw new
|
|
446
|
+
throw new TypeError('"root" option must be a string')
|
|
447
447
|
}
|
|
448
448
|
if (path.isAbsolute(rootPath) === false) {
|
|
449
449
|
throw new Error('"root" option must be an absolute path')
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fastify/static",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.4",
|
|
4
4
|
"description": "Plugin for serving static files as fast as possible.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"types": "types/index.d.ts",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"coverage": "
|
|
9
|
+
"coverage": "c8 --reporter html borp --coverage --check-coverage --lines 100",
|
|
10
10
|
"lint": "eslint",
|
|
11
11
|
"lint:fix": "eslint --fix",
|
|
12
12
|
"test": "npm run test:unit && npm run test:typescript",
|
|
13
13
|
"test:typescript": "tsd",
|
|
14
|
-
"test:unit": "
|
|
14
|
+
"test:unit": "borp -C --check-coverage --lines 100",
|
|
15
15
|
"example": "node example/server.js"
|
|
16
16
|
},
|
|
17
17
|
"repository": {
|
|
@@ -23,11 +23,40 @@
|
|
|
23
23
|
"static"
|
|
24
24
|
],
|
|
25
25
|
"author": "Tommaso Allevi - @allevo",
|
|
26
|
+
"contributors": [
|
|
27
|
+
{
|
|
28
|
+
"name": "Matteo Collina",
|
|
29
|
+
"email": "hello@matteocollina.com"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "Manuel Spigolon",
|
|
33
|
+
"email": "behemoth89@gmail.com"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "Aras Abbasi",
|
|
37
|
+
"email": "aras.abbasi@gmail.com"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "Frazer Smith",
|
|
41
|
+
"email": "frazer.dev@icloud.com",
|
|
42
|
+
"url": "https://github.com/fdawgs"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
26
45
|
"license": "MIT",
|
|
27
46
|
"bugs": {
|
|
28
47
|
"url": "https://github.com/fastify/fastify-static/issues"
|
|
29
48
|
},
|
|
30
49
|
"homepage": "https://github.com/fastify/fastify-static",
|
|
50
|
+
"funding": [
|
|
51
|
+
{
|
|
52
|
+
"type": "github",
|
|
53
|
+
"url": "https://github.com/sponsors/fastify"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"type": "opencollective",
|
|
57
|
+
"url": "https://opencollective.com/fastify"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
31
60
|
"dependencies": {
|
|
32
61
|
"@fastify/accept-negotiator": "^2.0.0",
|
|
33
62
|
"@fastify/send": "^3.2.0",
|
|
@@ -40,14 +69,14 @@
|
|
|
40
69
|
"@fastify/compress": "^8.0.0",
|
|
41
70
|
"@fastify/pre-commit": "^2.1.0",
|
|
42
71
|
"@types/node": "^22.0.0",
|
|
72
|
+
"borp": "^0.19.0",
|
|
73
|
+
"c8": "^10.1.3",
|
|
43
74
|
"concat-stream": "^2.0.0",
|
|
44
|
-
"eslint": "^9.
|
|
75
|
+
"eslint": "^9.17.0",
|
|
45
76
|
"fastify": "^5.1.0",
|
|
46
|
-
"neostandard": "^0.
|
|
77
|
+
"neostandard": "^0.12.0",
|
|
47
78
|
"pino": "^9.1.0",
|
|
48
79
|
"proxyquire": "^2.1.3",
|
|
49
|
-
"simple-get": "^4.0.1",
|
|
50
|
-
"tap": "^18.7.1",
|
|
51
80
|
"tsd": "^0.31.0"
|
|
52
81
|
},
|
|
53
82
|
"tsd": {
|
|
@@ -3,14 +3,13 @@
|
|
|
3
3
|
/* eslint n/no-deprecated-api: "off" */
|
|
4
4
|
|
|
5
5
|
const path = require('node:path')
|
|
6
|
-
const { test } = require('
|
|
7
|
-
const simple = require('simple-get')
|
|
6
|
+
const { test } = require('node:test')
|
|
8
7
|
const Fastify = require('fastify')
|
|
9
8
|
|
|
10
9
|
const fastifyStatic = require('../')
|
|
11
10
|
|
|
12
|
-
test('register /content-type', t => {
|
|
13
|
-
t.plan(
|
|
11
|
+
test('register /content-type', async t => {
|
|
12
|
+
t.plan(5)
|
|
14
13
|
|
|
15
14
|
const pluginOptions = {
|
|
16
15
|
root: path.join(__dirname, '/content-type'),
|
|
@@ -19,72 +18,55 @@ test('register /content-type', t => {
|
|
|
19
18
|
const fastify = Fastify()
|
|
20
19
|
fastify.register(fastifyStatic, pluginOptions)
|
|
21
20
|
|
|
22
|
-
t.
|
|
21
|
+
t.after(() => fastify.close())
|
|
23
22
|
|
|
24
|
-
fastify.listen({ port: 0 }
|
|
25
|
-
t.error(err)
|
|
23
|
+
await fastify.listen({ port: 0 })
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
fastify.server.unref()
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
simple.concat({
|
|
32
|
-
method: 'GET',
|
|
33
|
-
url: 'http://localhost:' + fastify.server.address().port + '/content-type/index.html'
|
|
34
|
-
}, (err, response) => {
|
|
35
|
-
t.error(err)
|
|
36
|
-
t.equal(response.headers['content-type'], 'text/html; charset=utf-8')
|
|
37
|
-
})
|
|
38
|
-
})
|
|
27
|
+
await t.test('/content-type/index.html', async (t) => {
|
|
28
|
+
t.plan(2)
|
|
39
29
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
url: 'http://localhost:' + fastify.server.address().port + '/content-type/index.css'
|
|
45
|
-
}, (err, response) => {
|
|
46
|
-
t.error(err)
|
|
47
|
-
t.equal(response.headers['content-type'], 'text/css; charset=utf-8')
|
|
48
|
-
})
|
|
49
|
-
})
|
|
30
|
+
const response = await fetch('http://localhost:' + fastify.server.address().port + '/content-type/index.html')
|
|
31
|
+
t.assert.ok(response.ok)
|
|
32
|
+
t.assert.deepStrictEqual(response.headers.get('content-type'), 'text/html; charset=utf-8')
|
|
33
|
+
})
|
|
50
34
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
simple.concat({
|
|
54
|
-
method: 'GET',
|
|
55
|
-
url: 'http://localhost:' + fastify.server.address().port + '/content-type/sample.jpg'
|
|
56
|
-
}, (err, response) => {
|
|
57
|
-
t.error(err)
|
|
58
|
-
t.equal(response.headers['content-type'], 'image/jpeg')
|
|
59
|
-
})
|
|
60
|
-
})
|
|
35
|
+
await t.test('/content-type/index.css', async (t) => {
|
|
36
|
+
t.plan(2)
|
|
61
37
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
url: 'http://localhost:' + fastify.server.address().port + '/content-type/test.txt'
|
|
67
|
-
}, (err, response) => {
|
|
68
|
-
t.error(err)
|
|
69
|
-
t.equal(response.headers['content-type'], 'text/plain; charset=utf-8')
|
|
70
|
-
})
|
|
71
|
-
})
|
|
38
|
+
const response = await fetch('http://localhost:' + fastify.server.address().port + '/content-type/index.css')
|
|
39
|
+
t.assert.ok(response.ok)
|
|
40
|
+
t.assert.deepStrictEqual(response.headers.get('content-type'), 'text/css; charset=utf-8')
|
|
41
|
+
})
|
|
72
42
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
43
|
+
await t.test('/content-type/sample.jpg', async (t) => {
|
|
44
|
+
t.plan(2)
|
|
45
|
+
|
|
46
|
+
const response = await fetch('http://localhost:' + fastify.server.address().port + '/content-type/sample.jpg')
|
|
47
|
+
t.assert.ok(response.ok)
|
|
48
|
+
t.assert.deepStrictEqual(response.headers.get('content-type'), 'image/jpeg')
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
await t.test('/content-type/test.txt', async (t) => {
|
|
52
|
+
t.plan(2)
|
|
53
|
+
|
|
54
|
+
const response = await fetch('http://localhost:' + fastify.server.address().port + '/content-type/test.txt')
|
|
55
|
+
t.assert.ok(response.ok)
|
|
56
|
+
t.assert.deepStrictEqual(response.headers.get('content-type'), 'text/plain; charset=utf-8')
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
await t.test('/content-type/binary', async (t) => {
|
|
60
|
+
t.plan(2)
|
|
61
|
+
|
|
62
|
+
const response = await fetch('http://localhost:' + fastify.server.address().port + '/content-type/binary')
|
|
63
|
+
t.assert.ok(response.ok)
|
|
64
|
+
t.assert.deepStrictEqual(response.headers.get('content-type'), 'application/octet-stream')
|
|
83
65
|
})
|
|
84
66
|
})
|
|
85
67
|
|
|
86
|
-
test('register /content-type preCompressed', t => {
|
|
87
|
-
t.plan(
|
|
68
|
+
test('register /content-type preCompressed', async t => {
|
|
69
|
+
t.plan(5)
|
|
88
70
|
|
|
89
71
|
const pluginOptions = {
|
|
90
72
|
root: path.join(__dirname, '/content-type'),
|
|
@@ -94,81 +76,69 @@ test('register /content-type preCompressed', t => {
|
|
|
94
76
|
const fastify = Fastify()
|
|
95
77
|
fastify.register(fastifyStatic, pluginOptions)
|
|
96
78
|
|
|
97
|
-
t.
|
|
98
|
-
|
|
99
|
-
fastify.listen({ port: 0 }
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
t.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
'accept-encoding': 'gzip, deflate, br'
|
|
111
|
-
}
|
|
112
|
-
}, (err, response) => {
|
|
113
|
-
t.error(err)
|
|
114
|
-
t.equal(response.headers['content-type'], 'text/html; charset=utf-8')
|
|
115
|
-
})
|
|
79
|
+
t.after(() => fastify.close())
|
|
80
|
+
|
|
81
|
+
await fastify.listen({ port: 0 })
|
|
82
|
+
|
|
83
|
+
fastify.server.unref()
|
|
84
|
+
|
|
85
|
+
await t.test('/content-type/index.html', async (t) => {
|
|
86
|
+
t.plan(2)
|
|
87
|
+
|
|
88
|
+
const response = await fetch('http://localhost:' + fastify.server.address().port + '/content-type/index.html', {
|
|
89
|
+
headers: {
|
|
90
|
+
'accept-encoding': 'gzip, deflate, br'
|
|
91
|
+
}
|
|
116
92
|
})
|
|
93
|
+
t.assert.ok(response.ok)
|
|
94
|
+
t.assert.deepStrictEqual(response.headers.get('content-type'), 'text/html; charset=utf-8')
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
await t.test('/content-type/index.css', async (t) => {
|
|
98
|
+
t.plan(2)
|
|
117
99
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
url: 'http://localhost:' + fastify.server.address().port + '/content-type/index.css',
|
|
123
|
-
headers: {
|
|
124
|
-
'accept-encoding': 'gzip, deflate, br'
|
|
125
|
-
}
|
|
126
|
-
}, (err, response) => {
|
|
127
|
-
t.error(err)
|
|
128
|
-
t.equal(response.headers['content-type'], 'text/css; charset=utf-8')
|
|
129
|
-
})
|
|
100
|
+
const response = await fetch('http://localhost:' + fastify.server.address().port + '/content-type/index.css', {
|
|
101
|
+
headers: {
|
|
102
|
+
'accept-encoding': 'gzip, deflate, br'
|
|
103
|
+
}
|
|
130
104
|
})
|
|
105
|
+
t.assert.ok(response.ok)
|
|
106
|
+
t.assert.deepStrictEqual(response.headers.get('content-type'), 'text/css; charset=utf-8')
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
await t.test('/content-type/sample.jpg', async (t) => {
|
|
110
|
+
t.plan(2)
|
|
131
111
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
url: 'http://localhost:' + fastify.server.address().port + '/content-type/sample.jpg',
|
|
137
|
-
headers: {
|
|
138
|
-
'accept-encoding': 'gzip, deflate, br'
|
|
139
|
-
}
|
|
140
|
-
}, (err, response) => {
|
|
141
|
-
t.error(err)
|
|
142
|
-
t.equal(response.headers['content-type'], 'image/jpeg')
|
|
143
|
-
})
|
|
112
|
+
const response = await fetch('http://localhost:' + fastify.server.address().port + '/content-type/sample.jpg', {
|
|
113
|
+
headers: {
|
|
114
|
+
'accept-encoding': 'gzip, deflate, br'
|
|
115
|
+
}
|
|
144
116
|
})
|
|
117
|
+
t.assert.ok(response.ok)
|
|
118
|
+
t.assert.deepStrictEqual(response.headers.get('content-type'), 'image/jpeg')
|
|
119
|
+
})
|
|
145
120
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
}, (err, response) => {
|
|
155
|
-
t.error(err)
|
|
156
|
-
t.equal(response.headers['content-type'], 'text/plain; charset=utf-8')
|
|
157
|
-
})
|
|
121
|
+
await t.test('/content-type/test.txt', async (t) => {
|
|
122
|
+
t.plan(2)
|
|
123
|
+
|
|
124
|
+
const response = await fetch('http://localhost:' + fastify.server.address().port + '/content-type/test.txt', {
|
|
125
|
+
headers: {
|
|
126
|
+
'accept-encoding': 'gzip, deflate, br'
|
|
127
|
+
}
|
|
158
128
|
})
|
|
129
|
+
t.assert.ok(response.ok)
|
|
130
|
+
t.assert.deepStrictEqual(response.headers.get('content-type'), 'text/plain; charset=utf-8')
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
await t.test('/content-type/binary', async (t) => {
|
|
134
|
+
t.plan(2)
|
|
159
135
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
url: 'http://localhost:' + fastify.server.address().port + '/content-type/binary',
|
|
165
|
-
headers: {
|
|
166
|
-
'accept-encoding': 'gzip, deflate, br'
|
|
167
|
-
}
|
|
168
|
-
}, (err, response) => {
|
|
169
|
-
t.error(err)
|
|
170
|
-
t.equal(response.headers['content-type'], 'application/octet-stream')
|
|
171
|
-
})
|
|
136
|
+
const response = await fetch('http://localhost:' + fastify.server.address().port + '/content-type/binary', {
|
|
137
|
+
headers: {
|
|
138
|
+
'accept-encoding': 'gzip, deflate, br'
|
|
139
|
+
}
|
|
172
140
|
})
|
|
141
|
+
t.assert.ok(response.ok)
|
|
142
|
+
t.assert.deepStrictEqual(response.headers.get('content-type'), 'application/octet-stream')
|
|
173
143
|
})
|
|
174
144
|
})
|