Comparing version 3.0.0 to 3.0.1
@@ -135,2 +135,3 @@ // Load modules | ||
if (!response.source.settings.lookupCompressed || | ||
!response.request.connection.settings.compression || | ||
response.request.info.acceptEncoding !== 'gzip') { | ||
@@ -137,0 +138,0 @@ |
{ | ||
"name": "inert", | ||
"description": "Static file and directory handlers plugin for hapi.js", | ||
"version": "3.0.0", | ||
"version": "3.0.1", | ||
"repository": "git://github.com/hapijs/inert", | ||
@@ -27,3 +27,3 @@ "main": "lib/index.js", | ||
"code": "1.x.x", | ||
"hapi": "8.x.x", | ||
"hapi": "9.x.x", | ||
"lab": "5.x.x" | ||
@@ -30,0 +30,0 @@ }, |
221
README.md
@@ -1,2 +0,2 @@ | ||
#inert | ||
# inert | ||
@@ -8,1 +8,220 @@ Static file and directory handlers plugin for hapi.js. | ||
Lead Maintainer - [Gil Pedersen](https://github.com/kanongil) | ||
**inert** provides new [handler](https://github.com/hapijs/hapi/blob/master/API.md#serverhandlername-method) | ||
methods for serving static files and directories, as well as decorating the [reply](https://github.com/hapijs/hapi/blob/master/API.md#reply-interface) | ||
interface with a `file` method for serving file based resources. | ||
#### Features | ||
* Files are served with cache friendly `last-modified` and `etag` headers. | ||
* Generated file listings and custom indexes. | ||
* Precompressed file support for `content-encoding: gzip` responses. | ||
* File attachment support using `content-disposition` header. | ||
## Index | ||
- [Examples](#examples) | ||
- [Static file server](#static-file-server) | ||
- [Serving a single file](#serving-a-single-file) | ||
- [Customized file response](#customized-file-response) | ||
- [Usage](#usage) | ||
- [Registration options](#registration-options) | ||
- [`reply.file(path, [options])`](#replyfilepath-options) | ||
- [The `file` handler](#the-file-handler) | ||
- [The `directory` handler](#the-directory-handler) | ||
## Examples | ||
**inert** enables a number of common use cases for serving static assets. | ||
### Static file server | ||
The following creates a basic static file server that can be used to serve html content from the | ||
`public` directory on port 3000: | ||
```js | ||
var Path = require('path'); | ||
var Hapi = require('hapi'); | ||
var Inert = require('inert'); | ||
var server = new Hapi.Server({ | ||
connections: { | ||
routes: { | ||
files: { | ||
relativeTo: Path.join(__dirname, 'public') | ||
} | ||
} | ||
} | ||
}); | ||
server.connection({ port: 3000 }); | ||
server.register(Inert, function () {}); | ||
server.route({ | ||
method: 'GET', | ||
path: '/{param*}', | ||
handler: { | ||
directory: { | ||
path: '.', | ||
redirectToSlash: true, | ||
index: true | ||
} | ||
} | ||
}); | ||
server.start(function (err) { | ||
if (err) { | ||
throw err; | ||
} | ||
console.log('Server running at:', server.info.uri); | ||
}); | ||
``` | ||
### Serving a single file | ||
You can serve specific files using the `file` handler: | ||
```js | ||
server.route({ | ||
method: 'GET', | ||
path: '/{path*}', | ||
handler: { | ||
file: 'page.html' | ||
} | ||
}); | ||
``` | ||
### Customized file response | ||
If you need more control, the `reply.file()` method is available to use inside handlers: | ||
```js | ||
server.route({ | ||
method: 'GET', | ||
path: '/file', | ||
handler: function (request, reply) { | ||
var path = 'plain.txt'; | ||
if (request.headers['x-magic'] === 'sekret') { | ||
path = 'awesome.png'; | ||
} | ||
return reply.file(path).vary('x-magic'); | ||
} | ||
}); | ||
server.ext('onPostHandler', function (request, reply) { | ||
var response = request.response; | ||
if (response.isBoom && | ||
response.output.statusCode === 404) { | ||
return reply.file('404.html').code(404); | ||
} | ||
return reply.continue(); | ||
}); | ||
``` | ||
Note that paths for files served using the `reply.file()` handler are **NOT** guarded against | ||
access outside the `files.relativeTo` directory, so be careful to guard against malevolent user | ||
input. | ||
## Usage | ||
After registration, this plugin adds a new method to the `reply` object and exposes the `'file'` | ||
and `'directory'` route handlers. | ||
### Registration options | ||
**inert** accepts the following registration options: | ||
- `etagsCacheMaxSize` - sets the maximum number of file etag hash values stored in the | ||
etags cache. Defaults to `10000`. | ||
Note that **inert** uses the custom `'file'` `variety` to signal that the response is a static | ||
file generated by this plugin. | ||
### `reply.file(path, [options])` | ||
Transmits a file from the file system. The 'Content-Type' header defaults to the matching mime | ||
type based on filename extension.: | ||
- `path` - the file path. | ||
- `options` - optional settings: | ||
- `filename` - an optional filename to specify if sending a 'Content-Disposition' header, | ||
defaults to the basename of `path` | ||
- `mode` - specifies whether to include the 'Content-Disposition' header with the response. | ||
Available values: | ||
- `false` - header is not included. This is the default value. | ||
- `'attachment'` | ||
- `'inline'` | ||
- `lookupCompressed` - if `true`, looks for the same filename with the '.gz' suffix for a | ||
pre-compressed version of the file to serve if the request supports content encoding. | ||
Defaults to `false`. | ||
Returns a standard [response](https://github.com/hapijs/hapi/blob/master/API.md#response-object) object. | ||
The [response flow control rules](https://github.com/hapijs/hapi/blob/master/API.md#flow-control) **do not** apply. | ||
### The `file` handler | ||
Generates a static file endpoint for serving a single file. `file` can be set to: | ||
- a relative or absolute file path string (relative paths are resolved based on the | ||
route [`files`](https://github.com/hapijs/hapi/blob/master/API.md#route.config.files) | ||
configuration). | ||
- a function with the signature `function(request)` which returns the relative or absolute | ||
file path. | ||
- an object with one or more of the following options: | ||
- `path` - a path string or function as described above (required). | ||
- `filename` - an optional filename to specify if sending a 'Content-Disposition' | ||
header, defaults to the basename of `path` | ||
- `mode` - specifies whether to include the 'Content-Disposition' header with the | ||
response. Available values: | ||
- `false` - header is not included. This is the default value. | ||
- `'attachment'` | ||
- `'inline'` | ||
- `lookupCompressed` - if `true`, looks for the same filename with the '.gz' suffix | ||
for a pre-compressed version of the file to serve if the request supports content | ||
encoding. Defaults to `false`. | ||
### The `directory` handler | ||
Generates a directory endpoint for serving static content from a directory. | ||
Routes using the directory handler must include a path parameter at the end of the path | ||
string (e.g. `/path/to/somewhere/{param}` where the parameter name does not matter). The | ||
path parameter can use any of the parameter options (e.g. `{param}` for one level files | ||
only, `{param?}` for one level files or the directory root, `{param*}` for any level, or | ||
`{param*3}` for a specific level). If additional path parameters are present, they are | ||
ignored for the purpose of selecting the file system resource. The directory handler is an | ||
object with the following options: | ||
- `path` - (required) the directory root path (relative paths are resolved based on the | ||
route [`files`](https://github.com/hapijs/hapi/blob/master/API.md#route.config.files) | ||
configuration). Value can be: | ||
- a single path string used as the prefix for any resources requested by appending the | ||
request path parameter to the provided string. | ||
- an array of path strings. Each path will be attempted in order until a match is | ||
found (by following the same process as the single path string). | ||
- a function with the signature `function(request)` which returns the path string or | ||
an array of path strings. If the function returns an error, the error is passed back | ||
to the client in the response. | ||
- `index` - optional boolean|string|string[], determines if an index file will be served | ||
if found in the folder when requesting a directory. The given string or strings specify | ||
the name(s) of the index file to look for. If `true`, looks for 'index.html'. Any falsy | ||
value disables index file lookup. Defaults to `true`. | ||
- `listing` - optional boolean, determines if directory listing is generated when a | ||
directory is requested without an index document. | ||
Defaults to `false`. | ||
- `showHidden` - optional boolean, determines if hidden files will be shown and served. | ||
Defaults to `false`. | ||
- `redirectToSlash` - optional boolean, determines if requests for a directory without a | ||
trailing slash are redirected to the same path with the missing slash. Useful for | ||
ensuring relative links inside the response are resolved correctly. Disabled when the | ||
server config `router.stripTrailingSlash` is `true. `Defaults to `false`. | ||
- `lookupCompressed` - optional boolean, instructs the file processor to look for the same | ||
filename with the '.gz' suffix for a pre-compressed version of the file to serve if the | ||
request supports content encoding. Defaults to `false`. | ||
- `defaultExtension` - optional string, appended to file requests if the requested file is | ||
not found. Defaults to no extension. |
@@ -33,3 +33,3 @@ // Load modules | ||
var server = new Hapi.Server({ minimal: true, debug: debug }); | ||
var server = new Hapi.Server({ debug: debug }); | ||
server.connection(connection || { routes: { files: { relativeTo: __dirname } }, router: { stripTrailingSlash: false } }); | ||
@@ -36,0 +36,0 @@ server.register(Inert, Hoek.ignore); |
@@ -32,6 +32,6 @@ // Load modules | ||
var provisionServer = function (relativeTo, etagsCacheMaxSize) { | ||
var provisionServer = function (connection, etagsCacheMaxSize) { | ||
var server = new Hapi.Server({ minimal: true }); | ||
server.connection({ routes: { files: { relativeTo: relativeTo } } }); | ||
var server = new Hapi.Server(); | ||
server.connection(connection || {}); | ||
server.register(etagsCacheMaxSize !== undefined ? { register: Inert, options: { etagsCacheMaxSize: etagsCacheMaxSize } } : Inert, Hoek.ignore); | ||
@@ -43,3 +43,3 @@ return server; | ||
var server = provisionServer(__dirname); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }); | ||
var handler = function (request, reply) { | ||
@@ -97,3 +97,3 @@ | ||
var server = provisionServer('./'); | ||
var server = provisionServer({ routes: { files: { relativeTo: './' } } }); | ||
server.route({ method: 'GET', path: '/', handler: { file: { path: './package.json', mode: 'inline' } } }); | ||
@@ -113,3 +113,3 @@ | ||
var server = provisionServer('./'); | ||
var server = provisionServer({ routes: { files: { relativeTo: './' } } }); | ||
server.route({ method: 'GET', path: '/', handler: { file: { path: './package.json', mode: 'inline', filename: 'attachment.json' } } }); | ||
@@ -174,3 +174,3 @@ | ||
var server = provisionServer(__dirname); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }); | ||
var handler = function (request, reply) { | ||
@@ -195,3 +195,3 @@ | ||
var server = provisionServer(__dirname); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }); | ||
var handler = function (request, reply) { | ||
@@ -216,3 +216,3 @@ | ||
var server = provisionServer(__dirname); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }); | ||
var handler = function (request, reply) { | ||
@@ -237,3 +237,3 @@ | ||
var server = provisionServer(__dirname); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }); | ||
var handler = function (request, reply) { | ||
@@ -258,3 +258,3 @@ | ||
var server = provisionServer('/no/such/path/x1'); | ||
var server = provisionServer({ routes: { files: { relativeTo: '/no/such/path/x1' } } }); | ||
@@ -285,3 +285,3 @@ server.route({ method: 'GET', path: '/filenotfound', handler: { file: 'nopes' } }); | ||
var server = provisionServer(__dirname); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }); | ||
server.route({ method: 'GET', path: '/staticfile', handler: { file: Path.join(__dirname, '..', 'package.json') } }); | ||
@@ -305,3 +305,3 @@ | ||
var server = provisionServer(__dirname); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }); | ||
server.route({ method: 'GET', path: '/filefn/{file}', handler: { file: filenameFn } }); | ||
@@ -320,3 +320,3 @@ | ||
var server = provisionServer('.'); | ||
var server = provisionServer({ routes: { files: { relativeTo: '.' } } }); | ||
var relativeHandler = function (request, reply) { | ||
@@ -340,3 +340,3 @@ | ||
var server = provisionServer(__dirname); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }); | ||
server.route({ method: 'GET', path: '/relativestaticfile', handler: { file: '../package.json' } }); | ||
@@ -367,3 +367,3 @@ | ||
var server = provisionServer(__dirname); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }); | ||
var handler = function (request, reply) { | ||
@@ -385,3 +385,3 @@ | ||
var server = provisionServer(__dirname, 0); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }, 0); | ||
server.route({ method: 'GET', path: '/note', handler: { file: './file/note.txt' } }); | ||
@@ -407,3 +407,3 @@ | ||
var server = provisionServer(__dirname); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }); | ||
@@ -743,3 +743,3 @@ server.route({ method: 'GET', path: '/note', handler: { file: './file/note.txt' } }); | ||
var server = provisionServer(__dirname); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }); | ||
var handler = function (request, reply) { | ||
@@ -764,3 +764,3 @@ | ||
var server = provisionServer(__dirname); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }); | ||
var handler = function (request, reply) { | ||
@@ -785,3 +785,3 @@ | ||
var server = provisionServer(__dirname); | ||
var server = provisionServer({ routes: { files: { relativeTo: __dirname } } }); | ||
var handler = function (request, reply) { | ||
@@ -858,2 +858,3 @@ | ||
expect(res.headers['content-type']).to.equal('image/png'); | ||
expect(res.headers['content-encoding']).to.not.exist(); | ||
expect(res.payload).to.exist(); | ||
@@ -864,2 +865,16 @@ done(); | ||
it('ignores precompressed file when connection compression is disabled', function (done) { | ||
var server = provisionServer({ compression: false }); | ||
server.route({ method: 'GET', path: '/file', handler: { file: { path: './test/file/image.png', lookupCompressed: true } } }); | ||
server.inject({ url: '/file', headers: { 'accept-encoding': 'gzip' } }, function (res) { | ||
expect(res.headers['content-type']).to.equal('image/png'); | ||
expect(res.headers['content-encoding']).to.not.exist(); | ||
expect(res.payload).to.exist(); | ||
done(); | ||
}); | ||
}); | ||
it('does not throw an error when adding a route with a parameter and function path', function (done) { | ||
@@ -866,0 +881,0 @@ |
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
381236
26
1940
227