@fastify/static 6.5.0 → 6.6.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.
@@ -14,4 +14,5 @@ jobs:
14
14
  test:
15
15
  uses: fastify/workflows/.github/workflows/plugins-ci.yml@v3
16
16
  with:
17
+ license-check: true
17
18
  lint: true
package/README.md CHANGED
@@ -4,10 +4,14 @@
4
4
  [![NPM version](https://img.shields.io/npm/v/@fastify/static.svg?style=flat)](https://www.npmjs.com/package/@fastify/static)
5
5
  [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)
6
6
 
7
- Plugin for serving static files as fast as possible. Supports Fastify version `3.x`.
7
+ Plugin for serving static files as fast as possible. Supports Fastify version `4.x`.
8
8
 
9
- Please refer to [this branch](https://github.com/fastify/fastify-static/tree/2.x) and related versions for Fastify `^2.0.0` compatibility.
10
- Please refer to [this branch](https://github.com/fastify/fastify-static/tree/1.x) and related versions for Fastify `^1.11.0` compatibility.
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) |
11
15
 
12
16
  ## Install
13
17
 
@@ -16,7 +20,7 @@ Please refer to [this branch](https://github.com/fastify/fastify-static/tree/1.x
16
20
  ## Usage
17
21
 
18
22
  ```js
19
- const fastify = require('fastify')()
23
+ const fastify = require('fastify')({logger: true})
20
24
  const path = require('path')
21
25
 
22
26
  fastify.register(require('@fastify/static'), {
@@ -25,15 +29,25 @@ fastify.register(require('@fastify/static'), {
25
29
  })
26
30
 
27
31
  fastify.get('/another/path', function (req, reply) {
28
- return reply.sendFile('myHtml.html') // serving path.join(__dirname, 'public', 'myHtml.html') directly
32
+ reply.sendFile('myHtml.html') // serving path.join(__dirname, 'public', 'myHtml.html') directly
33
+ })
34
+
35
+ fastify.get('/another/patch-async', async function (req, reply) {
36
+ return reply.sendFile('myHtml.html')
29
37
  })
30
38
 
31
39
  fastify.get('/path/with/different/root', function (req, reply) {
32
- return reply.sendFile('myHtml.html', path.join(__dirname, 'build')) // serving a file from a different root location
40
+ reply.sendFile('myHtml.html', path.join(__dirname, 'build')) // serving a file from a different root location
33
41
  })
34
42
 
35
43
  fastify.get('/another/path', function (req, reply) {
36
- return reply.sendFile('myHtml.html', { cacheControl: false }) // overriding the options disabling cache-control headers
44
+ reply.sendFile('myHtml.html', { cacheControl: false }) // overriding the options disabling cache-control headers
45
+ })
46
+
47
+ // Run the server!
48
+ fastify.listen({ port: 3000 }, (err, address) => {
49
+ if (err) throw err
50
+ // Server is now listening on ${address}
37
51
  })
38
52
  ```
39
53
 
@@ -69,15 +83,20 @@ fastify.register(require('@fastify/static'), {
69
83
  })
70
84
 
71
85
  fastify.get('/another/path', function (req, reply) {
72
- return reply.download('myHtml.html', 'custom-filename.html') // sending path.join(__dirname, 'public', 'myHtml.html') directly with custom filename
86
+ reply.download('myHtml.html', 'custom-filename.html') // sending path.join(__dirname, 'public', 'myHtml.html') directly with custom filename
87
+ })
88
+
89
+ fastify.get('another/patch-async', async function (req, reply) {
90
+ // an async handler must always return the reply object
91
+ return reply.download('myHtml.html', 'custom-filename.html')
73
92
  })
74
93
 
75
94
  fastify.get('/path/without/cache/control', function (req, reply) {
76
- return reply.download('myHtml.html', { cacheControl: false }) // serving a file disabling cache-control headers
95
+ reply.download('myHtml.html', { cacheControl: false }) // serving a file disabling cache-control headers
77
96
  })
78
97
 
79
98
  fastify.get('/path/without/cache/control', function (req, reply) {
80
- return reply.download('myHtml.html', 'custom-filename.html', { cacheControl: false })
99
+ reply.download('myHtml.html', 'custom-filename.html', { cacheControl: false })
81
100
  })
82
101
 
83
102
  ```
@@ -182,11 +201,17 @@ Default: `undefined`
182
201
  Under the hood we use [send](https://github.com/pillarjs/send#index) lib that by default supports "index.html" files.
183
202
  To disable this set false or to supply a new index pass a string or an array in preferred order.
184
203
 
204
+ ### `serveDotFiles`
205
+
206
+ Default: `false`
207
+
208
+ When `true`, files in hidden directories (e.g. `.foo`) will be served.
209
+
185
210
  #### `list`
186
211
 
187
212
  Default: `undefined`
188
213
 
189
- If set, it provide the directory list calling the directory path.
214
+ If set, it provides the directory list calling the directory path.
190
215
 
191
216
  Default response is json.
192
217
 
@@ -0,0 +1 @@
1
+ {"hello": "world"}
@@ -10,6 +10,6 @@ fastify
10
10
  // An absolute path containing static files to serve.
11
11
  root: path.join(__dirname, '/public')
12
12
  })
13
- .listen(3000, err => {
13
+ .listen({ port: 3000 }, err => {
14
14
  if (err) throw err
15
15
  })
@@ -44,6 +44,6 @@ fastify
44
44
  render: (dirs, files) => handlebarTemplate({ dirs, files })
45
45
  }
46
46
  })
47
- .listen(3000, err => {
47
+ .listen({ port: 3000 }, err => {
48
48
  if (err) throw err
49
49
  })
@@ -0,0 +1,15 @@
1
+ 'use strict'
2
+
3
+ const path = require('path')
4
+ const fastify = require('fastify')({ logger: { level: 'trace' } })
5
+
6
+ fastify
7
+ .register(require('../'), {
8
+ // An absolute path containing static files to serve.
9
+ root: path.join(__dirname, '/public'),
10
+ wildcard: false,
11
+ serveDotFiles: true
12
+ })
13
+ .listen({ port: 3000 }, err => {
14
+ if (err) throw err
15
+ })
package/example/server.js CHANGED
@@ -8,6 +8,6 @@ fastify
8
8
  // An absolute path containing static files to serve.
9
9
  root: path.join(__dirname, '/public')
10
10
  })
11
- .listen(3000, err => {
11
+ .listen({ port: 3000 }, err => {
12
12
  if (err) throw err
13
13
  })
package/index.js CHANGED
@@ -37,7 +37,8 @@ async function fastifyStatic (fastify, opts) {
37
37
  immutable: opts.immutable,
38
38
  index: opts.index,
39
39
  lastModified: opts.lastModified,
40
- maxAge: opts.maxAge
40
+ maxAge: opts.maxAge,
41
+ serveDotFiles: opts.serveDotFiles ?? false
41
42
  }
42
43
 
43
44
  const allowedPath = opts.allowedPath
@@ -336,7 +337,7 @@ async function fastifyStatic (fastify, opts) {
336
337
  const winSeparatorRegex = new RegExp(`\\${path.win32.sep}`, 'g')
337
338
 
338
339
  for (const rootPath of Array.isArray(sendOptions.root) ? sendOptions.root : [sendOptions.root]) {
339
- const files = await globPromise(path.join(rootPath, globPattern).replace(winSeparatorRegex, path.posix.sep), { nodir: true })
340
+ const files = await globPromise(path.join(rootPath, globPattern).replace(winSeparatorRegex, path.posix.sep), { nodir: true, dot: sendOptions.serveDotFiles })
340
341
  const indexes = typeof opts.index === 'undefined' ? ['index.html'] : [].concat(opts.index)
341
342
 
342
343
  for (let file of files) {
@@ -518,3 +519,5 @@ module.exports = fp(fastifyStatic, {
518
519
  fastify: '4.x',
519
520
  name: '@fastify/static'
520
521
  })
522
+ module.exports.default = fastifyStatic
523
+ module.exports.fastifyStatic = fastifyStatic
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@fastify/static",
3
- "version": "6.5.0",
3
+ "version": "6.6.0",
4
4
  "description": "Plugin for serving static files as fast as possible.",
5
5
  "main": "index.js",
6
- "types": "index.d.ts",
6
+ "types": "types/index.d.ts",
7
7
  "scripts": {
8
8
  "lint": "standard | snazzy",
9
9
  "lint:fix": "standard --fix",
@@ -39,6 +39,7 @@
39
39
  },
40
40
  "devDependencies": {
41
41
  "@fastify/compress": "^6.0.0",
42
+ "@fastify/pre-commit": "^2.0.2",
42
43
  "@types/node": "^18.0.0",
43
44
  "@typescript-eslint/eslint-plugin": "^2.29.0",
44
45
  "@typescript-eslint/parser": "^2.29.0",
@@ -47,14 +48,13 @@
47
48
  "eslint-plugin-typescript": "^0.14.0",
48
49
  "fastify": "^4.0.0-rc.2",
49
50
  "handlebars": "^4.7.6",
50
- "pre-commit": "^1.2.2",
51
+ "pino": "^8.4.2",
51
52
  "proxyquire": "^2.1.0",
52
53
  "simple-get": "^4.0.0",
53
54
  "snazzy": "^9.0.0",
54
55
  "standard": "^17.0.0",
55
56
  "tap": "^16.0.0",
56
- "tsd": "^0.22.0",
57
- "typescript": "^4.0.2"
57
+ "tsd": "^0.24.1"
58
58
  },
59
59
  "tsd": {
60
60
  "directory": "test/types"
Binary file
@@ -0,0 +1 @@
1
+ {"hello": "world"}
@@ -51,6 +51,7 @@ const uncompressedStatic = fs
51
51
  .toString('utf8')
52
52
  const fooContent = fs.readFileSync('./test/static/foo.html').toString('utf8')
53
53
  const barContent = fs.readFileSync('./test/static2/bar.html').toString('utf8')
54
+ const jsonHiddenContent = fs.readFileSync('./test/static-hidden/.hidden/sample.json').toString('utf8')
54
55
 
55
56
  const GENERIC_RESPONSE_CHECK_COUNT = 5
56
57
  function genericResponseChecks (t, response) {
@@ -808,7 +809,7 @@ t.test('serving disabled', (t) => {
808
809
  fastify.register(fastifyStatic, pluginOptions)
809
810
 
810
811
  fastify.get('/foo/bar', (request, reply) => {
811
- return reply.sendFile('index.html')
812
+ reply.sendFile('index.html')
812
813
  })
813
814
 
814
815
  t.teardown(fastify.close.bind(fastify))
@@ -856,18 +857,18 @@ t.test('sendFile', (t) => {
856
857
  fastify.register(fastifyStatic, pluginOptions)
857
858
 
858
859
  fastify.get('/foo/bar', function (req, reply) {
859
- return reply.sendFile('/index.html')
860
+ reply.sendFile('/index.html')
860
861
  })
861
862
 
862
863
  fastify.get('/root/path/override/test', (request, reply) => {
863
- return reply.sendFile(
864
+ reply.sendFile(
864
865
  '/foo.html',
865
866
  path.join(__dirname, 'static', 'deep', 'path', 'for', 'test', 'purpose')
866
867
  )
867
868
  })
868
869
 
869
870
  fastify.get('/foo/bar/options/override/test', function (req, reply) {
870
- return reply.sendFile('/index.html', { maxAge })
871
+ reply.sendFile('/index.html', { maxAge })
871
872
  })
872
873
 
873
874
  fastify.listen({ port: 0 }, (err) => {
@@ -1066,26 +1067,26 @@ t.test('download', (t) => {
1066
1067
  fastify.register(fastifyStatic, pluginOptions)
1067
1068
 
1068
1069
  fastify.get('/foo/bar', function (req, reply) {
1069
- return reply.download('/index.html')
1070
+ reply.download('/index.html')
1070
1071
  })
1071
1072
 
1072
1073
  fastify.get('/foo/bar/change', function (req, reply) {
1073
- return reply.download('/index.html', 'hello-world.html')
1074
+ reply.download('/index.html', 'hello-world.html')
1074
1075
  })
1075
1076
 
1076
1077
  fastify.get('/foo/bar/override', function (req, reply) {
1077
- return reply.download('/index.html', 'hello-world.html', {
1078
+ reply.download('/index.html', 'hello-world.html', {
1078
1079
  maxAge: '2 hours',
1079
1080
  immutable: true
1080
1081
  })
1081
1082
  })
1082
1083
 
1083
1084
  fastify.get('/foo/bar/override/2', function (req, reply) {
1084
- return reply.download('/index.html', { acceptRanges: false })
1085
+ reply.download('/index.html', { acceptRanges: false })
1085
1086
  })
1086
1087
 
1087
1088
  fastify.get('/root/path/override/test', (request, reply) => {
1088
- return reply.download('/foo.html', {
1089
+ reply.download('/foo.html', {
1089
1090
  root: path.join(
1090
1091
  __dirname,
1091
1092
  'static',
@@ -1099,7 +1100,7 @@ t.test('download', (t) => {
1099
1100
  })
1100
1101
 
1101
1102
  fastify.get('/root/path/override/test/change', (request, reply) => {
1102
- return reply.download('/foo.html', 'hello-world.html', {
1103
+ reply.download('/foo.html', 'hello-world.html', {
1103
1104
  root: path.join(
1104
1105
  __dirname,
1105
1106
  'static',
@@ -3552,3 +3553,96 @@ t.test('should follow symbolic link without wildcard', (t) => {
3552
3553
  })
3553
3554
  })
3554
3555
  })
3556
+
3557
+ t.test('should serve files into hidden dir with wildcard `false`', (t) => {
3558
+ t.plan(9)
3559
+
3560
+ const pluginOptions = {
3561
+ root: path.join(__dirname, '/static-hidden'),
3562
+ wildcard: false,
3563
+ serveDotFiles: true
3564
+ }
3565
+ const fastify = Fastify()
3566
+ fastify.register(fastifyStatic, pluginOptions)
3567
+
3568
+ t.teardown(fastify.close.bind(fastify))
3569
+
3570
+ fastify.listen({ port: 0 }, (err) => {
3571
+ t.error(err)
3572
+
3573
+ fastify.server.unref()
3574
+
3575
+ simple.concat({
3576
+ method: 'GET',
3577
+ url: 'http://localhost:' + fastify.server.address().port + '/.hidden/sample.json'
3578
+ }, (err, response, body) => {
3579
+ t.error(err)
3580
+ t.equal(response.statusCode, 200)
3581
+ t.equal(body.toString(), jsonHiddenContent)
3582
+ t.ok(/application\/(json)/.test(response.headers['content-type']))
3583
+ t.ok(response.headers.etag)
3584
+ t.ok(response.headers['last-modified'])
3585
+ t.ok(response.headers.date)
3586
+ t.ok(response.headers['cache-control'])
3587
+ })
3588
+ })
3589
+ })
3590
+
3591
+ t.test('should not found hidden file with wildcard is `false`', (t) => {
3592
+ t.plan(3)
3593
+
3594
+ const pluginOptions = {
3595
+ root: path.join(__dirname, '/static-hidden'),
3596
+ wildcard: false
3597
+ }
3598
+ const fastify = Fastify()
3599
+ fastify.register(fastifyStatic, pluginOptions)
3600
+
3601
+ t.teardown(fastify.close.bind(fastify))
3602
+
3603
+ fastify.listen({ port: 0 }, (err) => {
3604
+ t.error(err)
3605
+
3606
+ fastify.server.unref()
3607
+
3608
+ simple.concat({
3609
+ method: 'GET',
3610
+ url: 'http://localhost:' + fastify.server.address().port + '/.hidden/sample.json'
3611
+ }, (err, response, body) => {
3612
+ t.error(err)
3613
+ t.equal(response.statusCode, 404)
3614
+ })
3615
+ })
3616
+ })
3617
+
3618
+ t.test('should serve files into hidden dir without wildcard option', (t) => {
3619
+ t.plan(9)
3620
+
3621
+ const pluginOptions = {
3622
+ root: path.join(__dirname, '/static-hidden')
3623
+ }
3624
+ const fastify = Fastify()
3625
+ fastify.register(fastifyStatic, pluginOptions)
3626
+
3627
+ t.teardown(fastify.close.bind(fastify))
3628
+
3629
+ fastify.listen({ port: 0 }, (err) => {
3630
+ t.error(err)
3631
+
3632
+ fastify.server.unref()
3633
+
3634
+ simple.concat({
3635
+ method: 'GET',
3636
+ url: 'http://localhost:' + fastify.server.address().port + '/.hidden/sample.json'
3637
+ }, (err, response, body) => {
3638
+ t.error(err)
3639
+ t.equal(response.statusCode, 200)
3640
+ t.equal(body.toString(), jsonHiddenContent)
3641
+ t.ok(/application\/(json)/.test(response.headers['content-type']))
3642
+ t.ok(response.headers.etag)
3643
+ t.ok(response.headers['last-modified'])
3644
+ t.ok(response.headers.date)
3645
+ t.ok(response.headers['cache-control'])
3646
+ })
3647
+ })
3648
+ })
@@ -2,7 +2,7 @@
2
2
  // Leo <https://github.com/leomelzer>
3
3
  /// <reference types="node" />
4
4
 
5
- import { FastifyPluginCallback, FastifyReply, FastifyRequest } from 'fastify';
5
+ import { FastifyPluginAsync, FastifyRequest } from 'fastify';
6
6
  import { Stats } from 'fs';
7
7
 
8
8
  declare module "fastify" {
@@ -16,7 +16,7 @@ declare module "fastify" {
16
16
  }
17
17
  }
18
18
 
19
- type FastifyStaticPlugin = FastifyPluginCallback<NonNullable<fastifyStatic.FastifyStaticOptions>>;
19
+ type FastifyStaticPlugin = FastifyPluginAsync<NonNullable<fastifyStatic.FastifyStaticOptions>>;
20
20
 
21
21
  declare namespace fastifyStatic {
22
22
  export interface ExtendedInformation {
@@ -73,6 +73,7 @@ declare namespace fastifyStatic {
73
73
  index?: string[] | string | false;
74
74
  lastModified?: boolean;
75
75
  maxAge?: string | number;
76
+ serveDotFiles?: boolean;
76
77
  }
77
78
 
78
79
  export interface FastifyStaticOptions extends SendOptions {
@@ -1,14 +1,14 @@
1
- import fastify, { FastifyInstance, FastifyPluginCallback, FastifyRequest } from 'fastify'
1
+ import fastify, { FastifyInstance, FastifyPluginAsync, FastifyRequest } from 'fastify'
2
2
  import { Server } from 'http';
3
3
  import { expectAssignable, expectError, expectType } from 'tsd'
4
- import * as fastifyStaticStar from '../..';
4
+ import * as fastifyStaticStar from '..';
5
5
  import fastifyStatic, {
6
6
  FastifyStaticOptions,
7
7
  fastifyStatic as fastifyStaticNamed,
8
- } from '../..'
8
+ } from '..'
9
9
 
10
- import fastifyStaticCjsImport = require('../..');
11
- const fastifyStaticCjs = require('../..');
10
+ import fastifyStaticCjsImport = require('..');
11
+ const fastifyStaticCjs = require('..');
12
12
 
13
13
  const app: FastifyInstance = fastify();
14
14
 
@@ -20,12 +20,12 @@ app.register(fastifyStaticCjsImport.fastifyStatic);
20
20
  app.register(fastifyStaticStar.default);
21
21
  app.register(fastifyStaticStar.fastifyStatic);
22
22
 
23
- expectType<FastifyPluginCallback<FastifyStaticOptions, Server>>(fastifyStatic);
24
- expectType<FastifyPluginCallback<FastifyStaticOptions, Server>>(fastifyStaticNamed);
25
- expectType<FastifyPluginCallback<FastifyStaticOptions, Server>>(fastifyStaticCjsImport.default);
26
- expectType<FastifyPluginCallback<FastifyStaticOptions, Server>>(fastifyStaticCjsImport.fastifyStatic);
27
- expectType<FastifyPluginCallback<FastifyStaticOptions, Server>>(fastifyStaticStar.default);
28
- expectType<FastifyPluginCallback<FastifyStaticOptions, Server>>(
23
+ expectType<FastifyPluginAsync<FastifyStaticOptions, Server>>(fastifyStatic);
24
+ expectType<FastifyPluginAsync<FastifyStaticOptions, Server>>(fastifyStaticNamed);
25
+ expectType<FastifyPluginAsync<FastifyStaticOptions, Server>>(fastifyStaticCjsImport.default);
26
+ expectType<FastifyPluginAsync<FastifyStaticOptions, Server>>(fastifyStaticCjsImport.fastifyStatic);
27
+ expectType<FastifyPluginAsync<FastifyStaticOptions, Server>>(fastifyStaticStar.default);
28
+ expectType<FastifyPluginAsync<FastifyStaticOptions, Server>>(
29
29
  fastifyStaticStar.fastifyStatic
30
30
  );
31
31
  expectType<any>(fastifyStaticCjs);
package/.eslintrc DELETED
@@ -1 +0,0 @@
1
- { "extends": "standard" }
package/lib/sdf/wqer DELETED
File without changes