Skip to content

Commit

Permalink
Merge branch 'master' of github.com:fastify/fastify-static
Browse files Browse the repository at this point in the history
  • Loading branch information
mcollina committed May 23, 2022
2 parents 287f503 + d80ebbc commit aeb37cf
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 18 deletions.
4 changes: 3 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ interface ListRender {
interface ListOptions {
names?: string[];
extendedFolderInfo?: boolean;
jsonFormat?: 'names' | 'extended';
}

interface ListOptionsJsonFormat extends ListOptions {
format: 'json';
jsonFormat?: 'names' | 'extended';
// Required when the URL parameter `format=html` exists
render?: ListRender;
}

interface ListOptionsHtmlFormat extends ListOptions {
Expand Down
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ async function fastifyStatic (fastify, opts) {

stream.on('error', function (err) {
if (err.code === 'ENOENT') {
// when preCompress is enabled and the path is a directoy without a trailing shash
// when preCompress is enabled and the path is a directory without a trailing slash
if (opts.preCompressed && encoding) {
const indexPathname = findIndexFile(pathname, options.root, options.index)
if (indexPathname) {
Expand Down Expand Up @@ -494,7 +494,7 @@ function getEncodingExtension (encoding) {

function getRedirectUrl (url) {
let i = 0
// we detech how many slash before a valid path
// we detect how many slash before a valid path
for (i; i < url.length; i++) {
if (url[i] !== '/' && url[i] !== '\\') break
}
Expand Down
7 changes: 4 additions & 3 deletions lib/dirList.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ const dirList = {
* @param {string} dotfiles
*/
send: async function ({ reply, dir, options, route, prefix, dotfiles }) {
if (reply.request.query.format === 'html' && typeof options.render !== 'function') {
throw new Error('The `list.render` option must be a function and is required with the URL parameter `format=html`')
}

let entries
try {
entries = await dirList.list(dir, options, dotfiles)
Expand Down Expand Up @@ -200,9 +204,6 @@ const dirList = {
if (options.list.format === 'html' && typeof options.list.render !== 'function') {
return new TypeError('The `list.render` option must be a function and is required with html format')
}
if (options.list.format === 'html' && options.list.jsonFormat != null) {
return new TypeError('The `list.jsonFormat` option must be with json format')
}
}

}
Expand Down
109 changes: 99 additions & 10 deletions test/dir-list.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,6 @@ t.test('throws when `list.format` is html and `list render` is not a function',
t.equal(err.message, 'The `list.render` option must be a function and is required with html format')
})

t.test('throws when `list.format` is html and `list.jsonFormat` is given', t => {
t.plan(2)

const err = dirList.validateOptions({ list: { format: 'html', render: () => '', jsonFormat: 'extended' } })
t.type(err, TypeError)
t.equal(err.message, 'The `list.jsonFormat` option must be with json format')
})

t.test('dir list wrong options', t => {
t.plan(3)

Expand Down Expand Up @@ -485,7 +477,103 @@ t.test('dir list json format - extended info', t => {
})
})

t.test('dir list - url parameter format', t => {
t.test('json format with url parameter format', t => {
t.plan(13)

const options = {
root: path.join(__dirname, '/static'),
prefix: '/public',
index: false,
list: {
format: 'json',
render (dirs, files) {
return 'html'
}
}
}
const route = '/public/'
const jsonContent = { dirs: ['deep', 'shallow'], files: ['.example', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] }

helper.arrange(t, options, (url) => {
simple.concat({
method: 'GET',
url: url + route
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.equal(body.toString(), JSON.stringify(jsonContent))
t.ok(response.headers['content-type'].includes('application/json'))
})

simple.concat({
method: 'GET',
url: url + route + '?format=html'
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.equal(body.toString(), 'html')
t.ok(response.headers['content-type'].includes('text/html'))
})

simple.concat({
method: 'GET',
url: url + route + '?format=json'
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.equal(body.toString(), JSON.stringify(jsonContent))
t.ok(response.headers['content-type'].includes('application/json'))
})
})
})

t.test('json format with url parameter format and without render option', t => {
t.plan(12)

const options = {
root: path.join(__dirname, '/static'),
prefix: '/public',
index: false,
list: {
format: 'json'
}
}
const route = '/public/'
const jsonContent = { dirs: ['deep', 'shallow'], files: ['.example', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] }

helper.arrange(t, options, (url) => {
simple.concat({
method: 'GET',
url: url + route
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.equal(body.toString(), JSON.stringify(jsonContent))
t.ok(response.headers['content-type'].includes('application/json'))
})

simple.concat({
method: 'GET',
url: url + route + '?format=html'
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 500)
t.equal(JSON.parse(body.toString()).message, 'The `list.render` option must be a function and is required with the URL parameter `format=html`')
})

simple.concat({
method: 'GET',
url: url + route + '?format=json'
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.equal(body.toString(), JSON.stringify(jsonContent))
t.ok(response.headers['content-type'].includes('application/json'))
})
})
})

t.test('html format with url parameter format', t => {
t.plan(13)

const options = {
Expand All @@ -500,6 +588,7 @@ t.test('dir list - url parameter format', t => {
}
}
const route = '/public/'
const jsonContent = { dirs: ['deep', 'shallow'], files: ['.example', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] }

helper.arrange(t, options, (url) => {
simple.concat({
Expand Down Expand Up @@ -528,7 +617,7 @@ t.test('dir list - url parameter format', t => {
}, (err, response, body) => {
t.error(err)
t.equal(response.statusCode, 200)
t.ok(body.toString())
t.equal(body.toString(), JSON.stringify(jsonContent))
t.ok(response.headers['content-type'].includes('application/json'))
})
})
Expand Down
2 changes: 1 addition & 1 deletion test/static.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2840,7 +2840,7 @@ t.test('routes should fallback to default errorHandler', t => {
})
})

t.test('precent encoded URLs in glob mode', (t) => {
t.test('percent encoded URLs in glob mode', (t) => {
t.plan(4)

const fastify = Fastify({})
Expand Down
2 changes: 1 addition & 1 deletion test/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ expectAssignable<FastifyStaticOptions>({
}
})

expectError<FastifyStaticOptions>({
expectAssignable<FastifyStaticOptions>({
root: '',
list: {
format: 'json',
Expand Down

0 comments on commit aeb37cf

Please sign in to comment.