Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: wildcard head return content-length header #448

Merged
merged 1 commit into from Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 7 additions & 2 deletions index.js
Expand Up @@ -111,8 +111,13 @@
throw new Error('"wildcard" option must be a boolean')
}
if (opts.wildcard === undefined || opts.wildcard === true) {
fastify.get(prefix + '*', { ...routeOpts, exposeHeadRoute: true }, (req, reply) => {
pumpSendToReply(req, reply, '/' + req.params['*'], sendOptions.root)
fastify.route({
...routeOpts,
method: ['HEAD', 'GET'],
path: prefix + '*',
handler (req, reply) {
pumpSendToReply(req, reply, '/' + req.params['*'], sendOptions.root)
}
})
if (opts.redirect === true && prefix !== opts.prefix) {
fastify.get(opts.prefix, routeOpts, (req, reply) => {
Expand Down Expand Up @@ -489,7 +494,7 @@
return indexFiles.find(filename => {
const p = path.join(root, pathname, filename)
try {
const stats = statSync(p)

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.
This path depends on a
user-provided value
.
return !stats.isDirectory()
} catch {
return false
Expand Down
44 changes: 39 additions & 5 deletions test/static.test.js
Expand Up @@ -1740,7 +1740,7 @@ t.test('with fastify-compress', t => {
})
})
t.test('register /static/ with schemaHide true', t => {
t.plan(4)
t.plan(3)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? There weren't unfinished test errors before?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we no longer have GET and HEAD registered separately.
FYI: The internal HEAD route also trigger onRoute hook.


const pluginOptions = {
root: path.join(__dirname, '/static'),
Expand Down Expand Up @@ -1780,7 +1780,7 @@ t.test('register /static/ with schemaHide true', t => {
})

t.test('register /static/ with schemaHide false', t => {
t.plan(4)
t.plan(3)

const pluginOptions = {
root: path.join(__dirname, '/static'),
Expand Down Expand Up @@ -1820,7 +1820,7 @@ t.test('register /static/ with schemaHide false', t => {
})

t.test('register /static/ without schemaHide', t => {
t.plan(4)
t.plan(3)

const pluginOptions = {
root: path.join(__dirname, '/static'),
Expand Down Expand Up @@ -2957,7 +2957,7 @@ t.test('inject support', async (t) => {
})

t.test('routes should use custom errorHandler premature stream close', t => {
t.plan(4)
t.plan(3)

const pluginOptions = {
root: path.join(__dirname, '/static'),
Expand Down Expand Up @@ -2992,7 +2992,7 @@ t.test('routes should use custom errorHandler premature stream close', t => {
})

t.test('routes should fallback to default errorHandler', t => {
t.plan(4)
t.plan(3)

const pluginOptions = {
root: path.join(__dirname, '/static'),
Expand Down Expand Up @@ -3962,3 +3962,37 @@ t.test(
t.same(response2.body, aContent)
}
)

t.test('content-length in head route should not return zero when using wildcard', t => {
t.plan(6)

const pluginOptions = {
root: path.join(__dirname, '/static')
}
const fastify = Fastify()

fastify.register(fastifyStatic, pluginOptions)

t.teardown(fastify.close.bind(fastify))

fastify.listen({ port: 0 }, err => {
t.error(err)

fastify.server.unref()

const file = fs.readFileSync(path.join(__dirname, '/static/index.html'))
const contentLength = Buffer.byteLength(file).toString()

simple.concat({
method: 'HEAD',
url: 'http://localhost:' + fastify.server.address().port + '/index.html',
followRedirect: false
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.equal(response.headers['content-type'], 'text/html; charset=UTF-8')
t.equal(response.headers['content-length'], contentLength)
t.equal(body.toString(), '')
})
})
})