fastify-static
Advanced tools
Comparing version 4.4.1 to 4.4.2
43
index.js
@@ -45,2 +45,13 @@ 'use strict' | ||
if (opts.prefix === undefined) opts.prefix = '/' | ||
let prefix = opts.prefix | ||
if (!opts.prefixAvoidTrailingSlash) { | ||
prefix = | ||
opts.prefix[opts.prefix.length - 1] === '/' | ||
? opts.prefix | ||
: opts.prefix + '/' | ||
} | ||
function pumpSendToReply ( | ||
@@ -150,3 +161,4 @@ request, | ||
options: opts.list, | ||
route: pathname | ||
route: pathname, | ||
prefix | ||
}).catch((err) => reply.send(err)) | ||
@@ -160,2 +172,4 @@ return | ||
} catch (error) { | ||
// the try-catch here is actually unreachable, but we keep it for safety and prevent DoS attack | ||
/* istanbul ignore next */ | ||
reply.send(error) | ||
@@ -176,3 +190,4 @@ } | ||
options: opts.list, | ||
route: pathname | ||
route: pathname, | ||
prefix | ||
}).catch((err) => reply.send(err)) | ||
@@ -221,13 +236,2 @@ return | ||
if (opts.prefix === undefined) opts.prefix = '/' | ||
let prefix = opts.prefix | ||
if (!opts.prefixAvoidTrailingSlash) { | ||
prefix = | ||
opts.prefix[opts.prefix.length - 1] === '/' | ||
? opts.prefix | ||
: opts.prefix + '/' | ||
} | ||
const errorHandler = (error, request, reply) => { | ||
@@ -455,6 +459,9 @@ if (error && error.code === 'ERR_STREAM_PREMATURE_CLOSE') { | ||
function getRedirectUrl (url) { | ||
if (url.startsWith('//') || url.startsWith('/\\')) { | ||
// malicous redirect | ||
return '/' | ||
let i = 0 | ||
// we detech how many slash before a valid path | ||
for (i; i < url.length; i++) { | ||
if (url[i] !== '/' && url[i] !== '\\') break | ||
} | ||
// turns all leading / or \ into a single / | ||
url = '/' + url.substr(i) | ||
try { | ||
@@ -464,4 +471,8 @@ const parsed = new URL(url, 'http://localhost.com/') | ||
} catch (error) { | ||
// the try-catch here is actually unreachable, but we keep it for safety and prevent DoS attack | ||
/* istanbul ignore next */ | ||
const err = new Error(`Invalid redirect URL: ${url}`) | ||
/* istanbul ignore next */ | ||
err.statusCode = 400 | ||
/* istanbul ignore next */ | ||
throw err | ||
@@ -468,0 +479,0 @@ } |
@@ -101,3 +101,3 @@ 'use strict' | ||
*/ | ||
send: async function ({ reply, dir, options, route }) { | ||
send: async function ({ reply, dir, options, route, prefix }) { | ||
let entries | ||
@@ -124,4 +124,4 @@ try { | ||
const html = options.render( | ||
entries.dirs.map(entry => dirList.htmlInfo(entry, route)), | ||
entries.files.map(entry => dirList.htmlInfo(entry, route))) | ||
entries.dirs.map(entry => dirList.htmlInfo(entry, route, prefix, options)), | ||
entries.files.map(entry => dirList.htmlInfo(entry, route, prefix, options))) | ||
reply.type('text/html').send(html) | ||
@@ -136,4 +136,12 @@ }, | ||
*/ | ||
htmlInfo: function (entry, route) { | ||
return { href: path.join(path.dirname(route), entry.name).replace(/\\/g, '/'), name: entry.name, stats: entry.stats, extendedInfo: entry.extendedInfo } | ||
htmlInfo: function (entry, route, prefix, options) { | ||
if (options.names && options.names.includes(path.basename(route))) { | ||
route = path.normalize(path.join(route, '..')) | ||
} | ||
return { | ||
href: path.join(prefix, route, entry.name).replace(/\\/g, '/'), | ||
name: entry.name, | ||
stats: entry.stats, | ||
extendedInfo: entry.extendedInfo | ||
} | ||
}, | ||
@@ -140,0 +148,0 @@ |
{ | ||
"name": "fastify-static", | ||
"version": "4.4.1", | ||
"version": "4.4.2", | ||
"description": "Plugin for serving static files as fast as possible.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -53,3 +53,3 @@ 'use strict' | ||
format: 'html' | ||
// no render function | ||
// no render function | ||
} | ||
@@ -163,12 +163,12 @@ }, | ||
<ul> | ||
<li><a href="/deep">deep</a></li> | ||
<li><a href="/shallow">shallow</a></li> | ||
<li><a href="/public/deep">deep</a></li> | ||
<li><a href="/public/shallow">shallow</a></li> | ||
</ul> | ||
<ul> | ||
<li><a href="/.example" target="_blank">.example</a></li> | ||
<li><a href="/a .md" target="_blank">a .md</a></li> | ||
<li><a href="/foo.html" target="_blank">foo.html</a></li> | ||
<li><a href="/foobar.html" target="_blank">foobar.html</a></li> | ||
<li><a href="/index.css" target="_blank">index.css</a></li> | ||
<li><a href="/index.html" target="_blank">index.html</a></li> | ||
<li><a href="/public/.example" target="_blank">.example</a></li> | ||
<li><a href="/public/a .md" target="_blank">a .md</a></li> | ||
<li><a href="/public/foo.html" target="_blank">foo.html</a></li> | ||
<li><a href="/public/foobar.html" target="_blank">foobar.html</a></li> | ||
<li><a href="/public/index.css" target="_blank">index.css</a></li> | ||
<li><a href="/public/index.html" target="_blank">index.html</a></li> | ||
</ul> | ||
@@ -195,12 +195,12 @@ </body></html> | ||
<ul> | ||
<li><a href="/deep">deep</a></li> | ||
<li><a href="/shallow">shallow</a></li> | ||
<li><a href="/public/deep">deep</a></li> | ||
<li><a href="/public/shallow">shallow</a></li> | ||
</ul> | ||
<ul> | ||
<li><a href="/.example" target="_blank">.example</a></li> | ||
<li><a href="/a .md" target="_blank">a .md</a></li> | ||
<li><a href="/foo.html" target="_blank">foo.html</a></li> | ||
<li><a href="/foobar.html" target="_blank">foobar.html</a></li> | ||
<li><a href="/index.css" target="_blank">index.css</a></li> | ||
<li><a href="/index.html" target="_blank">index.html</a></li> | ||
<li><a href="/public/.example" target="_blank">.example</a></li> | ||
<li><a href="/public/a .md" target="_blank">a .md</a></li> | ||
<li><a href="/public/foo.html" target="_blank">foo.html</a></li> | ||
<li><a href="/public/foobar.html" target="_blank">foobar.html</a></li> | ||
<li><a href="/public/index.css" target="_blank">index.css</a></li> | ||
<li><a href="/public/index.html" target="_blank">index.html</a></li> | ||
</ul> | ||
@@ -246,2 +246,49 @@ </body></html> | ||
t.test('dir list href nested structure', t => { | ||
t.plan(6) | ||
const options = { | ||
root: path.join(__dirname, '/static'), | ||
prefix: '/public', | ||
index: false, | ||
list: { | ||
format: 'html', | ||
names: ['index', 'index.htm'], | ||
render (dirs, files) { | ||
return dirs[0].href | ||
} | ||
} | ||
} | ||
const routes = [ | ||
{ path: '/public/', response: '/public/deep' }, | ||
{ path: '/public/index', response: '/public/deep' }, | ||
{ path: '/public/deep/', response: '/public/deep/path' }, | ||
{ path: '/public/deep/index.htm', response: '/public/deep/path' }, | ||
{ path: '/public/deep/path/', response: '/public/deep/path/for' } | ||
] | ||
helper.arrange(t, options, (url) => { | ||
for (const route of routes) { | ||
t.test(route.path, t => { | ||
t.plan(5) | ||
simple.concat({ | ||
method: 'GET', | ||
url: url + route.path | ||
}, (err, response, body) => { | ||
t.error(err) | ||
t.equal(response.statusCode, 200) | ||
t.equal(body.toString(), route.response) | ||
simple.concat({ | ||
method: 'GET', | ||
url: url + body.toString() | ||
}, (err, response, body) => { | ||
t.error(err) | ||
t.equal(response.statusCode, 200) | ||
}) | ||
}) | ||
}) | ||
} | ||
}) | ||
}) | ||
t.test('dir list html format - stats', t => { | ||
@@ -248,0 +295,0 @@ t.plan(7) |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
349182
4316