Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ If set to `true`, `fastify-static` redirects to the directory with a trailing sl
This option cannot be set to `true` with `wildcard` set to `false` on a server
with `ignoreTrailingSlash` set to `true`.

If this option is set to `false`, then requesting directories without trailing
slash will trigger your app's 404 handler using `reply.callNotFound()`.

#### `wildcard`

Default: `true`
Expand Down
10 changes: 6 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,14 @@ function fastifyStatic (fastify, opts, next) {
stream.on('headers', setHeaders)
}

if (opts.redirect === true) {
stream.on('directory', function (res, path) {
stream.on('directory', function (res, path) {
if (opts.redirect === true) {
const parsed = url.parse(request.raw.url)
reply.redirect(301, parsed.pathname + '/' + (parsed.search || ''))
})
}
} else {
reply.callNotFound()
}
})

stream.on('error', function (err) {
if (err) {
Expand Down
75 changes: 75 additions & 0 deletions test/static.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1850,3 +1850,78 @@ t.test('register /static with redirect true and wildcard false', t => {
})
})
})

t.test('trailing slash behavior with redirect = false', t => {
t.plan(6)

const fastify = Fastify()
fastify.register(fastifyStatic, {
root: path.join(__dirname, '/static'),
prefix: '/static',
redirect: false
})
fastify.server.unref()

t.tearDown(fastify.close.bind(fastify))

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

const host = 'http://localhost:' + fastify.server.address().port

t.test('prefix with no trailing slash => 404', t => {
t.plan(2)
simple.concat({
method: 'GET',
url: host + '/static'
}, (err, response) => {
t.error(err)
t.strictEqual(response.statusCode, 404)
})
})

t.test('prefix with trailing trailing slash => 200', t => {
t.plan(2)
simple.concat({
method: 'GET',
url: host + '/static/'
}, (err, response) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
})
})

t.test('deep path with no index.html or trailing slash => 404', t => {
t.plan(2)
simple.concat({
method: 'GET',
url: host + '/static/deep/path'
}, (err, response) => {
t.error(err)
t.strictEqual(response.statusCode, 404)
})
})

t.test('deep path with index.html but no trailing slash => 404', t => {
t.plan(2)
simple.concat({
method: 'GET',
url: host + '/static/deep/path/for/test'
}, (err, response) => {
t.error(err)
t.strictEqual(response.statusCode, 404)
})
})

t.test('deep path with index.html and trailing slash => 200', t => {
t.plan(2)
simple.concat({
method: 'GET',
url: host + '/static/deep/path/for/test/'
}, (err, response) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
})
})
})
})