@fastify/static 7.0.2 → 7.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/index.js CHANGED
@@ -111,8 +111,13 @@ async function fastifyStatic (fastify, opts) {
111
111
  throw new Error('"wildcard" option must be a boolean')
112
112
  }
113
113
  if (opts.wildcard === undefined || opts.wildcard === true) {
114
- fastify.get(prefix + '*', { ...routeOpts, exposeHeadRoute: true }, (req, reply) => {
115
- pumpSendToReply(req, reply, '/' + req.params['*'], sendOptions.root)
114
+ fastify.route({
115
+ ...routeOpts,
116
+ method: ['HEAD', 'GET'],
117
+ path: prefix + '*',
118
+ handler (req, reply) {
119
+ pumpSendToReply(req, reply, '/' + req.params['*'], sendOptions.root)
120
+ }
116
121
  })
117
122
  if (opts.redirect === true && prefix !== opts.prefix) {
118
123
  fastify.get(opts.prefix, routeOpts, (req, reply) => {
@@ -216,7 +221,8 @@ async function fastifyStatic (fastify, opts) {
216
221
  }
217
222
  }
218
223
 
219
- const stream = send(request.raw, pathnameForSend, options)
224
+ // `send(..., path, ...)` will URI-decode path so we pass an encoded path here
225
+ const stream = send(request.raw, encodeURI(pathnameForSend), options)
220
226
  let resolvedFilename
221
227
  stream.on('file', function (file) {
222
228
  resolvedFilename = file
package/lib/dirList.js CHANGED
@@ -149,7 +149,7 @@ const dirList = {
149
149
  route = path.normalize(path.join(route, '..'))
150
150
  }
151
151
  return {
152
- href: path.join(prefix, route, entry.name).replace(/\\/gu, '/'),
152
+ href: encodeURI(path.join(prefix, route, entry.name).replace(/\\/gu, '/')),
153
153
  name: entry.name,
154
154
  stats: entry.stats,
155
155
  extendedInfo: entry.extendedInfo
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastify/static",
3
- "version": "7.0.2",
3
+ "version": "7.0.4",
4
4
  "description": "Plugin for serving static files as fast as possible.",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
@@ -55,7 +55,7 @@
55
55
  "snazzy": "^9.0.0",
56
56
  "standard": "^17.0.0",
57
57
  "tap": "^16.0.0",
58
- "tsd": "^0.30.0",
58
+ "tsd": "^0.31.0",
59
59
  "typescript": "^5.1.6"
60
60
  },
61
61
  "tsd": {
@@ -154,7 +154,7 @@ t.test('dir list, custom options', t => {
154
154
  }
155
155
 
156
156
  const route = '/public/'
157
- const content = { dirs: ['deep', 'shallow'], files: ['.example', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] }
157
+ const content = { dirs: ['deep', 'shallow'], files: ['.example', '100%.txt', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] }
158
158
 
159
159
  helper.arrange(t, options, (url) => {
160
160
  t.test(route, t => {
@@ -205,7 +205,8 @@ t.test('dir list html format', t => {
205
205
  </ul>
206
206
  <ul>
207
207
  <li><a href="/public/.example" target="_blank">.example</a></li>
208
- <li><a href="/public/a .md" target="_blank">a .md</a></li>
208
+ <li><a href="/public/100%25.txt" target="_blank">100%.txt</a></li>
209
+ <li><a href="/public/a%20.md" target="_blank">a .md</a></li>
209
210
  <li><a href="/public/foo.html" target="_blank">foo.html</a></li>
210
211
  <li><a href="/public/foobar.html" target="_blank">foobar.html</a></li>
211
212
  <li><a href="/public/index.css" target="_blank">index.css</a></li>
@@ -236,7 +237,8 @@ t.test('dir list html format', t => {
236
237
  </ul>
237
238
  <ul>
238
239
  <li><a href="/public/.example" target="_blank">.example</a></li>
239
- <li><a href="/public/a .md" target="_blank">a .md</a></li>
240
+ <li><a href="/public/100%25.txt" target="_blank">100%.txt</a></li>
241
+ <li><a href="/public/a%20.md" target="_blank">a .md</a></li>
240
242
  <li><a href="/public/foo.html" target="_blank">foo.html</a></li>
241
243
  <li><a href="/public/foobar.html" target="_blank">foobar.html</a></li>
242
244
  <li><a href="/public/index.css" target="_blank">index.css</a></li>
@@ -492,7 +494,7 @@ t.test('json format with url parameter format', t => {
492
494
  }
493
495
  }
494
496
  const route = '/public/'
495
- const jsonContent = { dirs: ['deep', 'shallow'], files: ['.example', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] }
497
+ const jsonContent = { dirs: ['deep', 'shallow'], files: ['.example', '100%.txt', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] }
496
498
 
497
499
  helper.arrange(t, options, (url) => {
498
500
  simple.concat({
@@ -539,7 +541,7 @@ t.test('json format with url parameter format and without render option', t => {
539
541
  }
540
542
  }
541
543
  const route = '/public/'
542
- const jsonContent = { dirs: ['deep', 'shallow'], files: ['.example', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] }
544
+ const jsonContent = { dirs: ['deep', 'shallow'], files: ['.example', '100%.txt', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] }
543
545
 
544
546
  helper.arrange(t, options, (url) => {
545
547
  simple.concat({
@@ -588,7 +590,7 @@ t.test('html format with url parameter format', t => {
588
590
  }
589
591
  }
590
592
  const route = '/public/'
591
- const jsonContent = { dirs: ['deep', 'shallow'], files: ['.example', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] }
593
+ const jsonContent = { dirs: ['deep', 'shallow'], files: ['.example', '100%.txt', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] }
592
594
 
593
595
  helper.arrange(t, options, (url) => {
594
596
  simple.concat({
@@ -0,0 +1 @@
1
+ 100%
@@ -1740,7 +1740,7 @@ t.test('with fastify-compress', t => {
1740
1740
  })
1741
1741
  })
1742
1742
  t.test('register /static/ with schemaHide true', t => {
1743
- t.plan(4)
1743
+ t.plan(3)
1744
1744
 
1745
1745
  const pluginOptions = {
1746
1746
  root: path.join(__dirname, '/static'),
@@ -1780,7 +1780,7 @@ t.test('register /static/ with schemaHide true', t => {
1780
1780
  })
1781
1781
 
1782
1782
  t.test('register /static/ with schemaHide false', t => {
1783
- t.plan(4)
1783
+ t.plan(3)
1784
1784
 
1785
1785
  const pluginOptions = {
1786
1786
  root: path.join(__dirname, '/static'),
@@ -1820,7 +1820,7 @@ t.test('register /static/ with schemaHide false', t => {
1820
1820
  })
1821
1821
 
1822
1822
  t.test('register /static/ without schemaHide', t => {
1823
- t.plan(4)
1823
+ t.plan(3)
1824
1824
 
1825
1825
  const pluginOptions = {
1826
1826
  root: path.join(__dirname, '/static'),
@@ -2957,7 +2957,7 @@ t.test('inject support', async (t) => {
2957
2957
  })
2958
2958
 
2959
2959
  t.test('routes should use custom errorHandler premature stream close', t => {
2960
- t.plan(4)
2960
+ t.plan(3)
2961
2961
 
2962
2962
  const pluginOptions = {
2963
2963
  root: path.join(__dirname, '/static'),
@@ -2992,7 +2992,7 @@ t.test('routes should use custom errorHandler premature stream close', t => {
2992
2992
  })
2993
2993
 
2994
2994
  t.test('routes should fallback to default errorHandler', t => {
2995
- t.plan(4)
2995
+ t.plan(3)
2996
2996
 
2997
2997
  const pluginOptions = {
2998
2998
  root: path.join(__dirname, '/static'),
@@ -3962,3 +3962,64 @@ t.test(
3962
3962
  t.same(response2.body, aContent)
3963
3963
  }
3964
3964
  )
3965
+
3966
+ t.test(
3967
+ 'serves files with % in the filename',
3968
+ async (t) => {
3969
+ t.plan(2)
3970
+
3971
+ const txtContent = fs.readFileSync(path.join(__dirname, 'static', '100%.txt'), 'utf-8')
3972
+
3973
+ const pluginOptions = {
3974
+ root: url.pathToFileURL(path.join(__dirname, '/static')),
3975
+ wildcard: false
3976
+ }
3977
+
3978
+ const fastify = Fastify()
3979
+
3980
+ fastify.register(fastifyStatic, pluginOptions)
3981
+ const response = await fastify.inject({
3982
+ method: 'GET',
3983
+ url: '100%25.txt',
3984
+ headers: {
3985
+ 'accept-encoding': '*, *'
3986
+ }
3987
+ })
3988
+ t.equal(response.statusCode, 200)
3989
+ t.same(response.body, txtContent)
3990
+ }
3991
+ )
3992
+
3993
+ t.test('content-length in head route should not return zero when using wildcard', t => {
3994
+ t.plan(6)
3995
+
3996
+ const pluginOptions = {
3997
+ root: path.join(__dirname, '/static')
3998
+ }
3999
+ const fastify = Fastify()
4000
+
4001
+ fastify.register(fastifyStatic, pluginOptions)
4002
+
4003
+ t.teardown(fastify.close.bind(fastify))
4004
+
4005
+ fastify.listen({ port: 0 }, err => {
4006
+ t.error(err)
4007
+
4008
+ fastify.server.unref()
4009
+
4010
+ const file = fs.readFileSync(path.join(__dirname, '/static/index.html'))
4011
+ const contentLength = Buffer.byteLength(file).toString()
4012
+
4013
+ simple.concat({
4014
+ method: 'HEAD',
4015
+ url: 'http://localhost:' + fastify.server.address().port + '/index.html',
4016
+ followRedirect: false
4017
+ }, (err, response, body) => {
4018
+ t.error(err)
4019
+ t.equal(response.statusCode, 200)
4020
+ t.equal(response.headers['content-type'], 'text/html; charset=UTF-8')
4021
+ t.equal(response.headers['content-length'], contentLength)
4022
+ t.equal(body.toString(), '')
4023
+ })
4024
+ })
4025
+ })