3h-serve v0.8.2
3h-serve
A simple but powerful server.
TOC
Introduction
3h-serve is a simple but powerful server which is mainly used for testing.
You can run npm i -g 3h-serve to install it globally and check the help information by executing 3h-serve -h.
Features
Serverless Functions
Serverless functions are supported out of the box.
For example, given a script file /api/helloWorld.js:
module.exports = (request, response) => {
response.end('Hello, world!');
};By running 3h-serve --serverless "^/api/" in the root directory and visitting localhost:8080/api/helloWorld in your browser, you should get Hello, world! as the result.
More specifically speaking, a function exported from a file which matches the serverless pattern given in options will be invoked to handle the request. The file defining the serverless function should be like this:
/**
* @param {import('http').IncomingMessage} request The native request object
* @param {import('http').ServerResponse} response The native response object
* @param {import('3h-serve').lib} lib The lib object (See `Program Usage` section)
* @param {object} options Options passed to current handler
*/
module.exports = (request, response, lib, options) => {
// Do something with the request and respond to it...
};SPA Home Page Routing
Routing single page applications is also supported. That is, with this feature, given a home page named 200.html(the name can be configured) in a directory, requests to files in the directory which are not present will be responded with that page.
Lucid Caching
3h-serve has a built-in cache control system. With cache enabled, all responses will have the following cache control directive and an ETag identifier, which tells the browsers that they can store any assets for a year but they must validate cached assets before serving them:
Cache-Control: public, max-age=31536000, no-cacheIn this way, all assets will be cached but no stale assets will be served.
Clean URLs
Clean URLs mean that you can visit /baz/index.html by requesting /baz/index or even /baz, which includes default page serving and default extension matching. (Default: index.html and .html)
Automatic Zipping
With zipping enabled, all responses will be zipped if corresponding clients claim support of it (by using request header Accept-Encoding). This includes br, gzip and deflate zipping support.
Custom Fallback Page
You can also customize the fallback page of your site by just simpling put a file named 404.html(the name can be configured) in the root directory of your site.
Debug Logging
3h-serve provides detailed debug logging so that you can see how requests are solved. To enable logging, set log level to log or debug. Setting it to log results in some brief request and response information, while setting it to debug will make routing processes logging also available.
Command Line Usage
3h-serve <root> [options]
<root> Serving root
Default: .
-a, --absolute Indicate that the root path is absolute
-p, --port <port> The port to listen on
Default: 8080
--default-page <file> The default page to serve
Default: index.html
--no-default-page Disable default page
--default-ext <ext> Default file extension
Default: .html
--no-default-ext Disable default file extension
--spa <file> SPA home page
Default: 200.html
--no-spa Disable SPA routing
--forbidden Forbidden URL pattern
--fallback-page <file> Fallback page path
Default: 404.html
--no-fallback-page Disable fallback page
-s, --serverless Serverless file pattern
--serverless-ext <ext> Default serverless file extension
Default: .js
--no-serverless-ext Disable default serverless file extension
--no-cache Disable cache
--no-zip Disable zipping
-l, --log-level Log level
Options: "info"(default), "log", "debug"
--silent Disable log
--time-format Time format
Default: [YYYY-MM-DD HH:mm:SS.sss]
-h, --help Show help informationProgram Usage
The exported APIs are listed here which can be accessed by installing 3h-serve as a dependency and importing them from 3h-serve. (Note that the lib object is also available as the third parameter of serverless functions.)
/**
* @desc The default MIME type map
*/
const DEFAULT_TYPES: Map<string, string>;
/**
* @typedef ServeOptions
* @property {string} root The root directory (Default: .)
* @property {number} port The port to use (Default: 8080)
* @property {string} timeFormat Time format passing to `3h-log` (Default: [YYYY-MM-DD HH:mm:SS.sss])
* @property {boolean} cache Whether to enable cache (Default: true)
* @property {boolean} zip Whether to enable response zipping (Default: true)
* @property {'info' | 'log' | 'debug'} logLevel Log level (Default: info)
* @property {boolean} silent Whether to suppress any log (including basic info logging)
* @property {string | null} separator The separator between logs (Default: ----------)
* @property {Map<string, string>} types The MINE type map (Default: DEFAULT_TYPES)
* @property {RegExp | null} forbiddenPattern Pattern of forbidden URLs (Default: null)
* @property {RegExp | null} serverlessPattern Pattern of serverless files (Default: null)
* @property {string | null} serverlessExtension Default extension of serverless files (Default: .js)
* @property {string | null} spaPage SPA home page (Default: 200.html)
* @property {string | null} defaultPage The default page to serve (Default: index.html)
* @property {string | null} defaultExtension The default extension to match (Default: .html)
* @property {string | null} fallbackPage Fallback page (Default: 404.html)
*/
/**
* @desc Defaults for `serve`
*/
const DEFAULT_SERVE_OPTIONS: ServeOptions;
/**
* @desc Create a server that acts according to given options
*/
function serve(options?: ServeOptions): Server;
/**
* @desc The lib object provides some useful functionalities for dealing with requests
*/
namespace lib {
/**
* @desc Merge the defaults and options
*/
function merge<T>(defaults: T, options: Partial<T>): T;
/**
* @desc Tell whether the given path is a file
*/
function isFile(path: string): boolean;
/**
* @typedef RouteOptions
* @property {string | null} spaPage SPA home page
* @property {string | null} defaultPage The default page to serve
* @property {string | null} defaultExtension The default extension to match
* @property {boolean} acceptServerless Whether serverless files are acceptable
* @property {string | null} serverlessExtension Default serverless file extension
* @property {Logger | null} logger The logger to use
*/
/**
* @typedef RoutingResult
* @property {string} path The result path
* @property {boolean} serverless Whether the target is a serverless function
*/
/**
* @desc Route the given path and returns the result
*/
function route(path: string, options: RouteOptions): RoutingResult | null;
/**
* @desc Log the status code and its corresponding status phrase
*/
function logStatus(logger: Logger, statusCode: number): void;
/**
* @desc End the response with the given code and logs it if logger is provided
*/
function endWithCode(response: ServerResponse, code: number, logger?: Logger | null): void;
/**
* @typedef EndWithFileOptions
* @property {boolean} cache
* @property {boolean} zip
* @property {Map<string, string>} types
* @property {Logger | null} logger The logger to use
*/
/**
* @desc End the response with the file indicated by `path`
*/
function endWithFile(
request: IncomingMessage,
response: ServerResponse,
path: string,
options: EndWithFileOptions
): void;
/**
* @typedef SolveOptions
* @property {string} root The root path
* @property {boolean} cache Whether to enable cache
* @property {boolean} zip Whether to enable zipping
* @property {Map<string, string>} types The MIME map to use
* @property {RegExp | null} forbiddenPattern Pattern of forbidden URLs
* @property {RegExp | null} serverlessPattern Pattern of serverless files
* @property {string | null} serverlessExtension Default extension of serverless files
* @property {string | null} spaPage SPA home page
* @property {string | null} defaultPage The default page to serve
* @property {string | null} defaultExtension The default extension to match
* @property {string | null} fallbackPage Fallback page
* @property {Logger | null} logger The logger to use
*/
/**
* @desc Solve the request according to the given path
*/
function solve(
request: IncomingMessage,
response: ServerResponse,
path: string,
options: SolveOptions
): void;
}