@fastify/static 8.0.2 → 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.
@@ -17,7 +17,7 @@ on:
17
17
 
18
18
  jobs:
19
19
  test:
20
- uses: fastify/workflows/.github/workflows/plugins-ci.yml@v5.0.0
20
+ uses: fastify/workflows/.github/workflows/plugins-ci.yml@v5
21
21
  with:
22
22
  license-check: true
23
23
  lint: true
package/README.md CHANGED
@@ -1,21 +1,30 @@
1
1
  # @fastify/static
2
2
 
3
- ![CI](https://github.com/fastify/fastify-static/workflows/CI/badge.svg)
3
+ [![CI](https://github.com/fastify/fastify-static/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/fastify/fastify-static/actions/workflows/ci.yml)
4
4
  [![NPM version](https://img.shields.io/npm/v/@fastify/static.svg?style=flat)](https://www.npmjs.com/package/@fastify/static)
5
- [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)
5
+ [![neostandard javascript style](https://img.shields.io/badge/code_style-neostandard-brightgreen?style=flat)](https://github.com/neostandard/neostandard)
6
6
 
7
- Plugin for serving static files as fast as possible. Supports Fastify version `4.x`.
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
- `npm i @fastify/static`
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 define if the fastify route hide-schema attribute is hidden or not
148
+ A flag that defines if the fastify route hide-schema attribute is hidden or not
140
149
 
141
150
  #### `setHeaders`
142
151
 
@@ -153,17 +162,18 @@ where the arguments are:
153
162
  #### `send` Options
154
163
 
155
164
  The following options are also supported and will be passed directly to the
156
- [`send`](https://www.npmjs.com/package/send) module:
157
-
158
- - [`acceptRanges`](https://www.npmjs.com/package/send#acceptranges)
159
- - [`cacheControl`](https://www.npmjs.com/package/send#cachecontrol)
160
- - [`dotfiles`](https://www.npmjs.com/package/send#dotfiles)
161
- - [`etag`](https://www.npmjs.com/package/send#etag)
162
- - [`extensions`](https://www.npmjs.com/package/send#extensions)
163
- - [`immutable`](https://www.npmjs.com/package/send#immutable)
164
- - [`index`](https://www.npmjs.com/package/send#index)
165
- - [`lastModified`](https://www.npmjs.com/package/send#lastmodified)
166
- - [`maxAge`](https://www.npmjs.com/package/send#maxage)
165
+ [`@fastify/send`](https://www.npmjs.com/package/@fastify/send) module:
166
+
167
+ - [`acceptRanges`](https://www.npmjs.com/package/@fastify/send#acceptranges)
168
+ - [`contentType`](https://www.npmjs.com/package/@fastify/send#contenttype)
169
+ - [`cacheControl`](https://www.npmjs.com/package/@fastify/send#cachecontrol) (Enable or disable setting Cache-Control response header, defaults to true. **Important:** If you want to provide a custom Cache-Control response header, this option must be false.)
170
+ - [`dotfiles`](https://www.npmjs.com/package/@fastify/send#dotfiles)
171
+ - [`etag`](https://www.npmjs.com/package/@fastify/send#etag)
172
+ - [`extensions`](https://www.npmjs.com/package/@fastify/send#extensions)
173
+ - [`immutable`](https://www.npmjs.com/package/@fastify/send#immutable)
174
+ - [`index`](https://www.npmjs.com/package/@fastify/send#index)
175
+ - [`lastModified`](https://www.npmjs.com/package/@fastify/send#lastmodified)
176
+ - [`maxAge`](https://www.npmjs.com/package/@fastify/send#maxage)
167
177
 
168
178
  You're able to alter this options when calling `reply.download('filename.html', options)` or `reply.download('filename.html', 'otherfilename.html', options)` on each response to a request.
169
179
 
@@ -198,7 +208,7 @@ with `ignoreTrailingSlash` set to `true`.
198
208
 
199
209
  Default: `(pathName, root, request) => true`
200
210
 
201
- This function allows filtering the served files. Also, with the help of the request object a more complex path authentication is possible.
211
+ This function allows filtering the served files. Also, with the help of the request object a more complex path authentication is possible.
202
212
  If the function returns `true`, the file will be served.
203
213
  If the function returns `false`, Fastify's 404 handler will be called.
204
214
 
@@ -206,7 +216,7 @@ If the function returns `false`, Fastify's 404 handler will be called.
206
216
 
207
217
  Default: `undefined`
208
218
 
209
- Under the hood we use [send](https://github.com/pillarjs/send#index) lib that by default supports "index.html" files.
219
+ Under the hood we use [`@fastify/send`](https://www.npmjs.com/package/@fastify/send) lib that by default supports "index.html" files.
210
220
  To disable this set false or to supply a new index pass a string or an array in preferred order.
211
221
 
212
222
  #### `serveDotFiles`
@@ -421,7 +431,7 @@ This option determines the output format when `json` is selected.
421
431
 
422
432
  Default: `false`
423
433
 
424
- Try to send the brotli encoded asset first (when supported within the `Accept-Encoding` headers), retry for gzip, then the fall back to the original `pathname`. You may choose to skip compression for smaller files that don't benefit from it.
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.
425
435
 
426
436
  Assume this structure with the compressed asset as a sibling of the un-compressed counterpart:
427
437
 
@@ -452,7 +462,7 @@ If a request matches the URL `prefix` but a file cannot be found for the
452
462
  request, Fastify's 404 handler will be called. You can set a custom 404
453
463
  handler with [`fastify.setNotFoundHandler()`](https://fastify.dev/docs/latest/Reference/Server/#setnotfoundhandler).
454
464
 
455
- When registering `@fastify/static` within an encapsulated context, the `wildcard` option may need to be set to `false` in order to support index resolution and nested not-found-handler:
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:
456
466
 
457
467
  ```js
458
468
  const app = require('fastify')();
@@ -469,7 +479,7 @@ app.register((childContext, _, done) => {
469
479
  }, { prefix: 'docs' });
470
480
  ```
471
481
 
472
- This code will send the `index.html` for the paths `docs`, `docs/`, and `docs/index.html`. For all other `docs/<undefined-routes>` it will reply with `404.html`.
482
+ This code will send the `index.html` for the paths `docs`, `docs/`, and `docs/index.html`. For all other `docs/<undefined-routes>` it will reply with `404.html`.
473
483
 
474
484
  ### Handling Errors
475
485
 
@@ -490,4 +500,4 @@ fastify.addHook('onSend', function (req, reply, payload, next) {
490
500
 
491
501
  ## License
492
502
 
493
- Licensed under [MIT](./LICENSE)
503
+ Licensed under [MIT](./LICENSE).
package/eslint.config.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  module.exports = require('neostandard')({
4
+ ignores: require('neostandard').resolveIgnoresFromGitignore(),
4
5
  noJsx: true,
5
6
  ts: true,
6
7
  })
package/index.js CHANGED
@@ -38,6 +38,7 @@ async function fastifyStatic (fastify, opts) {
38
38
  const sendOptions = {
39
39
  root: opts.root,
40
40
  acceptRanges: opts.acceptRanges,
41
+ contentType: opts.contentType,
41
42
  cacheControl: opts.cacheControl,
42
43
  dotfiles: opts.dotfiles,
43
44
  etag: opts.etag,
@@ -76,7 +77,7 @@ async function fastifyStatic (fastify, opts) {
76
77
  if (opts.decorateReply !== false) {
77
78
  fastify.decorateReply('sendFile', function (filePath, rootPath, options) {
78
79
  const opts = typeof rootPath === 'object' ? rootPath : options
79
- const root = typeof rootPath === 'string' ? rootPath : opts && opts.root
80
+ const root = typeof rootPath === 'string' ? rootPath : opts?.root
80
81
  pumpSendToReply(
81
82
  this.request,
82
83
  this,
@@ -442,7 +443,7 @@ function checkRootPathForErrors (fastify, rootPath) {
442
443
 
443
444
  function checkPath (fastify, rootPath) {
444
445
  if (typeof rootPath !== 'string') {
445
- throw new Error('"root" option must be a string')
446
+ throw new TypeError('"root" option must be a string')
446
447
  }
447
448
  if (path.isAbsolute(rootPath) === false) {
448
449
  throw new Error('"root" option must be an absolute path')
@@ -472,7 +473,7 @@ function getContentType (path) {
472
473
  if (!send.isUtf8MimeType(type)) {
473
474
  return type
474
475
  }
475
- return `${type}; charset=UTF-8`
476
+ return `${type}; charset=utf-8`
476
477
  }
477
478
 
478
479
  function findIndexFile (pathname, root, indexFiles = ['index.html']) {
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@fastify/static",
3
- "version": "8.0.2",
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": "npm run test:unit -- --coverage-report=html",
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": "tap",
14
+ "test:unit": "borp -C --check-coverage --lines 100",
15
15
  "example": "node example/server.js"
16
16
  },
17
17
  "repository": {
@@ -23,14 +23,43 @@
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
- "@fastify/send": "^3.1.0",
62
+ "@fastify/send": "^3.2.0",
34
63
  "content-disposition": "^0.5.4",
35
64
  "fastify-plugin": "^5.0.0",
36
65
  "fastq": "^1.17.1",
@@ -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.9.0",
45
- "fastify": "^5.0.0",
46
- "neostandard": "^0.11.3",
75
+ "eslint": "^9.17.0",
76
+ "fastify": "^5.1.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('tap')
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(6)
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.teardown(fastify.close.bind(fastify))
21
+ t.after(() => fastify.close())
23
22
 
24
- fastify.listen({ port: 0 }, (err) => {
25
- t.error(err)
23
+ await fastify.listen({ port: 0 })
26
24
 
27
- fastify.server.unref()
25
+ fastify.server.unref()
28
26
 
29
- t.test('/content-type/index.html', (t) => {
30
- t.plan(2)
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
- t.test('/content-type/index.css', (t) => {
41
- t.plan(2)
42
- simple.concat({
43
- method: 'GET',
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
- t.test('/content-type/sample.jpg', (t) => {
52
- t.plan(2)
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
- t.test('/content-type/test.txt', (t) => {
63
- t.plan(2)
64
- simple.concat({
65
- method: 'GET',
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
- t.test('/content-type/binary', (t) => {
74
- t.plan(2)
75
- simple.concat({
76
- method: 'GET',
77
- url: 'http://localhost:' + fastify.server.address().port + '/content-type/binary'
78
- }, (err, response) => {
79
- t.error(err)
80
- t.equal(response.headers['content-type'], 'application/octet-stream')
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(6)
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.teardown(fastify.close.bind(fastify))
98
-
99
- fastify.listen({ port: 0 }, (err) => {
100
- t.error(err)
101
-
102
- fastify.server.unref()
103
-
104
- t.test('/content-type/index.html', (t) => {
105
- t.plan(2)
106
- simple.concat({
107
- method: 'GET',
108
- url: 'http://localhost:' + fastify.server.address().port + '/content-type/index.html',
109
- headers: {
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
- t.test('/content-type/index.css', (t) => {
119
- t.plan(2)
120
- simple.concat({
121
- method: 'GET',
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
- t.test('/content-type/sample.jpg', (t) => {
133
- t.plan(2)
134
- simple.concat({
135
- method: 'GET',
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
- t.test('/content-type/test.txt', (t) => {
147
- t.plan(2)
148
- simple.concat({
149
- method: 'GET',
150
- url: 'http://localhost:' + fastify.server.address().port + '/content-type/test.txt',
151
- headers: {
152
- 'accept-encoding': 'gzip, deflate, br'
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
- t.test('/content-type/binary', (t) => {
161
- t.plan(2)
162
- simple.concat({
163
- method: 'GET',
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
  })