@fastify/static 9.1.1 → 9.1.2

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
@@ -122,7 +122,7 @@ async function fastifyStatic (fastify, opts) {
122
122
  method: ['HEAD', 'GET'],
123
123
  path: prefix + '*',
124
124
  handler (req, reply) {
125
- const pathname = getPathnameForSend(req.raw.url, prefix)
125
+ const pathname = getPathnameForSend(req.raw.url, req.routeOptions.url)
126
126
  if (!pathname) {
127
127
  return reply.callNotFound()
128
128
  }
@@ -570,25 +570,23 @@ function getEncodingHeader (headers, checked) {
570
570
 
571
571
  /**
572
572
  * @param {string} url
573
- * @param {string} prefix
573
+ * @param {string} route
574
574
  * @returns {string|undefined}
575
575
  */
576
- function getPathnameForSend (url, prefix) {
576
+ function getPathnameForSend (url, route) {
577
577
  const questionMark = url.indexOf('?')
578
578
  let pathname = questionMark === -1 ? url : url.slice(0, questionMark)
579
579
 
580
- if (prefix !== '/') {
581
- const routePrefix = prefix.endsWith('/')
582
- ? prefix.slice(0, -1)
583
- : prefix
580
+ const routePrefix = route.endsWith('*')
581
+ ? route.slice(0, -1)
582
+ : route
584
583
 
585
- if (!pathname.startsWith(routePrefix)) {
586
- return
587
- }
588
-
589
- pathname = pathname.slice(routePrefix.length)
584
+ if (routePrefix !== '/' && !pathname.startsWith(routePrefix)) {
585
+ return
590
586
  }
591
587
 
588
+ pathname = pathname.slice(routePrefix.length)
589
+
592
590
  if (pathname === '') {
593
591
  pathname = '/'
594
592
  } else if (!pathname.startsWith('/')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastify/static",
3
- "version": "9.1.1",
3
+ "version": "9.1.2",
4
4
  "description": "Plugin for serving static files as fast as possible.",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
@@ -6,6 +6,7 @@ const path = require('node:path')
6
6
  const fs = require('node:fs')
7
7
  const url = require('node:url')
8
8
  const http = require('node:http')
9
+ const Module = require('node:module')
9
10
  const { test } = require('node:test')
10
11
  const Fastify = require('fastify')
11
12
  const compress = require('@fastify/compress')
@@ -81,6 +82,16 @@ if (typeof Promise.withResolvers === 'undefined') {
81
82
  }
82
83
  }
83
84
 
85
+ function loadInternalPathnameForSend () {
86
+ const modulePath = require.resolve('../index.js')
87
+ const source = fs.readFileSync(modulePath, 'utf8') + '\nmodule.exports.__getPathnameForSend = getPathnameForSend\n'
88
+ const testModule = new Module(modulePath)
89
+ testModule.filename = modulePath
90
+ testModule.paths = module.paths
91
+ testModule._compile(source, modulePath)
92
+ return testModule.exports.__getPathnameForSend
93
+ }
94
+
84
95
  test('register /static prefixAvoidTrailingSlash', async t => {
85
96
  t.plan(11)
86
97
 
@@ -3590,6 +3601,51 @@ test(
3590
3601
  }
3591
3602
  )
3592
3603
 
3604
+ test('getPathnameForSend returns undefined for mismatched and malformed routes', (t) => {
3605
+ t.plan(3)
3606
+
3607
+ const getPathnameForSend = loadInternalPathnameForSend()
3608
+
3609
+ t.assert.deepStrictEqual(getPathnameForSend('/nested/public/index.css', '/public/*'), undefined)
3610
+ t.assert.deepStrictEqual(getPathnameForSend('/static/%E0%A4%A', '/static/*'), undefined)
3611
+ t.assert.deepStrictEqual(getPathnameForSend('/static/index.css', '/static'), '/index.css')
3612
+ })
3613
+
3614
+ test('wildcard handler falls back to not found when the raw url does not match the route prefix', async (t) => {
3615
+ t.plan(2)
3616
+
3617
+ const fastify = Fastify()
3618
+ let wildcardHandler
3619
+
3620
+ fastify.addHook('onRoute', (route) => {
3621
+ if (route.url === '/static/*') {
3622
+ wildcardHandler = route.handler
3623
+ }
3624
+ })
3625
+
3626
+ fastify.register(fastifyStatic, {
3627
+ root: path.join(__dirname, '/static'),
3628
+ prefix: '/static'
3629
+ })
3630
+
3631
+ t.after(() => fastify.close())
3632
+
3633
+ await fastify.ready()
3634
+ t.assert.ok(wildcardHandler)
3635
+
3636
+ let notFoundCalled = false
3637
+ wildcardHandler({
3638
+ raw: { url: '/nested/static/index.css' },
3639
+ routeOptions: { url: '/static/*' }
3640
+ }, {
3641
+ callNotFound () {
3642
+ notFoundCalled = true
3643
+ }
3644
+ })
3645
+
3646
+ t.assert.deepStrictEqual(notFoundCalled, true)
3647
+ })
3648
+
3593
3649
  test('does not serve static files with encoded path separators', async (t) => {
3594
3650
  t.plan(4)
3595
3651
 
@@ -3620,6 +3676,31 @@ test('does not serve static files with encoded path separators', async (t) => {
3620
3676
  t.assert.deepStrictEqual(encodedPathResponse.json().message, 'Route GET:/deep%2Fpath/for/test/purpose/foo.html not found')
3621
3677
  })
3622
3678
 
3679
+ test('serves wildcard files when registered in an encapsulated context', async (t) => {
3680
+ t.plan(3)
3681
+
3682
+ const fastify = Fastify()
3683
+
3684
+ t.after(() => fastify.close())
3685
+
3686
+ fastify.register(async function (childContext) {
3687
+ childContext.register(fastifyStatic, {
3688
+ root: path.join(__dirname, '/static'),
3689
+ prefix: '/public',
3690
+ decorateReply: false
3691
+ })
3692
+ }, { prefix: '/nested' })
3693
+
3694
+ const response = await fastify.inject({
3695
+ method: 'GET',
3696
+ url: '/nested/public/index.css'
3697
+ })
3698
+
3699
+ t.assert.deepStrictEqual(response.statusCode, 200)
3700
+ t.assert.deepStrictEqual(response.headers['content-type'], 'text/css; charset=utf-8')
3701
+ t.assert.deepStrictEqual(response.body, fs.readFileSync(path.join(__dirname, '/static/index.css'), 'utf8'))
3702
+ })
3703
+
3623
3704
  test('content-length in head route should not return zero when using wildcard', async t => {
3624
3705
  t.plan(5)
3625
3706
 
@@ -1 +0,0 @@
1
- /none
@@ -1 +0,0 @@
1
- ../origin