fastify-static
Advanced tools
Comparing version 0.5.0 to 0.6.0
79
index.js
@@ -10,13 +10,4 @@ 'use strict' | ||
const DEFAULT_500_PAGE = path.join(__dirname, 'static', '500.html') | ||
const DEFAULT_403_PAGE = path.join(__dirname, 'static', '403.html') | ||
const DEFAULT_404_PAGE = path.join(__dirname, 'static', '404.html') | ||
function fastifyStatic (fastify, opts, next) { | ||
const error = checkPathsForErrors({ | ||
root: opts.root, | ||
page500Path: opts.page500Path, | ||
page403Path: opts.page403Path, | ||
page404Path: opts.page404Path | ||
}) | ||
const error = checkRootPathForErrors(opts.root) | ||
if (error !== undefined) return next(error) | ||
@@ -42,24 +33,6 @@ | ||
} | ||
const page500 = opts.page500Path || DEFAULT_500_PAGE | ||
const page403 = opts.page403Path || DEFAULT_403_PAGE | ||
const page404 = opts.page404Path || DEFAULT_404_PAGE | ||
function overwriteStatusCode (res, statusCode) { | ||
return function () { res.statusCode = statusCode } | ||
} | ||
function pumpSendToReply (request, reply, pathname) { | ||
const sendStream = send(request.req, pathname, sendOptions) | ||
function servePathWithStatusCodeWrapper (page, statusCode) { | ||
return function servePage (req, res) { | ||
send(req, page) | ||
.on('stream', overwriteStatusCode(res, statusCode)) | ||
.pipe(res) | ||
} | ||
} | ||
const serve404 = servePathWithStatusCodeWrapper(page404, 404) | ||
const serve403 = servePathWithStatusCodeWrapper(page403, 403) | ||
const serve500 = servePathWithStatusCodeWrapper(page500, 500) | ||
function pumpSendToReply (req, reply, pathname) { | ||
const sendStream = send(req, pathname, sendOptions) | ||
if (setHeaders !== undefined) { | ||
@@ -70,5 +43,7 @@ sendStream.on('headers', setHeaders) | ||
sendStream.on('error', function (err) { | ||
if (err.statusCode === 404) return serve404(req, reply.res) | ||
if (err.statusCode === 403) return serve403(req, reply.res) | ||
serve500(req, reply.res) | ||
if (err.status === 404) { | ||
reply.notFound() | ||
} else { | ||
reply.send(err) | ||
} | ||
}) | ||
@@ -83,11 +58,11 @@ | ||
fastify.get(prefix + '*', function (req, reply) { | ||
pumpSendToReply(req.req, reply, '/' + req.params['*']) | ||
pumpSendToReply(req, reply, '/' + req.params['*']) | ||
}) | ||
fastify.get(prefix, function (req, reply) { | ||
pumpSendToReply(req.req, reply, '/') | ||
pumpSendToReply(req, reply, '/') | ||
}) | ||
fastify.decorateReply('sendFile', function (filePath) { | ||
pumpSendToReply(this.request.req, this, filePath) | ||
pumpSendToReply(this.request, this, filePath) | ||
}) | ||
@@ -98,21 +73,17 @@ | ||
function checkPathsForErrors (paths) { | ||
if (paths.root === undefined) return new Error('"root" option is required') | ||
function checkRootPathForErrors (rootPath) { | ||
if (rootPath === undefined) { | ||
return new Error('"root" option is required') | ||
} | ||
if (typeof rootPath !== 'string') { | ||
return new Error('"root" option must be a string') | ||
} | ||
if (path.isAbsolute(rootPath) === false) { | ||
return new Error('"root" option must be an absolute path') | ||
} | ||
var err = checkPath(paths.root, 'root', 'isDirectory') | ||
if (!err && paths.page500Path !== undefined) err = checkPath(paths.page500Path, 'page500Path', 'isFile') | ||
if (!err && paths.page403Path !== undefined) err = checkPath(paths.page403Path, 'page403Path', 'isFile') | ||
if (!err && paths.page404Path !== undefined) err = checkPath(paths.page404Path, 'page404Path', 'isFile') | ||
return err | ||
} | ||
function checkPath (p, pathName, statMethod) { | ||
if (typeof p !== 'string') return new Error(`"${pathName}" option must be a string`) | ||
if (path.isAbsolute(p) === false) return new Error(`"${pathName}" option must be an absolute path`) | ||
let pathStat | ||
try { | ||
pathStat = statSync(p) | ||
pathStat = statSync(rootPath) | ||
} catch (e) { | ||
@@ -122,7 +93,7 @@ return e | ||
if (pathStat[statMethod]() === false) { | ||
return new Error(`${pathName} option must point to a ${statMethod.slice(2).toLowerCase()}`) | ||
if (pathStat.isDirectory() === false) { | ||
return new Error('"root" option must point to a directory') | ||
} | ||
} | ||
module.exports = fp(fastifyStatic, '>= 0.35.0') | ||
module.exports = fp(fastifyStatic, '>= 0.38.0') |
{ | ||
"name": "fastify-static", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"description": "Plugin for serving static files as fast as possible.", | ||
@@ -33,3 +33,3 @@ "main": "index.js", | ||
"coveralls": "^3.0.0", | ||
"fastify": "^0.36.0", | ||
"fastify": "^0.38.0", | ||
"pre-commit": "^1.2.2", | ||
@@ -40,4 +40,4 @@ "proxyquire": "^1.8.0", | ||
"standard": "^10.0.3", | ||
"tap": "^11.0.0" | ||
"tap": "^11.0.1" | ||
} | ||
} |
@@ -19,5 +19,2 @@ # fastify-static | ||
prefix: '/public/', // optional: default '/' | ||
page404Path: path.join(__dirname, 'public', '404.html'), // optional | ||
page403Path: path.join(__dirname, 'public', '403.html'), // optional | ||
page500Path: path.join(__dirname, 'public', '500.html') // optional | ||
}) | ||
@@ -45,7 +42,2 @@ | ||
#### `page404Path`, `page403Path`, `page500Path` | ||
The absolute path to an HTML file to send as a response for the corresponding | ||
error status code. A generic error page is sent by default. | ||
#### `setHeaders` | ||
@@ -78,4 +70,16 @@ | ||
#### Handling 404s | ||
If a request matches the URL `prefix` but a file cannot be found for the | ||
request, Fastify's 404 handler will be called. You can set a custom 404 | ||
handler with [`fastify.setNotFoundHandler()`](https://www.fastify.io/docs/latest/Server-Methods/#setnotfoundhandler). | ||
### Handling Errors | ||
If an error occurs while trying to send a file, the error will be passed | ||
to Fastify's error handler. You can set a custom error handler with | ||
[`fastify.setErrorHandler()`](https://www.fastify.io/docs/latest/Server-Methods/#seterrorhandler). | ||
## License | ||
Licensed under [MIT](./LICENSE) |
@@ -15,5 +15,2 @@ 'use strict' | ||
const body403 = fs.readFileSync('./static/403.html').toString('utf8') | ||
const body404 = fs.readFileSync('./static/404.html').toString('utf8') | ||
const GENERIC_RESPONSE_CHECK_COUNT = 5 | ||
@@ -28,2 +25,8 @@ function genericResponseChecks (t, response) { | ||
const GENERIC_ERROR_RESPONSE_CHECK_COUNT = 2 | ||
function genericErrorResponseChecks (t, response) { | ||
t.strictEqual(response.headers['content-type'], 'application/json') | ||
t.ok(response.headers.date) | ||
} | ||
t.test('register /static', t => { | ||
@@ -120,3 +123,3 @@ t.plan(9) | ||
t.test('/static/this/path/doesnt/exist.html', t => { | ||
t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
request.get({ | ||
@@ -129,4 +132,3 @@ method: 'GET', | ||
t.strictEqual(response.statusCode, 404) | ||
t.strictEqual(body, body404) | ||
genericResponseChecks(t, response) | ||
genericErrorResponseChecks(t, response) | ||
}) | ||
@@ -136,3 +138,3 @@ }) | ||
t.test('/static/../index.js', t => { | ||
t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
request.get({ | ||
@@ -145,4 +147,3 @@ method: 'GET', | ||
t.strictEqual(response.statusCode, 403) | ||
t.strictEqual(body, body403) | ||
genericResponseChecks(t, response) | ||
genericErrorResponseChecks(t, response) | ||
}) | ||
@@ -244,3 +245,3 @@ }) | ||
t.test('/static/this/path/doesnt/exist.html', t => { | ||
t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
request.get({ | ||
@@ -253,4 +254,3 @@ method: 'GET', | ||
t.strictEqual(response.statusCode, 404) | ||
t.strictEqual(body, body404) | ||
genericResponseChecks(t, response) | ||
genericErrorResponseChecks(t, response) | ||
}) | ||
@@ -260,3 +260,3 @@ }) | ||
t.test('/static/../index.js', t => { | ||
t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
request.get({ | ||
@@ -269,4 +269,3 @@ method: 'GET', | ||
t.strictEqual(response.statusCode, 403) | ||
t.strictEqual(body, body403) | ||
genericResponseChecks(t, response) | ||
genericErrorResponseChecks(t, response) | ||
}) | ||
@@ -277,2 +276,74 @@ }) | ||
t.test('error responses can be customized with fastify.setErrorHandler()', t => { | ||
t.plan(2) | ||
const pluginOptions = { | ||
root: path.join(__dirname, '/static') | ||
} | ||
const fastify = require('fastify')() | ||
fastify.setErrorHandler(function errorHandler (err, reply) { | ||
reply.send(err.status + ' Custom error message') | ||
}) | ||
fastify.register(fastifyStatic, pluginOptions) | ||
fastify.listen(0, err => { | ||
t.error(err) | ||
fastify.server.unref() | ||
t.test('/../index.js', t => { | ||
t.plan(4) | ||
request.get({ | ||
method: 'GET', | ||
uri: 'http://localhost:' + fastify.server.address().port + '/../index.js', | ||
followRedirect: false | ||
}, (err, response, body) => { | ||
t.error(err) | ||
t.strictEqual(response.statusCode, 403) | ||
t.strictEqual(response.headers['content-type'], 'text/plain') | ||
t.strictEqual(body, '403 Custom error message') | ||
}) | ||
}) | ||
}) | ||
}) | ||
t.test('not found responses can be customized with fastify.setNotFoundHandler()', t => { | ||
t.plan(2) | ||
const pluginOptions = { | ||
root: path.join(__dirname, '/static') | ||
} | ||
const fastify = require('fastify')() | ||
fastify.setNotFoundHandler(function notFoundHandler (request, reply) { | ||
reply.code(404).send(request.req.url + ' Not Found') | ||
}) | ||
fastify.register(fastifyStatic, pluginOptions) | ||
fastify.listen(0, err => { | ||
t.error(err) | ||
fastify.server.unref() | ||
t.test('/path/does/not/exist.html', t => { | ||
t.plan(4) | ||
request.get({ | ||
method: 'GET', | ||
uri: 'http://localhost:' + fastify.server.address().port + '/path/does/not/exist.html', | ||
followRedirect: false | ||
}, (err, response, body) => { | ||
t.error(err) | ||
t.strictEqual(response.statusCode, 404) | ||
t.strictEqual(response.headers['content-type'], 'text/plain') | ||
t.strictEqual(body, '/path/does/not/exist.html Not Found') | ||
}) | ||
}) | ||
}) | ||
}) | ||
t.test('sendFile', t => { | ||
@@ -388,3 +459,3 @@ t.plan(2) | ||
t.test('errors', t => { | ||
t.plan(12) | ||
t.plan(6) | ||
@@ -395,5 +466,6 @@ t.test('no root', t => { | ||
const fastify = require('fastify')({logger: false}) | ||
fastify.register(fastifyStatic, pluginOptions, err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
fastify.register(fastifyStatic, pluginOptions) | ||
.ready(err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
}) | ||
@@ -405,5 +477,6 @@ | ||
const fastify = require('fastify')({logger: false}) | ||
fastify.register(fastifyStatic, pluginOptions, err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
fastify.register(fastifyStatic, pluginOptions) | ||
.ready(err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
}) | ||
@@ -415,5 +488,6 @@ | ||
const fastify = require('fastify')({logger: false}) | ||
fastify.register(fastifyStatic, pluginOptions, err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
fastify.register(fastifyStatic, pluginOptions) | ||
.ready(err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
}) | ||
@@ -425,5 +499,6 @@ | ||
const fastify = require('fastify')({logger: false}) | ||
fastify.register(fastifyStatic, pluginOptions, err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
fastify.register(fastifyStatic, pluginOptions) | ||
.ready(err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
}) | ||
@@ -435,61 +510,8 @@ | ||
const fastify = require('fastify')({logger: false}) | ||
fastify.register(fastifyStatic, pluginOptions, err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
fastify.register(fastifyStatic, pluginOptions) | ||
.ready(err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
}) | ||
t.test('page500Path is not a string', t => { | ||
t.plan(1) | ||
const pluginOptions = { root: __dirname, page500Path: 42 } | ||
const fastify = require('fastify')({logger: false}) | ||
fastify.register(fastifyStatic, pluginOptions, err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
}) | ||
t.test('page500Path is not a file', t => { | ||
t.plan(1) | ||
const pluginOptions = { root: __dirname, page500Path: __dirname } | ||
const fastify = require('fastify')({logger: false}) | ||
fastify.register(fastifyStatic, pluginOptions, err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
}) | ||
t.test('page404Path is not a string', t => { | ||
t.plan(1) | ||
const pluginOptions = { root: __dirname, page404Path: 42 } | ||
const fastify = require('fastify')({logger: false}) | ||
fastify.register(fastifyStatic, pluginOptions, err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
}) | ||
t.test('page404Path is not a file', t => { | ||
t.plan(1) | ||
const pluginOptions = { root: __dirname, page404Path: __dirname } | ||
const fastify = require('fastify')({logger: false}) | ||
fastify.register(fastifyStatic, pluginOptions, err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
}) | ||
t.test('page403Path is not a string', t => { | ||
t.plan(1) | ||
const pluginOptions = { root: __dirname, page403Path: 42 } | ||
const fastify = require('fastify')({logger: false}) | ||
fastify.register(fastifyStatic, pluginOptions, err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
}) | ||
t.test('page403Path is not a file', t => { | ||
t.plan(1) | ||
const pluginOptions = { root: __dirname, page403Path: __dirname } | ||
const fastify = require('fastify')({logger: false}) | ||
fastify.register(fastifyStatic, pluginOptions, err => { | ||
t.equal(err.constructor, Error) | ||
}) | ||
}) | ||
t.test('setHeaders is not a function', t => { | ||
@@ -499,6 +521,7 @@ t.plan(1) | ||
const fastify = require('fastify')({logger: false}) | ||
fastify.register(fastifyStatic, pluginOptions, err => { | ||
t.equal(err.constructor, TypeError) | ||
}) | ||
fastify.register(fastifyStatic, pluginOptions) | ||
.ready(err => { | ||
t.equal(err.constructor, TypeError) | ||
}) | ||
}) | ||
}) |
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
83
0
22635
10
515