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
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,52 @@ fastify.get('/another/path', function (req, reply) {

```

### Options
Copy link
Member

Choose a reason for hiding this comment

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

Can we link to the options in send docs instead? I’m not a fun of duplicating them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure. Would you like me to keep the descriptions for the Fastify options though?

Copy link
Member

Choose a reason for hiding this comment

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

yes!


#### `root` (required)

The absolute path of the directory that contains the files to serve.
The file to serve will be determined by combining `req.url` with the
provided root directory.

#### `prefix`

Default: `'/'`

A URL path prefix used to create a virtual mount path for the static directory.

#### `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`

Default: `undefined`

A function to set custom headers on the response. Alterations to the headers
must be done synchronously. The function is called as `fn(res, path, stat)`,
where the arguments are:

- `res` The response object.
- `path` The path of the file that is being sent.
- `stat` The stat object of the file that is being sent.

#### `send` Options

The following options are also supported and will be passed directly to the
[`send`](https://www.npmjs.com/package/send) module:

- [`acceptRanges`](https://www.npmjs.com/package/send#acceptranges)
- [`cacheControl`](https://www.npmjs.com/package/send#cachecontrol)
- [`dotfiles`](https://www.npmjs.com/package/send#dotfiles)
- [`etag`](https://www.npmjs.com/package/send#etag)
- [`extensions`](https://www.npmjs.com/package/send#extensions)
- [`immutable`](https://www.npmjs.com/package/send#immutable)
- [`index`](https://www.npmjs.com/package/send#index)
- [`lastModified`](https://www.npmjs.com/package/send#lastmodified)
- [`maxAge`](https://www.npmjs.com/package/send#maxage)

## License

Licensed under [MIT](./LICENSE)
25 changes: 23 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,24 @@ function fastifyStatic (fastify, opts, next) {
})
if (error !== undefined) return next(error)

const root = opts.root
const setHeaders = opts.setHeaders

if (setHeaders !== undefined && typeof setHeaders !== 'function') {
return next(new TypeError('The `setHeaders` option must be a function'))
}

const sendOptions = {
root: opts.root,
acceptRanges: opts.acceptRanges,
cacheControl: opts.cacheControl,
dotfiles: opts.dotfiles,
etag: opts.etag,
extensions: opts.extensions,
immutable: opts.immutable,
index: opts.index,
lastModified: opts.lastModified,
maxAge: opts.maxAge
}
const page500 = opts.page500Path || DEFAULT_500_PAGE
const page403 = opts.page403Path || DEFAULT_403_PAGE
const page404 = opts.page404Path || DEFAULT_404_PAGE
Expand All @@ -41,7 +58,11 @@ function fastifyStatic (fastify, opts, next) {
const serve500 = servePathWithStatusCodeWrapper(page500, 500)

function pumpSendToReply (req, reply, pathname) {
const sendStream = send(req, pathname, { root })
const sendStream = send(req, pathname, sendOptions)

if (setHeaders !== undefined) {
sendStream.on('headers', setHeaders)
}

sendStream.on('error', function (err) {
if (err.statusCode === 404) return serve404(req, reply.res)
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"coveralls": "^3.0.0",
"fastify": "^0.35.0",
"pre-commit": "^1.2.2",
"proxyquire": "^1.8.0",
"request": "^2.81.0",
"snazzy": "^7.0.0",
"standard": "^10.0.3",
Expand Down
82 changes: 79 additions & 3 deletions test/static.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ t.test('register /static/', t => {
})
})

t.test('send', t => {
t.test('sendFile', t => {
t.plan(2)

const pluginOptions = {
Expand All @@ -283,7 +283,7 @@ t.test('send', t => {

fastify.server.unref()

t.test('reply.send()', t => {
t.test('reply.sendFile()', t => {
t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT)
request.get({
method: 'GET',
Expand All @@ -306,8 +306,75 @@ t.test('prefix default', t => {
t.doesNotThrow(() => fastify.register(fastifyStatic, pluginOptions))
})

t.test('errors', t => {
t.test('send options', t => {
t.plan(11)
const pluginOptions = {
root: path.join(__dirname, '/static'),
acceptRanges: 'acceptRanges',
cacheControl: 'cacheControl',
dotfiles: 'dotfiles',
etag: 'etag',
extensions: 'extensions',
immutable: 'immutable',
index: 'index',
lastModified: 'lastModified',
maxAge: 'maxAge'
}
const fastify = require('fastify')({logger: false})
const fastifyStatic = require('proxyquire')('../', {
send: function sendStub (req, pathName, options) {
t.strictEqual(pathName, '/index.html')
t.strictEqual(options.root, path.join(__dirname, '/static'))
t.strictEqual(options.acceptRanges, 'acceptRanges')
t.strictEqual(options.cacheControl, 'cacheControl')
t.strictEqual(options.dotfiles, 'dotfiles')
t.strictEqual(options.etag, 'etag')
t.strictEqual(options.extensions, 'extensions')
t.strictEqual(options.immutable, 'immutable')
t.strictEqual(options.index, 'index')
t.strictEqual(options.lastModified, 'lastModified')
t.strictEqual(options.maxAge, 'maxAge')
return { on: () => {}, pipe: () => {} }
}
})
fastify.register(fastifyStatic, pluginOptions)
fastify.inject({url: '/index.html'})
})

t.test('setHeaders option', t => {
t.plan(6 + GENERIC_RESPONSE_CHECK_COUNT)

const pluginOptions = {
root: path.join(__dirname, 'static'),
setHeaders: function (res, pathName) {
t.strictEqual(pathName, path.join(__dirname, 'static/index.html'))
res.setHeader('X-Test-Header', 'test')
}
}
const fastify = require('fastify')()
fastify.register(fastifyStatic, pluginOptions)

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

fastify.server.unref()

request.get({
method: 'GET',
uri: 'http://localhost:' + fastify.server.address().port + '/index.html',
followRedirect: false
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(response.headers['x-test-header'], 'test')
t.strictEqual(body, indexContent)
genericResponseChecks(t, response)
})
})
})

t.test('errors', t => {
t.plan(12)

t.test('no root', t => {
t.plan(1)
Expand Down Expand Up @@ -407,4 +474,13 @@ t.test('errors', t => {
t.equal(err.constructor, Error)
})
})

t.test('setHeaders is not a function', t => {
t.plan(1)
const pluginOptions = { root: __dirname, setHeaders: 'headers' }
const fastify = require('fastify')({logger: false})
fastify.register(fastifyStatic, pluginOptions, err => {
t.equal(err.constructor, TypeError)
})
})
})