Inert
repository·master·Indexed 42 days ago
https://github.com/hapijs/inertA plugin for hapi.js (version 7.1.2) that provides specialized handlers for serving static files and directories. It adds the h.file() method to the response toolkit and exposes 'file' and 'directory' handlers for route configurations, including support for ETag caching, pre-compressed files, and directory listings.
What's inside Inert
- @hapi/inert is a plugin for the hapi web framework that provides handlers for serving static files and directories. While it is designed to work seamlessly within the hapi ecosystem, it is a standalone module that can be used with other web frameworks.
Install and register @hapi/inert
masterTo use
@hapi/inertfor serving static files, you must first register it with your Hapi server. Once registered, it provides theh.file()method on the response toolkit and exposes'file'and'directory'handlers for your routes.const Hapi = require('@hapi/hapi'); const Inert = require('@hapi/inert'); const server = new Hapi.Server({ port: 3000, routes: { files: { relativeTo: Path.join(__dirname, 'public') } } }); const provision = async () => { await server.register(Inert); // ... setup routes await server.start(); }; provision();Configure @hapi/inert server options
masterYou can configure
@hapi/inertvia theplugins.inertkey in your Hapi server configuration.etagsCacheMaxSize(number): Sets the maximum number of file etag hash values stored in the cache. Defaults to1000.
Register the @hapi/inert plugin
masterTo use Inert in your hapi server, register it as a plugin. Inert does not support registration options; the
optionsobject passed toregistermust be empty. It requireshapiversion>=20.0.0.await server.register({ plugin: require('@hapi/inert'), options: {} });Handle file access errors
masterInert uses Boom to signal file access errors:
Boom.notFound(): For missing or hidden files.Boom.forbidden(): For files that exist but cannot be accessed.Boom.internal()/'system': For unexpected configuration or processing errors.
Errors may contain an
err.data.pathproperty indicating the path that failed.Serve a single file with the file handler
masterThe
filehandler is used in a route configuration to serve a specific file. Thepathcan be a string (relative to the route'sfiles.relativeToconfig) or a function that returns the path.server.route({ method: 'GET', path: '/{path*}', handler: { file: 'page.html' } });Create a static file server with the directory handler
masterThe
directoryhandler allows you to serve an entire folder. Routes using this handler must include a path parameter at the end of the path string (e.g.,/{param*}).Common options for the
directoryhandler:path: The directory root (string, array of strings, or a function returning them).index: Iftrue, looks forindex.html. Can be a specific string or array of strings.redirectToSlash: Redirects requests for a directory without a trailing slash to the version with a slash.listing: Enables directory listing if no index file is found.
server.route({ method: 'GET', path: '/{param*}', handler: { directory: { path: '.', redirectToSlash: true, index: true, } } });Configure h.file(path, [options])
masterThe
h.file()method transmits a file from the file system. TheContent-Typeheader is automatically determined by the filename extension.Options:
confine(boolean): Iftrue, returns403 Forbiddenif the path resolves outside theconfinedirectory. Defaults totrue(uses route'srelativeTo).filename(string): Overrides theContent-Dispositionfilename.mode(string): ControlsContent-Disposition. Values:'false'(default),'attachment', or'inline'.lookupCompressed(boolean): Iftrue, looks for pre-compressed versions (e.g.,.gz). Defaults tofalse.lookupMap(object): Maps encoding to extensions. Default:{ gzip: '.gz' }.etagMethod(string|false):'hash'(default, SHA1),'simple'(size/date), orfalseto disable.start(number): Byte offset to start reading. Defaults to0.end(number): Byte offset to stop reading.
Use h.file() for customized file responses
masterInside a route handler, you can use
h.file(path, [options])to respond with a file. This is useful for dynamic file selection based on request logic or error handling.server.route({ method: 'GET', path: '/file', handler(request, h) { let path = 'plain.txt'; if (request.headers['x-magic'] === 'sekret') { path = 'awesome.png'; } return h.file(path).vary('x-magic'); } }); // Example: Custom 404 page server.ext('onPreResponse', (request, h) => { const response = request.response; if (response.isBoom && response.output.statusCode === 404) { return h.file('404.html').code(404); } return h.continue; });Configure the directory handler
masterThe
directoryhandler generates an endpoint for serving content from a directory. It is an object with the following options:path(required): The directory root. Can be a string, an array of strings, or a functionfunction(request).index(boolean|string|string[]): Determines if an index file is served.truelooks forindex.html. Defaults totrue.listing(boolean): Iftrue, generates a directory listing when no index is found. Defaults tofalse.showHidden(boolean): Iftrue, shows hidden files. Defaults tofalse.redirectToSlash(boolean): Redirects requests without a trailing slash. Defaults tofalse.lookupCompressed(boolean): Looks for pre-compressed versions. Defaults tofalse.lookupMap(object): Maps encoding to extensions. Default:{ gzip: '.gz' }.etagMethod(string|false):'hash'(default),'simple', orfalse.defaultExtension(string): Appended to requests if the file is not found.
Configure the Inert etagsCacheMaxSize setting
masterYou can configure the maximum size of the ETag cache via the server's plugin settings. This is done by providing an
inertobject within your server configuration. TheetagsCacheMaxSizeoption must be a non-negative integer (defaults to1000if not specified).const server = Hapi.server({ // ... other server settings plugins: { inert: { etagsCacheMaxSize: 500 } } });Use the file toolkit method
masterInert decorates the hapi
toolkit(thehobject) with afilemethod. This is useful when you want to return a file response from within a handler using the toolkit.Key options for
h.file(path, responseOptions):confine: A string defining the directory boundary. Defaults to'.'if undefined ortrue. This prevents access to files outside the specified directory.start: The byte offset to start reading from.end: The byte offset to stop reading at.
Note:
options.startmust be less than or equal tooptions.end.server.route({ method: 'GET', path: '/download', handler: (request, h) => { return h.file('/path/to/file.zip', { start: 0, end: 1024 }); } });