From a67b25f472c7ec99e63f358b3c1e8801d6261148 Mon Sep 17 00:00:00 2001 From: Rajat Kumar Date: Mon, 4 Mar 2019 10:19:37 -0800 Subject: [PATCH] feat(plugin): plugin to serve static files (#1753) * feat: another file serving plugin --- docs/_api/formatters.md | 82 ++- docs/_api/plugins.md | 556 ++++++++++++------ docs/_api/request.md | 230 +++++--- docs/_api/response.md | 192 +++--- docs/_api/server.md | 325 ++++++---- docs/config/plugins.yaml | 1 + lib/plugins/index.js | 1 + lib/plugins/staticFiles.js | 140 +++++ package.json | 1 + test/plugins/staticFiles.test.js | 412 +++++++++++++ test/plugins/testStaticFiles/docs/doc.md | 1 + test/plugins/testStaticFiles/docs/index.html | 12 + test/plugins/testStaticFiles/file1.txt | 1 + test/plugins/testStaticFiles/index.html | 12 + .../special/$_$/bad (file).txt | 1 + tools/docsBuild.js | 1 + 16 files changed, 1501 insertions(+), 467 deletions(-) create mode 100644 lib/plugins/staticFiles.js create mode 100644 test/plugins/staticFiles.test.js create mode 100644 test/plugins/testStaticFiles/docs/doc.md create mode 100644 test/plugins/testStaticFiles/docs/index.html create mode 100644 test/plugins/testStaticFiles/file1.txt create mode 100644 test/plugins/testStaticFiles/index.html create mode 100644 test/plugins/testStaticFiles/special/$_$/bad (file).txt diff --git a/docs/_api/formatters.md b/docs/_api/formatters.md index f4deac73a..ea1d1758c 100644 --- a/docs/_api/formatters.md +++ b/docs/_api/formatters.md @@ -7,14 +7,14 @@ permalink: /docs/formatters-api/ ### Table of Contents -- [Usage](#usage) -- [Types](#types) - - [formatter](#formatter) -- [Included formatters](#included-formatters) - - [formatText](#formattext) - - [formatJSON](#formatjson) - - [formatJSONP](#formatjsonp) - - [formatBinary](#formatbinary) +- [Usage][1] +- [Types][2] + - [formatter][3] +- [Included formatters][4] + - [formatText][5] + - [formatJSON][6] + - [formatJSONP][7] + - [formatBinary][8] ## Usage @@ -48,15 +48,15 @@ var server = restify.createServer({ Format a response for being sent over the wire -Type: [Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function) +Type: [Function][9] **Parameters** -- `req` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the request object (not used) -- `res` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the response object -- `body` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** response body to format +- `req` **[Object][10]** the request object (not used) +- `res` **[Object][10]** the response object +- `body` **[Object][10]** response body to format -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** formatted response data +Returns **[String][11]** formatted response data ## Included formatters @@ -71,12 +71,12 @@ exists. If it doesn't, then the response is a zero-length string. **Parameters** -- `req` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the request object (not used) -- `res` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the response object -- `body` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** response body. If it has a toString() method this +- `req` **[Object][10]** the request object (not used) +- `res` **[Object][10]** the response object +- `body` **[Object][10]** response body. If it has a toString() method this will be used to make the string representation -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** data +Returns **[String][11]** data ### formatJSON @@ -85,11 +85,11 @@ exist then a JSON.stringify will be attempted. **Parameters** -- `req` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the request object (not used) -- `res` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the response object -- `body` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** response body +- `req` **[Object][10]** the request object (not used) +- `res` **[Object][10]** the response object +- `body` **[Object][10]** response body -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** data +Returns **[String][11]** data ### formatJSONP @@ -98,11 +98,11 @@ Unicode escapes line and paragraph separators. **Parameters** -- `req` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the request object -- `res` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the response object -- `body` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** response body +- `req` **[Object][10]** the request object +- `res` **[Object][10]** the response object +- `body` **[Object][10]** response body -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** data +Returns **[String][11]** data ### formatBinary @@ -110,8 +110,32 @@ Binary formatter. **Parameters** -- `req` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the request object -- `res` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the response object -- `body` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** response body +- `req` **[Object][10]** the request object +- `res` **[Object][10]** the response object +- `body` **[Object][10]** response body -Returns **[Buffer](https://nodejs.org/api/buffer.html)** body +Returns **[Buffer][12]** body + +[1]: #usage + +[2]: #types + +[3]: #formatter + +[4]: #included-formatters + +[5]: #formattext + +[6]: #formatjson + +[7]: #formatjsonp + +[8]: #formatbinary + +[9]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function + +[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object + +[11]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String + +[12]: https://nodejs.org/api/buffer.html diff --git a/docs/_api/plugins.md b/docs/_api/plugins.md index 7777cdb03..e8c0c4e6b 100644 --- a/docs/_api/plugins.md +++ b/docs/_api/plugins.md @@ -7,39 +7,40 @@ permalink: /docs/plugins-api/ ### Table of Contents -- [Usage](#usage) -- [server.pre() plugins](#serverpre-plugins) - - [context](#context) - - [dedupeSlashes](#dedupeslashes) - - [pause](#pause) - - [sanitizePath](#sanitizepath) - - [reqIdHeaders](#reqidheaders) - - [strictQueryParams](#strictqueryparams) - - [userAgentConnection](#useragentconnection) -- [server.use() plugins](#serveruse-plugins) - - [acceptParser](#acceptparser) - - [authorizationParser](#authorizationparser) - - [dateParser](#dateparser) - - [queryParser](#queryparser) - - [jsonp](#jsonp) - - [bodyParser](#bodyparser) - - [requestLogger](#requestlogger) - - [gzipResponse](#gzipresponse) - - [serveStatic](#servestatic) - - [throttle](#throttle) - - [requestExpiry](#requestexpiry) - - [Using an external storage mechanism for key/bucket mappings.](#using-an-external-storage-mechanism-for-keybucket-mappings) - - [inflightRequestThrottle](#inflightrequestthrottle) - - [cpuUsageThrottle](#cpuusagethrottle) - - [conditionalHandler](#conditionalhandler) - - [conditionalRequest](#conditionalrequest) - - [auditLogger](#auditlogger) - - [metrics](#metrics) -- [Types](#types) - - [metrics~callback](#metricscallback) -- [req.set](#reqset) -- [req.get](#reqget) -- [req.getAll](#reqgetall) +- [Usage][1] +- [server.pre() plugins][2] + - [context][3] + - [dedupeSlashes][4] + - [pause][5] + - [sanitizePath][6] + - [reqIdHeaders][7] + - [strictQueryParams][8] + - [userAgentConnection][9] +- [server.use() plugins][10] + - [acceptParser][11] + - [authorizationParser][12] + - [dateParser][13] + - [queryParser][14] + - [jsonp][15] + - [bodyParser][16] + - [requestLogger][17] + - [gzipResponse][18] + - [serveStatic][19] + - [serveStaticFiles][20] + - [throttle][21] + - [requestExpiry][22] + - [Using an external storage mechanism for key/bucket mappings.][23] + - [inflightRequestThrottle][24] + - [cpuUsageThrottle][25] + - [conditionalHandler][26] + - [conditionalRequest][27] + - [auditLogger][28] + - [metrics][29] +- [Types][30] + - [metrics~callback][31] +- [req.set][32] +- [req.get][33] +- [req.getAll][34] ## Usage @@ -99,7 +100,7 @@ server.get('/', [ ]); ``` -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### dedupeSlashes @@ -118,24 +119,24 @@ server.get('/hello/:one', function(req, res, next) { // the server will now convert requests to /hello//jake => /hello/jake ``` -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### pause This pre handler fixes issues with node hanging when an `asyncHandler` is used prior to `bodyParser`. - - - +[https://github.com/restify/node-restify/issues/287][36] +[https://github.com/restify/node-restify/issues/409][37] +[https://github.com/restify/node-restify/wiki/1.4-to-2.0-Migration-Tips][38] -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### sanitizePath Cleans up sloppy URLs on the request object, like `/foo////bar///` to `/foo/bar`. -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### reqIdHeaders @@ -145,12 +146,12 @@ will return the header values. **Parameters** -- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** an options object - - `opts.headers` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>** array of headers from where to pull existing +- `opts` **[Object][39]** an options object + - `opts.headers` **[Array][40]<[String][41]>** array of headers from where to pull existing request id headers. Lookup precedence is left to right (lowest index first) -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### strictQueryParams @@ -168,12 +169,12 @@ RFC 2616 Fielding, et al. **Parameters** -- `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** an options object - - `options.message` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** a custom error message +- `options` **[Object][39]?** an options object + - `options.message` **[String][41]?** a custom error message default value: "Url query params does not meet strict format" -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### userAgentConnection @@ -192,11 +193,11 @@ agent regexp, however. **Parameters** -- `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** an options object - - `options.userAgentRegExp` **[RegExp](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp)** matching any +- `options` **[Object][39]?** an options object + - `options.userAgentRegExp` **[RegExp][42]** matching any user-agents applicable (optional, default `/^curl.+/`) -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ## server.use() plugins @@ -216,7 +217,7 @@ Note you can get the set of types allowed from a restify server by doing **Parameters** -- `accepts` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>** array of accept types. +- `accepts` **[Array][40]<[String][41]>** array of accept types. **Examples** @@ -226,25 +227,28 @@ server.use(restify.plugins.acceptParser(server.acceptable)); - Throws **NotAcceptableError** -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** restify handler. +Returns **[Function][35]** restify handler. ### authorizationParser Parses out the `Authorization` header as best restify can. Currently only HTTP Basic Auth and -[HTTP Signature](https://github.com/joyent/node-http-signature) +[HTTP Signature][43] schemes are supported. **Parameters** -- `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** an optional options object that is +- `options` **[Object][39]?** an optional options object that is passed to http-signature **Examples** -_Subsequent handlers will see `req.authorization`, which looks like above.`req.username` will also be set, and defaults to 'anonymous'. If the scheme +Subsequent handlers will see `req.authorization`, which looks like above. + +`req.username` will also be set, and defaults to 'anonymous'. If the scheme is unrecognized, the only thing available in `req.authorization` will be -`scheme` and `credentials` - it will be up to you to parse out the rest._ +`scheme` and `credentials` - it will be up to you to parse out the rest. + ```javascript { @@ -259,7 +263,7 @@ is unrecognized, the only thing available in `req.authorization` will be - Throws **InvalidArgumentError** -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### dateParser @@ -274,7 +278,7 @@ Kerberos!) **Parameters** -- `clockSkew` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** allowed clock skew in seconds. (optional, default `300`) +- `clockSkew` **[Number][44]** allowed clock skew in seconds. (optional, default `300`) **Examples** @@ -286,7 +290,7 @@ server.use(restify.plugins.dateParser(60)); - Throws **RequestExpiredError** - Throws **InvalidHeaderError** -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** restify handler. +Returns **[Function][35]** restify handler. ### queryParser @@ -296,32 +300,32 @@ additionally params are merged into `req.params`. You can disable by passing in `mapParams: false` in the options object. Many options correspond directly to option defined for the underlying -[`qs.parse`](https://github.com/ljharb/qs). +[`qs.parse`][45]. **Parameters** -- `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** an options object - - `options.mapParams` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** disable passing (optional, default `true`) - - `options.mapParams` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Copies parsed query parameters +- `options` **[Object][39]?** an options object + - `options.mapParams` **[Object][39]** disable passing (optional, default `true`) + - `options.mapParams` **[Boolean][46]** Copies parsed query parameters into`req.params`. (optional, default `false`) - - `options.overrideParams` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Only applies when if + - `options.overrideParams` **[Boolean][46]** Only applies when if mapParams true. When true, will stomp on req.params field when existing value is found. (optional, default `false`) - - `options.allowDots` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Transform `?foo.bar=baz` to a + - `options.allowDots` **[Boolean][46]** Transform `?foo.bar=baz` to a nested object: `{foo: {bar: 'baz'}}`. (optional, default `false`) - - `options.arrayLimit` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** Only transform `?a[$index]=b` + - `options.arrayLimit` **[Number][44]** Only transform `?a[$index]=b` to an array if `$index` is less than `arrayLimit`. (optional, default `20`) - - `options.depth` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** The depth limit for parsing + - `options.depth` **[Number][44]** The depth limit for parsing nested objects, e.g. `?a[b][c][d][e][f][g][h][i]=j`. (optional, default `5`) - - `options.parameterLimit` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** Maximum number of query + - `options.parameterLimit` **[Number][44]** Maximum number of query params parsed. Additional params are silently dropped. (optional, default `1000`) - - `options.parseArrays` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Whether to parse + - `options.parseArrays` **[Boolean][46]** Whether to parse `?a[]=b&a[1]=c` to an array, e.g. `{a: ['b', 'c']}`. (optional, default `true`) - - `options.plainObjects` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Whether `req.query` is a + - `options.plainObjects` **[Boolean][46]** Whether `req.query` is a "plain" object -- does not inherit from `Object`. This can be used to allow query params whose names collide with Object methods, e.g. `?hasOwnProperty=blah`. (optional, default `false`) - - `options.strictNullHandling` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** If true, `?a&b=` + - `options.strictNullHandling` **[Boolean][46]** If true, `?a&b=` results in `{a: null, b: ''}`. Otherwise, `{a: '', b: ''}`. (optional, default `false`) **Examples** @@ -330,7 +334,7 @@ Many options correspond directly to option defined for the underlying server.use(restify.plugins.queryParser({ mapParams: false })); ``` -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### jsonp @@ -349,7 +353,7 @@ var server = restify.createServer(); server.use(restify.plugins.jsonp()); ``` -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### bodyParser @@ -375,57 +379,57 @@ All bodyParsers support the following options: **Parameters** -- `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** an option object - - `options.maxBodySize` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** The maximum size in bytes allowed in +- `options` **[Object][39]?** an option object + - `options.maxBodySize` **[Number][44]?** The maximum size in bytes allowed in the HTTP body. Useful for limiting clients from hogging server memory. - - `options.mapParams` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** if `req.params` should be filled with + - `options.mapParams` **[Boolean][46]?** if `req.params` should be filled with parsed parameters from HTTP body. - - `options.mapFiles` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** if `req.params` should be filled with + - `options.mapFiles` **[Boolean][46]?** if `req.params` should be filled with the contents of files sent through a multipart request. - [formidable](https://github.com/felixge/node-formidable) is used internally + [formidable][47] is used internally for parsing, and a file is denoted as a multipart part with the `filename` option set in its `Content-Disposition`. This will only be performed if `mapParams` is true. - - `options.overrideParams` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** if an entry in `req.params` + - `options.overrideParams` **[Boolean][46]?** if an entry in `req.params` should be overwritten by the value in the body if the names are the same. For instance, if you have the route `/:someval`, and someone posts an `x-www-form-urlencoded` Content-Type with the body `someval=happy` to `/sad`, the value will be `happy` if `overrideParams` is `true`, `sad` otherwise. - - `options.multipartHandler` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?** a callback to handle any + - `options.multipartHandler` **[Function][35]?** a callback to handle any multipart part which is not a file. If this is omitted, the default handler is invoked which may or may not map the parts into `req.params`, depending on the `mapParams`-option. - - `options.multipartFileHandler` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?** a callback to handle any + - `options.multipartFileHandler` **[Function][35]?** a callback to handle any multipart file. It will be a file if the part has a `Content-Disposition` with the `filename` parameter set. This typically happens when a browser sends a form and there is a parameter similar to ``. If this is not provided, the default behaviour is to map the contents into `req.params`. - - `options.keepExtensions` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** if you want the uploaded + - `options.keepExtensions` **[Boolean][46]?** if you want the uploaded files to include the extensions of the original files (multipart uploads only). Does nothing if `multipartFileHandler` is defined. - - `options.uploadDir` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** Where uploaded files are + - `options.uploadDir` **[String][41]?** Where uploaded files are intermediately stored during transfer before the contents is mapped into `req.params`. Does nothing if `multipartFileHandler` is defined. - - `options.multiples` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** if you want to support html5 multiple + - `options.multiples` **[Boolean][46]?** if you want to support html5 multiple attribute in upload fields. - - `options.hash` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** If you want checksums calculated for + - `options.hash` **[String][41]?** If you want checksums calculated for incoming files, set this to either `sha1` or `md5`. - - `options.rejectUnknown` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Set to `true` if you want to end + - `options.rejectUnknown` **[Boolean][46]?** Set to `true` if you want to end the request with a `UnsupportedMediaTypeError` when none of the supported content types was given. - - `options.requestBodyOnGet` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Parse body of a GET + - `options.requestBodyOnGet` **[Boolean][46]** Parse body of a GET request. (optional, default `false`) - - `options.reviver` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?** `jsonParser` only. If a function, + - `options.reviver` **[Function][35]?** `jsonParser` only. If a function, this prescribes how the value originally produced by parsing is transformed, before being returned. For more information check out `JSON.parse(text[, reviver])`. - - `options.maxFieldsSize` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** `multipartParser` + - `options.maxFieldsSize` **[Number][44]** `multipartParser` only. Limits the amount of memory all fields together (except files) can allocate in bytes. @@ -462,25 +466,25 @@ server.use(restify.plugins.bodyParser({ - Throws **UnsupportedMediaTypeError** -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### requestLogger -Sets up a child [bunyan](https://github.com/trentm/node-bunyan) logger with +Sets up a child [bunyan][48] logger with the current request id filled in, along with any other parameters you define. You can pass in no options to this, in which case only the request id will be appended, and no serializers appended (this is also the most performant); the logger created at server creation time will be used as the parent logger. -This logger can be used normally, with [req.log](#request-api). +This logger can be used normally, with [req.log][49]. This plugin does _not_ log each individual request. Use the Audit Logging plugin or a custom middleware for that use. **Parameters** -- `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** an options object - - `options.headers` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** A list of headers to transfer from +- `options` **[Object][39]?** an options object + - `options.headers` **[Array][40]?** A list of headers to transfer from the request to top level props on the log. **Examples** @@ -494,7 +498,7 @@ server.use(restify.plugins.requestLogger({ })); ``` -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### gzipResponse @@ -510,11 +514,11 @@ that the `content-length` header cannot be known, and so This plugin has no impact if the client does not send `accept-encoding: gzip`. - +[https://github.com/restify/node-restify/issues/284][50] **Parameters** -- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** an options object, see: zlib.createGzip +- `opts` **[Object][39]?** an options object, see: zlib.createGzip **Examples** @@ -522,7 +526,7 @@ This plugin has no impact if the client does not send server.use(restify.plugins.gzipResponse()); ``` -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### serveStatic @@ -530,12 +534,13 @@ Serves static files. **Parameters** -- `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** an options object +- `options` **[Object][39]** an options object **Examples** -_The serveStatic module is different than most of the other plugins, in that -it is expected that you are going to map it to a route, as below:_ +The serveStatic module is different than most of the other plugins, in that +it is expected that you are going to map it to a route, as below: + ```javascript server.get('/docs/current/*', restify.plugins.serveStatic({ @@ -544,13 +549,15 @@ server.get('/docs/current/*', restify.plugins.serveStatic({ })); ``` -_The above `route` and `directory` combination will serve a file located in +The above `route` and `directory` combination will serve a file located in `./documentation/v1/docs/current/index.html` when you attempt to hit `http://localhost:8080/docs/current/`. If you want the serveStatic module to serve files directly from the `/documentation/v1` directory (and not append the request path `/docs/current/`), you can set the `appendRequestPath` option to `false`, and the served file -would be `./documentation/v1/index.html`, in the previous example.The plugin will enforce that all files under `directory` are served. +would be `./documentation/v1/index.html`, in the previous example. + +The plugin will enforce that all files under `directory` are served. The `directory` served is relative to the process working directory. You can also provide a `default` parameter such as index.html for any directory that lacks a direct file match. @@ -561,9 +568,12 @@ character set to the content-type detected by the plugin. For example, `charSet: 'utf-8'` will result in HTML being served with a `Content-Type` of `text/html; charset=utf-8`. Lastly, you can pass in a `maxAge` numeric, which will set the -`Cache-Control` header. Default is `3600` (1 hour).An additional option for serving a static file is to pass `file` in to the +`Cache-Control` header. Default is `3600` (1 hour). + +An additional option for serving a static file is to pass `file` in to the serveStatic method as an option. The following will serve index.html from -the documentation/v1/ directory anytime a client requests `/home/`._ +the documentation/v1/ directory anytime a client requests `/home/`. + ```javascript server.get('/home/*', restify.plugins.serveStatic({ @@ -581,7 +591,65 @@ server.get('/home/([a-z]+[.]html)', restify.plugins.serveStatic({ - Throws **NotAuthorizedError** - Throws **ResourceNotFoundError** -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler + +### serveStaticFiles + +Serves static files, with API similar to expressjs + +**Parameters** + +- `directory` **[String][41]** the directory to serve files from +- `opts` **[Object][39]** an options object, which is optional + - `opts.maxAge` **[Number][44]** specify max age in millisecs (optional, default `0`) + - `opts.etag` **[Boolean][46]** enable/disable etag, default = true (optional, default `true`) + - `opts.setHeaders` **[Function][35]?** set custom headers for the Files + (synchronously), The function is called as `fn(res, path, stat)`, + where the arguments are: + `res` the response object + `path` the file path that is being sent + `stat` the stat object of the file that is being sent + +**Examples** + +The serveStaticFiles plugin allows you to map a GET route to a +directory on the disk + + +```javascript +server.get('/public/*', // don't forget the `/*` + restify.plugins.serveStaticFiles('./documentation/v1') +); +``` + +The GET `route` and `directory` combination will serve a file +located in `./documentation/v1/index.html` when you attempt to hit +`http://localhost:8080/public/index.html` + +The plugin uses [send][51] under the hood +which is also used by `expressjs` to serve static files. Most of the options +that work with `send` will work with this plugin. + +The default file the plugin looks for is `index.html` + + +```javascript +server.get('/public/*', + restify.plugins.serveStaticFiles('./documentation/v1', { + maxAge: 3600000, // this is in millisecs + etag: false, + setHeaders: function setCustomHeaders(response, requestedPath, stat) { + response.setHeader('restify-plugin-x', 'awesome'); + } + }) +); +``` + +- Throws **MethodNotAllowedError** +- Throws **NotAuthorizedError** +- Throws **ResourceNotFoundError** + +Returns **[Function][35]** Handler ### throttle @@ -589,7 +657,7 @@ Creates an API rate limiter that can be plugged into the standard restify request handling pipeline. `restify` ships with a fairly comprehensive implementation of -[Token bucket](http://en.wikipedia.org/wiki/Token_bucket), with the ability +[Token bucket][52], with the ability to throttle on IP (or x-forwarded-for) and username (from `req.username`). You define "global" request rate and burst rate, and you can define overrides for specific keys. @@ -600,7 +668,7 @@ than `/my/fast/memcache`). If a client has consumed all of their available rate/burst, an HTTP response code of `429` -[Too Many Requests](http://tools.ietf.org/html/draft-nottingham-http-new-status-03#section-4) +[Too Many Requests][53] is returned. This throttle gives you three options on which to throttle: @@ -622,28 +690,29 @@ On the `options` object ip and username are treated as an XOR. **Parameters** -- `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** required options with: - - `options.burst` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** burst - - `options.rate` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** rate - - `options.ip` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** ip - - `options.username` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** username - - `options.xff` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** xff - - `options.setHeaders` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Set response headers for rate, +- `options` **[Object][39]** required options with: + - `options.burst` **[Number][44]** burst + - `options.rate` **[Number][44]** rate + - `options.ip` **[Boolean][46]?** ip + - `options.username` **[Boolean][46]?** username + - `options.xff` **[Boolean][46]?** xff + - `options.setHeaders` **[Boolean][46]** Set response headers for rate, limit (burst) and remaining. (optional, default `false`) - - `options.overrides` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** overrides - - `options.tokensTable` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** a storage engine this plugin will + - `options.overrides` **[Object][39]?** overrides + - `options.tokensTable` **[Object][39]** a storage engine this plugin will use to store throttling keys -> bucket mappings. If you don't specify this, the default is to use an in-memory O(1) LRU, with 10k distinct keys. Any implementation just needs to support put/get. - - `options.maxKeys` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** If using the default + - `options.maxKeys` **[Number][44]** If using the default implementation, you can specify how large you want the table to be. (optional, default `10000`) **Examples** -_An example options object with overrides:_ +An example options object with overrides: + ```javascript { @@ -660,7 +729,7 @@ _An example options object with overrides:_ - Throws **TooManyRequestsError** -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### requestExpiry @@ -700,19 +769,20 @@ and/or uniform request distribution. To enable this, you can pass in **Parameters** -- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** an options object - - `opts.absoluteHeader` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** The header key to be used for +- `opts` **[Object][39]** an options object + - `opts.absoluteHeader` **[String][41]?** The header key to be used for the expiry time of each request. - - `opts.startHeader` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The header key for the start time + - `opts.startHeader` **[String][41]** The header key for the start time of the request. - - `opts.timeoutHeader` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The header key for the time in + - `opts.timeoutHeader` **[String][41]** The header key for the time in milliseconds that should ellapse before the request is considered expired. **Examples** -_The only option provided is `header` which is the request header used -to specify the client timeout._ +The only option provided is `header` which is the request header used +to specify the client timeout. + ```javascript server.use(restify.plugins.requestExpiry({ @@ -720,7 +790,7 @@ server.use(restify.plugins.requestExpiry({ }); ``` -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### inflightRequestThrottle @@ -738,12 +808,12 @@ using `pre` to avoid performing unnecessary work. **Parameters** -- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** configure this plugin - - `opts.limit` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** maximum number of inflight requests the server +- `opts` **[Object][39]** configure this plugin + - `opts.limit` **[Number][44]** maximum number of inflight requests the server will handle before returning an error - - `opts.err` **[Error](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error)** A restify error used as a response when the + - `opts.err` **[Error][54]** A restify error used as a response when the inflight request limit is exceeded - - `opts.server` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** the instance of the restify server this + - `opts.server` **[Function][35]** the instance of the restify server this plugin will throttle. **Examples** @@ -758,7 +828,7 @@ options.res = new errors.InternalServerError(); server.pre(restify.plugins.inflightRequestThrottle(options)); ``` -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** middleware to be registered on server.pre +Returns **[Function][35]** middleware to be registered on server.pre ### cpuUsageThrottle @@ -804,18 +874,18 @@ for the ewma module. **Parameters** -- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** Configure this plugin. - - `opts.limit` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** The point at which restify will begin +- `opts` **[Object][39]** Configure this plugin. + - `opts.limit` **[Number][44]?** The point at which restify will begin rejecting a % of all requests at the front door. This value is a percentage. For example 0.8 === 80% average CPU utilization. Defaults to 0.75. - - `opts.max` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** The point at which restify will reject 100% of + - `opts.max` **[Number][44]?** The point at which restify will reject 100% of all requests at the front door. This is used in conjunction with limit to determine what % of traffic restify needs to reject when attempting to bring the average load back to the user requested values. Since Node.js is single threaded, the default for this is 1. In some rare cases, a Node.js process can exceed 100% CPU usage and you will want to update this value. - - `opts.interval` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** How frequently we calculate the average CPU + - `opts.interval` **[Number][44]?** How frequently we calculate the average CPU utilization. When we calculate an average CPU utilization, we calculate it over this interval, and this drives whether or not we should be shedding load. This can be thought of as a "resolution" where the lower this value, @@ -823,7 +893,7 @@ for the ewma module. we will recalculate the % of traffic we should be shedding. This check is rather lightweight, while the default is 250ms, you should be able to decrease this value without seeing a significant impact to performance. - - `opts.halfLife` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** When we sample the CPU usage on an + - `opts.halfLife` **[Number][44]?** When we sample the CPU usage on an interval, we create a series of data points. We take these points and calculate a moving average. The halfLife indicates how quickly a point "decays" to @@ -850,8 +920,9 @@ const options = { server.pre(restify.plugins.cpuUsageThrottle(options)); ``` -_You can also update the plugin during runtime using the `.update()` function. -This function accepts the same `opts` object as a constructor._ +You can also update the plugin during runtime using the `.update()` function. +This function accepts the same `opts` object as a constructor. + ```javascript var plugin = restify.plugins.cpuUsageThrottle(options); @@ -860,7 +931,7 @@ server.pre(plugin); plugin.update({ limit: .4, halfLife: 5000 }); ``` -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** middleware to be registered on server.pre +Returns **[Function][35]** middleware to be registered on server.pre ### conditionalHandler @@ -868,10 +939,10 @@ Runs first handler that matches to the condition **Parameters** -- `candidates` **([Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)>)** candidates - - `candidates.handler` **([Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function) \| [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)>)** handler(s) - - `candidates.version` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>)?** '1.1.0', ['1.1.0', '1.2.0'] - - `candidates.contentType` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** accepted content type, '\*\\/json' +- `candidates` **([Object][39] \| [Array][40]<[Object][39]>)** candidates + - `candidates.handler` **([Function][35] \| [Array][40]<[Function][35]>)** handler(s) + - `candidates.version` **([String][41] \| [Array][40]<[String][41]>)?** '1.1.0', ['1.1.0', '1.2.0'] + - `candidates.contentType` **[String][41]?** accepted content type, '\*\\/json' **Examples** @@ -920,7 +991,7 @@ server.get('/hello/:name', restify.plugins.conditionalHandler([ - Throws **InvalidVersionError** - Throws **UnsupportedMediaTypeError** -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### conditionalRequest @@ -967,30 +1038,33 @@ server.get('/hello/:name', function(req, res, next) { - Throws **BadRequestError** - Throws **PreconditionFailedError** -Returns **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)>** Handlers +Returns **[Array][40]<[Function][35]>** Handlers ### auditLogger **Parameters** -- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** The options object. - - `opts.log` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** The logger. - - `opts.event` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The event from the server which initiates the +- `opts` **[Object][39]** The options object. + - `opts.log` **[Object][39]** The logger. + - `opts.event` **[String][41]** The event from the server which initiates the log, one of 'pre', 'routed', or 'after' - - `opts.context` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?** The optional context function of signature + - `opts.context` **[Function][35]?** The optional context function of signature f(req, res, route, err). Invoked each time an audit log is generated. This function can return an object that customizes the format of anything off the req, res, route, and err objects. The output of this function will be available on the `context` key in the audit object. - - `opts.server` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** The restify server, used to emit + - `opts.server` **[Object][39]?** The restify server, used to emit the audit log object programmatically - - `opts.printLog` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Whether to print the log + - `opts.printLog` **[boolean][46]** Whether to print the log via the logger. (optional, default `true`) + - `opts.serializers` **[Object][39]?** Override the default logger serializers + for err, req and res **Examples** -_Audit logging is a special plugin, as you don't use it with `.use()` -but with the `after` event:_ +Audit logging is a special plugin, as you don't use it with `.use()` +but with the `after` event: + ```javascript server.on('after', restify.plugins.auditLogger({ @@ -1005,10 +1079,11 @@ server.on('after', restify.plugins.auditLogger({ })); ``` -_You pass in the auditor a bunyan logger, optionally server object, +You pass in the auditor a bunyan logger, optionally server object, Ringbuffer and a flag printLog indicate if log needs to be print out at info level or not. By default, without specify printLog flag, it will write out -record lookling like this:_ +record lookling like this: + ```javascript { @@ -1087,14 +1162,15 @@ record lookling like this:_ } ``` -_The `timers` field shows the time each handler took to run in microseconds. +The `timers` field shows the time each handler took to run in microseconds. Restify by default will record this information for every handler for each route. However, if you decide to include nested handlers, you can track the timing yourself by utilizing the Request -[startHandlerTimer](#starthandlertimerhandlername) and -[endHandlerTimer](#endhandlertimerhandlername) API. +[startHandlerTimer][55] and +[endHandlerTimer][56] API. You can also listen to auditlog event and get same above log object when -log event emits. For example_ +log event emits. For example + ```javascript SERVER.on('auditlog', function (data) { @@ -1102,7 +1178,7 @@ SERVER.on('auditlog', function (data) { }); ``` -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Handler +Returns **[Function][35]** Handler ### metrics @@ -1114,7 +1190,7 @@ about that request. **Parameters** -- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** an options obj +- `opts` **[Object][39]** an options obj - `opts.server` **Server** restify server - `callback` **createMetrics~callback** a callback fn @@ -1127,7 +1203,7 @@ server.on('after', restify.plugins.metrics({ server: server }, })); ``` -Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** returns a function suitable to be used +Returns **[Function][35]** returns a function suitable to be used with restify server's `after` event ## Types @@ -1139,33 +1215,33 @@ Returns **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference Callback used by metrics plugin -Type: [Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function) +Type: [Function][35] **Parameters** -- `err` **[Error](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error)** -- `metrics` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** metrics about the request - - `metrics.statusCode` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** status code of the response. can be +- `err` **[Error][54]** +- `metrics` **[Object][39]** metrics about the request + - `metrics.statusCode` **[Number][44]** status code of the response. can be undefined in the case of an uncaughtException - - `metrics.method` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** http request verb - - `metrics.totalLatency` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** latency includes both request is flushed + - `metrics.method` **[String][41]** http request verb + - `metrics.totalLatency` **[Number][44]** latency includes both request is flushed and all handlers finished - - `metrics.latency` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** latency when request is flushed - - `metrics.preLatency` **([Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) | null)** pre handlers latency - - `metrics.useLatency` **([Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) | null)** use handlers latency - - `metrics.routeLatency` **([Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number) | null)** route handlers latency - - `metrics.path` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** `req.path()` value - - `metrics.inflightRequests` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** Number of inflight requests pending + - `metrics.latency` **[Number][44]** latency when request is flushed + - `metrics.preLatency` **([Number][44] | null)** pre handlers latency + - `metrics.useLatency` **([Number][44] | null)** use handlers latency + - `metrics.routeLatency` **([Number][44] | null)** route handlers latency + - `metrics.path` **[String][41]** `req.path()` value + - `metrics.inflightRequests` **[Number][44]** Number of inflight requests pending in restify. - - `metrics.unifinishedRequests` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** Same as `inflightRequests` - - `metrics.connectionState` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** can be either `'close'` or + - `metrics.unifinishedRequests` **[Number][44]** Same as `inflightRequests` + - `metrics.connectionState` **[String][41]** can be either `'close'` or `undefined`. If this value is set, err will be a corresponding `RequestCloseError`. If connectionState is either `'close'`, then the `statusCode` is not applicable since the connection was severed before a response was written. -- `req` **[Request](https://developer.mozilla.org/Add-ons/SDK/High-Level_APIs/request)** the request obj -- `res` **[Response](https://developer.mozilla.org/docs/Web/Guide/HTML/HTML5)** the response obj +- `req` **[Request][57]** the request obj +- `res` **[Response][58]** the response obj - `route` **Route** the route obj that serviced the request ## req.set @@ -1175,10 +1251,10 @@ Requires the context plugin. **Parameters** -- `key` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** key +- `key` **[String][41]** key - `value` **any** value -Returns **[undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)** no return value +Returns **[undefined][59]** no return value ## req.get @@ -1187,7 +1263,7 @@ Requires the context plugin. **Parameters** -- `key` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** key +- `key` **[String][41]** key Returns **any** value stored in context @@ -1197,3 +1273,121 @@ Get all context Requires the context plugin. Returns **any** value stored in context + +[1]: #usage + +[2]: #serverpre-plugins + +[3]: #context + +[4]: #dedupeslashes + +[5]: #pause + +[6]: #sanitizepath + +[7]: #reqidheaders + +[8]: #strictqueryparams + +[9]: #useragentconnection + +[10]: #serveruse-plugins + +[11]: #acceptparser + +[12]: #authorizationparser + +[13]: #dateparser + +[14]: #queryparser + +[15]: #jsonp + +[16]: #bodyparser + +[17]: #requestlogger + +[18]: #gzipresponse + +[19]: #servestatic + +[20]: #servestaticfiles + +[21]: #throttle + +[22]: #requestexpiry + +[23]: #using-an-external-storage-mechanism-for-keybucket-mappings + +[24]: #inflightrequestthrottle + +[25]: #cpuusagethrottle + +[26]: #conditionalhandler + +[27]: #conditionalrequest + +[28]: #auditlogger + +[29]: #metrics + +[30]: #types + +[31]: #metricscallback + +[32]: #reqset + +[33]: #reqget + +[34]: #reqgetall + +[35]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function + +[36]: https://github.com/restify/node-restify/issues/287 + +[37]: https://github.com/restify/node-restify/issues/409 + +[38]: https://github.com/restify/node-restify/wiki/1.4-to-2.0-Migration-Tips + +[39]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object + +[40]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array + +[41]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String + +[42]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp + +[43]: https://github.com/joyent/node-http-signature + +[44]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number + +[45]: https://github.com/ljharb/qs + +[46]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean + +[47]: https://github.com/felixge/node-formidable + +[48]: https://github.com/trentm/node-bunyan + +[49]: #request-api + +[50]: https://github.com/restify/node-restify/issues/284 + +[51]: https://github.com/pillarjs/send + +[52]: http://en.wikipedia.org/wiki/Token_bucket + +[53]: http://tools.ietf.org/html/draft-nottingham-http-new-status-03#section-4 + +[54]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error + +[55]: #starthandlertimerhandlername + +[56]: #endhandlertimerhandlername + +[57]: https://developer.mozilla.org/Add-ons/SDK/High-Level_APIs/request + +[58]: https://developer.mozilla.org/docs/Web/Guide/HTML/HTML5 + +[59]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined diff --git a/docs/_api/request.md b/docs/_api/request.md index c3d65f5e2..b4e909031 100644 --- a/docs/_api/request.md +++ b/docs/_api/request.md @@ -7,41 +7,41 @@ permalink: /docs/request-api/ ### Table of Contents -- [Request](#request) - - [accepts](#accepts) - - [acceptsEncoding](#acceptsencoding) - - [contentLength](#contentlength) - - [getContentType](#getcontenttype) - - [date](#date) - - [href](#href) - - [id](#id) - - [getPath](#getpath) - - [getQuery](#getquery) - - [time](#time) - - [version](#version) - - [header](#header) - - [trailer](#trailer) - - [is](#is) - - [isChunked](#ischunked) - - [isKeepAlive](#iskeepalive) - - [isSecure](#issecure) - - [isUpgradeRequest](#isupgraderequest) - - [isUpload](#isupload) - - [toString](#tostring) - - [userAgent](#useragent) - - [startHandlerTimer](#starthandlertimer) - - [endHandlerTimer](#endhandlertimer) - - [connectionState](#connectionstate) - - [getRoute](#getroute) -- [Events](#events) -- [Log](#log) +- [Request][1] + - [accepts][2] + - [acceptsEncoding][3] + - [contentLength][4] + - [getContentType][5] + - [date][6] + - [href][7] + - [id][8] + - [getPath][9] + - [getQuery][10] + - [time][11] + - [version][12] + - [header][13] + - [trailer][14] + - [is][15] + - [isChunked][16] + - [isKeepAlive][17] + - [isSecure][18] + - [isUpgradeRequest][19] + - [isUpload][20] + - [toString][21] + - [userAgent][22] + - [startHandlerTimer][23] + - [endHandlerTimer][24] + - [connectionState][25] + - [getRoute][26] +- [Events][27] +- [Log][28] ## Request **Extends http.IncomingMessage** Wraps all of the node -[http.IncomingMessage](https://nodejs.org/api/http.html) +[http.IncomingMessage][29] APIs, events and properties, plus the following. ### accepts @@ -52,12 +52,13 @@ Otherwise the given type is matched by an exact match, and then subtypes. **Parameters** -- `types` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>)** an array of accept type headers +- `types` **([String][30] \| [Array][31]<[String][30]>)** an array of accept type headers **Examples** -_You may pass the subtype such as html which is then converted internally -to text/html using the mime lookup table:_ +You may pass the subtype such as html which is then converted internally +to text/html using the mime lookup table: + ```javascript // Accept: text/html @@ -76,7 +77,7 @@ req.accepts('png'); // => false ``` -Returns **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** is accepteed +Returns **[Boolean][32]** is accepteed ### acceptsEncoding @@ -84,29 +85,29 @@ Checks if the request accepts the encoding type(s) specified. **Parameters** -- `types` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>)** an array of accept type headers +- `types` **([String][30] \| [Array][31]<[String][30]>)** an array of accept type headers -Returns **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** is accepted encoding +Returns **[Boolean][32]** is accepted encoding ### contentLength Returns the value of the content-length header. -Returns **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** +Returns **[Number][33]** ### getContentType Returns the value of the content-type header. If a content-type is not set, this will return a default value of `application/octet-stream` -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** content type +Returns **[String][30]** content type ### date Returns a Date object representing when the request was setup. Like `time()`, but returns a Date object. -Returns **[Date](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date)** date when request began being processed +Returns **[Date][34]** date when request began being processed ### href @@ -122,7 +123,7 @@ server.get('/:x/bar', function(req, res, next) { }); ``` -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** +Returns **[String][30]** ### id @@ -133,9 +134,9 @@ once will cause restify to throw. **Parameters** -- `reqId` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** request id +- `reqId` **[String][30]** request id -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** id +Returns **[String][30]** id ### getPath @@ -151,7 +152,7 @@ server.get('/:x/bar', function(req, res, next) { }); ``` -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** +Returns **[String][30]** ### getQuery @@ -166,8 +167,9 @@ req.getQuery(); // => 'a=1' ``` -_If the queryParser plugin is used, the parsed query string is -available under the req.query:_ +If the queryParser plugin is used, the parsed query string is +available under the req.query: + ```javascript // incoming request is /foo?a=1 @@ -176,14 +178,14 @@ req.query; // => { a: 1 } ``` -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** query +Returns **[String][30]** query ### time The number of ms since epoch of when this request began being processed. Like date(), but returns a number. -Returns **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** time when request began being processed in epoch: +Returns **[Number][33]** time when request began being processed in epoch: ellapsed milliseconds since January 1, 1970, 00:00:00 UTC @@ -191,7 +193,7 @@ Returns **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/G Returns the accept-version header. -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** +Returns **[String][30]** ### header @@ -202,8 +204,8 @@ correctly spelled 'referrer' header to the actual spelling used. **Parameters** -- `key` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the key of the header -- `defaultValue` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** default value if header isn't +- `key` **[String][30]** the key of the header +- `defaultValue` **[String][30]?** default value if header isn't found on the req **Examples** @@ -214,7 +216,7 @@ req.header('HOST'); req.header('Accept', '*\/*'); ``` -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** header value +Returns **[String][30]** header value ### trailer @@ -223,10 +225,10 @@ correctly spelled 'referrer' header to the actual spelling used. **Parameters** -- `name` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the name of the header -- `value` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** default value if header isn't found on the req +- `name` **[String][30]** the name of the header +- `value` **[String][30]** default value if header isn't found on the req -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** trailer value +Returns **[String][30]** trailer value ### is @@ -235,7 +237,7 @@ and if it contains the given mime type. **Parameters** -- `type` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** a content-type header value +- `type` **[String][30]** a content-type header value **Examples** @@ -254,49 +256,49 @@ req.is('html'); // => false ``` -Returns **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** is content-type header +Returns **[Boolean][32]** is content-type header ### isChunked Check if the incoming request is chunked. -Returns **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** is chunked +Returns **[Boolean][32]** is chunked ### isKeepAlive Check if the incoming request is kept alive. -Returns **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** is keep alive +Returns **[Boolean][32]** is keep alive ### isSecure Check if the incoming request is encrypted. -Returns **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** is secure +Returns **[Boolean][32]** is secure ### isUpgradeRequest Check if the incoming request has been upgraded. -Returns **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** is upgraded +Returns **[Boolean][32]** is upgraded ### isUpload Check if the incoming request is an upload verb. -Returns **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** is upload +Returns **[Boolean][32]** is upload ### toString toString serialization -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** serialized request +Returns **[String][30]** serialized request ### userAgent Returns the user-agent header. -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** user agent +Returns **[String][30]** user agent ### startHandlerTimer @@ -308,13 +310,14 @@ handler chain to record timing information. **Parameters** -- `handlerName` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The name of the handler. +- `handlerName` **[String][30]** The name of the handler. **Examples** -_You must explicitly invoke +You must explicitly invoke endHandlerTimer() after invoking this function. Otherwise timing -information will be inaccurate._ +information will be inaccurate. + ```javascript server.get('/', function fooHandler(req, res, next) { @@ -338,7 +341,7 @@ server.get('/', function fooHandler(req, res, next) { }); ``` -Returns **[undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)** no return value +Returns **[undefined][35]** no return value ### endHandlerTimer @@ -348,9 +351,9 @@ handler. Otherwise the time recorded will be incorrect. **Parameters** -- `handlerName` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The name of the handler. +- `handlerName` **[String][30]** The name of the handler. -Returns **[undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)** no return value +Returns **[undefined][35]** no return value ### connectionState @@ -358,7 +361,7 @@ Returns the connection state of the request. Current possible values are: - `close` - when the request has been closed by the clien -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** connection state (`"close"`) +Returns **[String][30]** connection state (`"close"`) ### getRoute @@ -366,7 +369,8 @@ Returns the route object to which the current request was matched to. **Examples** -_Route info object structure:_ +Route info object structure: + ```javascript { @@ -377,12 +381,12 @@ _Route info object structure:_ } ``` -Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** route +Returns **[Object][36]** route ## Events In additional to emitting all the events from node's -[http.Server](http://nodejs.org/docs/latest/api/http.html#http_class_http_server), +[http.Server][37], restify servers also emit a number of additional events that make building REST and web applications much easier. @@ -475,7 +479,7 @@ routable, i.e. one that would result in a `404`. ### uncaughtException If the restify server was created with `handleUncaughtExceptions: true`, -restify will leverage [domains](https://nodejs.org/api/domain.html) to handle +restify will leverage [domains][38] to handle thrown errors in the handler chain. Thrown errors are a result of an explicit `throw` statement, or as a result of programmer errors like a typo or a null ref. These thrown errors are caught by the domain, and will be emitted via this @@ -516,7 +520,7 @@ Emitted when the server closes. ## Log -If you are using the [RequestLogger](#bundled-plugins) plugin, the child logger +If you are using the [RequestLogger][39] plugin, the child logger will be available on `req.log`: ```js @@ -532,3 +536,81 @@ each log statement. Since the logger lasts for the life of the request, you can use this to correlate statements for an individual request across any number of separate handlers. + +[1]: #request + +[2]: #accepts + +[3]: #acceptsencoding + +[4]: #contentlength + +[5]: #getcontenttype + +[6]: #date + +[7]: #href + +[8]: #id + +[9]: #getpath + +[10]: #getquery + +[11]: #time + +[12]: #version + +[13]: #header + +[14]: #trailer + +[15]: #is + +[16]: #ischunked + +[17]: #iskeepalive + +[18]: #issecure + +[19]: #isupgraderequest + +[20]: #isupload + +[21]: #tostring + +[22]: #useragent + +[23]: #starthandlertimer + +[24]: #endhandlertimer + +[25]: #connectionstate + +[26]: #getroute + +[27]: #events + +[28]: #log + +[29]: https://nodejs.org/api/http.html + +[30]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String + +[31]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array + +[32]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean + +[33]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number + +[34]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date + +[35]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined + +[36]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object + +[37]: http://nodejs.org/docs/latest/api/http.html#http_class_http_server + +[38]: https://nodejs.org/api/domain.html + +[39]: #bundled-plugins diff --git a/docs/_api/response.md b/docs/_api/response.md index 930434807..e47388d16 100644 --- a/docs/_api/response.md +++ b/docs/_api/response.md @@ -7,27 +7,27 @@ permalink: /docs/response-api/ ### Table of Contents -- [Response](#response) - - [cache](#cache) - - [noCache](#nocache) - - [charSet](#charset) - - [header](#header) - - [json](#json) - - [link](#link) - - [send](#send) - - [sendRaw](#sendraw) - - [set](#set) - - [status](#status) - - [redirect](#redirect) - - [redirect](#redirect-1) - - [redirect](#redirect-2) +- [Response][1] + - [cache][2] + - [noCache][3] + - [charSet][4] + - [header][5] + - [json][6] + - [link][7] + - [send][8] + - [sendRaw][9] + - [set][10] + - [status][11] + - [redirect][12] + - [redirect][13] + - [redirect][14] ## Response **Extends http.ServerResponse** Wraps all of the node -[http.ServerResponse](https://nodejs.org/docs/latest/api/http.html) +[http.ServerResponse][15] APIs, events and properties, plus the following. ### cache @@ -36,18 +36,18 @@ Sets the `cache-control` header. **Parameters** -- `type` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** value of the header +- `type` **[String][16]** value of the header (`"public"` or `"private"`) (optional, default `"public"`) -- `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** an options object - - `options.maxAge` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** max-age in seconds +- `options` **[Object][17]?** an options object + - `options.maxAge` **[Number][18]** max-age in seconds -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the value set to the header +Returns **[String][16]** the value set to the header ### noCache Turns off all cache related headers. -Returns **[Response](#response)** self, the response object +Returns **[Response][19]** self, the response object ### charSet @@ -55,7 +55,7 @@ Appends the provided character set to the response's `Content-Type`. **Parameters** -- `type` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** char-set value +- `type` **[String][16]** char-set value **Examples** @@ -63,7 +63,7 @@ Appends the provided character set to the response's `Content-Type`. res.charSet('utf-8'); ``` -Returns **[Response](#response)** self, the response object +Returns **[Response][19]** self, the response object ### header @@ -71,13 +71,14 @@ Sets headers on the response. **Parameters** -- `key` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the name of the header -- `value` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the value of the header +- `key` **[String][16]** the name of the header +- `value` **[String][16]** the value of the header **Examples** -_If only key is specified, return the value of the header. -If both key and value are specified, set the response header._ +If only key is specified, return the value of the header. +If both key and value are specified, set the response header. + ```javascript res.header('Content-Length'); @@ -93,8 +94,9 @@ res.header('foo', new Date()); // => Fri, 03 Feb 2012 20:09:58 GMT ``` -_`header()` can also be used to automatically chain header values -when applicable:_ +`header()` can also be used to automatically chain header values +when applicable: + ```javascript res.header('x-foo', 'a'); @@ -102,7 +104,7 @@ res.header('x-foo', 'b'); // => { 'x-foo': ['a', 'b'] } ``` -Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the retrieved value or the value that was set +Returns **[Object][17]** the retrieved value or the value that was set ### json @@ -115,9 +117,9 @@ res.send({hello: 'world'}); **Parameters** -- `code` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** http status code -- `body` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** value to json.stringify -- `headers` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** headers to set on the response +- `code` **[Number][18]?** http status code +- `body` **[Object][17]?** value to json.stringify +- `headers` **[Object][17]?** headers to set on the response **Examples** @@ -126,7 +128,7 @@ res.header('content-type', 'json'); res.send({hello: 'world'}); ``` -Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the response object +Returns **[Object][17]** the response object ### link @@ -134,10 +136,10 @@ Sets the link header. **Parameters** -- `key` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the link key -- `value` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the link value +- `key` **[String][16]** the link key +- `value` **[String][16]** the link value -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the header value set to res +Returns **[String][16]** the header value set to res ### send @@ -146,18 +148,19 @@ formatter based on the `content-type` header. **Parameters** -- `code` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** http status code -- `body` **([Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [Buffer](https://nodejs.org/api/buffer.html) \| [Error](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error))?** the content to send -- `headers` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** any add'l headers to set +- `code` **[Number][18]?** http status code +- `body` **([Object][17] \| [Buffer][20] \| [Error][21])?** the content to send +- `headers` **[Object][17]?** any add'l headers to set **Examples** -_You can use send() to wrap up all the usual writeHead(), write(), end() +You can use send() to wrap up all the usual writeHead(), write(), end() calls on the HTTP API of node. You can pass send either a `code` and `body`, or just a body. body can be an `Object`, a `Buffer`, or an `Error`. When you call `send()`, restify figures out how to format the response -based on the `content-type`._ +based on the `content-type`. + ```javascript res.send({hello: 'world'}); @@ -165,7 +168,7 @@ res.send(201, {hello: 'world'}); res.send(new BadRequestError('meh')); ``` -Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the response object +Returns **[Object][17]** the response object ### sendRaw @@ -176,11 +179,11 @@ formatters entirely and sends the content as is. **Parameters** -- `code` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** http status code -- `body` **([Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [Buffer](https://nodejs.org/api/buffer.html) \| [Error](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error))?** the content to send -- `headers` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** any add'l headers to set +- `code` **[Number][18]?** http status code +- `body` **([Object][17] \| [Buffer][20] \| [Error][21])?** the content to send +- `headers` **[Object][17]?** any add'l headers to set -Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** the response object +Returns **[Object][17]** the response object ### set @@ -189,9 +192,9 @@ Uses `header()` underneath the hood, enabling multi-value headers. **Parameters** -- `name` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object))** name of the header or +- `name` **([String][16] \| [Object][17])** name of the header or `Object` of headers -- `val` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** value of the header +- `val` **[String][16]** value of the header **Examples** @@ -208,7 +211,7 @@ res.set({ // } ``` -Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** self, the response object +Returns **[Object][17]** self, the response object ### status @@ -216,7 +219,7 @@ Sets the http status code on the response. **Parameters** -- `code` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** http status code +- `code` **[Number][18]** http status code **Examples** @@ -224,7 +227,7 @@ Sets the http status code on the response. res.status(201); ``` -Returns **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** the status code passed in +Returns **[Number][18]** the status code passed in ### redirect @@ -232,19 +235,19 @@ Redirect is sugar method for redirecting. **Parameters** -- `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** url or an options object to configure a redirect - - `options.secure` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** whether to redirect to http or https - - `options.hostname` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** redirect location's hostname - - `options.pathname` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** redirect location's pathname - - `options.port` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** redirect location's port number - - `options.query` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** redirect location's query string +- `options` **[Object][17]** url or an options object to configure a redirect + - `options.secure` **[Boolean][22]?** whether to redirect to http or https + - `options.hostname` **[String][16]?** redirect location's hostname + - `options.pathname` **[String][16]?** redirect location's pathname + - `options.port` **[String][16]?** redirect location's port number + - `options.query` **[String][16]?** redirect location's query string parameters - - `options.overrideQuery` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** if true, `options.query` + - `options.overrideQuery` **[Boolean][22]?** if true, `options.query` stomps over any existing query parameters on current URL. by default, will merge the two. - - `options.permanent` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** if true, sets 301. defaults to 302. -- `next` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** mandatory, to complete the response and trigger + - `options.permanent` **[Boolean][22]?** if true, sets 301. defaults to 302. +- `next` **[Function][23]** mandatory, to complete the response and trigger audit logger. **Examples** @@ -253,9 +256,10 @@ Redirect is sugar method for redirecting. res.redirect({...}, next); ``` -_A convenience method for 301/302 redirects. Using this method will tell +A convenience method for 301/302 redirects. Using this method will tell restify to stop execution of your handler chain. -You can also use an options object. `next` is required._ +You can also use an options object. `next` is required. + ```javascript res.redirect({ @@ -270,7 +274,7 @@ res.redirect({ }, next); // => redirects to 301 https://www.foo.com/bar?a=1 ``` -Returns **[undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)** +Returns **[undefined][24]** ### redirect @@ -278,9 +282,9 @@ Redirect with code and url. **Parameters** -- `code` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** http redirect status code -- `url` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** redirect url -- `next` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** mandatory, to complete the response and trigger +- `code` **[Number][18]** http redirect status code +- `url` **[String][16]** redirect url +- `next` **[Function][23]** mandatory, to complete the response and trigger audit logger. **Examples** @@ -289,7 +293,7 @@ Redirect with code and url. res.redirect(301, 'www.foo.com', next); ``` -Returns **[undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)** +Returns **[undefined][24]** ### redirect @@ -297,8 +301,8 @@ Redirect with url. **Parameters** -- `url` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** redirect url -- `next` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** mandatory, to complete the response and trigger +- `url` **[String][16]** redirect url +- `next` **[Function][23]** mandatory, to complete the response and trigger audit logger. **Examples** @@ -308,4 +312,52 @@ res.redirect('www.foo.com', next); res.redirect('/foo', next); ``` -Returns **[undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)** +Returns **[undefined][24]** + +[1]: #response + +[2]: #cache + +[3]: #nocache + +[4]: #charset + +[5]: #header + +[6]: #json + +[7]: #link + +[8]: #send + +[9]: #sendraw + +[10]: #set + +[11]: #status + +[12]: #redirect + +[13]: #redirect-1 + +[14]: #redirect-2 + +[15]: https://nodejs.org/docs/latest/api/http.html + +[16]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String + +[17]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object + +[18]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number + +[19]: #response + +[20]: https://nodejs.org/api/buffer.html + +[21]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error + +[22]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean + +[23]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function + +[24]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined diff --git a/docs/_api/server.md b/docs/_api/server.md index 135cb38d6..277d5a1b2 100644 --- a/docs/_api/server.md +++ b/docs/_api/server.md @@ -7,29 +7,29 @@ permalink: /docs/server-api/ ### Table of Contents -- [createServer](#createserver) -- [Server](#server) - - [listen](#listen) - - [close](#close) - - [get](#get) - - [head](#head) - - [post](#post) - - [put](#put) - - [patch](#patch) - - [del](#del) - - [opts](#opts) - - [pre](#pre) - - [use](#use) - - [param](#param) - - [rm](#rm) - - [address](#address) - - [inflightRequests](#inflightrequests) - - [debugInfo](#debuginfo) - - [toString](#tostring) -- [Events](#events) -- [Errors](#errors) -- [Types](#types) - - [Server~methodOpts](#servermethodopts) +- [createServer][1] +- [Server][2] + - [listen][3] + - [close][4] + - [get][5] + - [head][6] + - [post][7] + - [put][8] + - [patch][9] + - [del][10] + - [opts][11] + - [pre][12] + - [use][13] + - [param][14] + - [rm][15] + - [address][16] + - [inflightRequests][17] + - [debugInfo][18] + - [toString][19] +- [Events][20] +- [Errors][21] +- [Types][22] + - [Server~methodOpts][23] ## createServer @@ -38,46 +38,46 @@ routes and handlers for incoming requests. **Parameters** -- `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** an options object - - `options.name` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** Name of the server. (optional, default `"restify"`) - - `options.dtrace` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** enable DTrace support (optional, default `false`) +- `options` **[Object][24]?** an options object + - `options.name` **[String][25]** Name of the server. (optional, default `"restify"`) + - `options.dtrace` **[Boolean][26]** enable DTrace support (optional, default `false`) - `options.router` **Router** Router (optional, default `newRouter(opts)`) - - `options.log` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** [bunyan](https://github.com/trentm/node-bunyan) instance. (optional, default `bunyan.createLogger(options.name||"restify")`) - - `options.url` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** Once listen() is called, this will be filled + - `options.log` **[Object][24]** [bunyan][27] instance. (optional, default `bunyan.createLogger(options.name||"restify")`) + - `options.url` **[String][25]?** Once listen() is called, this will be filled in with where the server is running. - - `options.certificate` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Buffer](https://nodejs.org/api/buffer.html))?** If you want to create an HTTPS + - `options.certificate` **([String][25] \| [Buffer][28])?** If you want to create an HTTPS server, pass in a PEM-encoded certificate and key. - - `options.key` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Buffer](https://nodejs.org/api/buffer.html))?** If you want to create an HTTPS server, + - `options.key` **([String][25] \| [Buffer][28])?** If you want to create an HTTPS server, pass in a PEM-encoded certificate and key. - - `options.formatters` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Custom response formatters for + - `options.formatters` **[Object][24]?** Custom response formatters for `res.send()`. - - `options.handleUncaughtExceptions` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** When true restify + - `options.handleUncaughtExceptions` **[Boolean][26]** When true restify will use a domain to catch and respond to any uncaught exceptions that occur in it's handler stack. - [bunyan](https://github.com/trentm/node-bunyan) instance. + [bunyan][27] instance. response header, default is `restify`. Pass empty string to unset the header. Comes with significant negative performance impact. (optional, default `false`) - - `options.spdy` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Any options accepted by - [node-spdy](https://github.com/indutny/node-spdy). - - `options.http2` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Any options accepted by - [http2.createSecureServer](https://nodejs.org/api/http2.html). - - `options.handleUpgrades` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Hook the `upgrade` event + - `options.spdy` **[Object][24]?** Any options accepted by + [node-spdy][29]. + - `options.http2` **[Object][24]?** Any options accepted by + [http2.createSecureServer][30]. + - `options.handleUpgrades` **[Boolean][26]** Hook the `upgrade` event from the node HTTP server, pushing `Connection: Upgrade` requests through the regular request handling chain. (optional, default `false`) - - `options.onceNext` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Prevents calling next multiple + - `options.onceNext` **[Boolean][26]** Prevents calling next multiple times (optional, default `false`) - - `options.strictNext` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Throws error when next() is + - `options.strictNext` **[Boolean][26]** Throws error when next() is called more than once, enabled onceNext option (optional, default `false`) - - `options.httpsServerOptions` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Any options accepted by - [node-https Server](http://nodejs.org/api/https.html#https_https). + - `options.httpsServerOptions` **[Object][24]?** Any options accepted by + [node-https Server][31]. If provided the following restify server options will be ignored: spdy, ca, certificate, key, passphrase, rejectUnauthorized, requestCert and ciphers; however these can all be specified on httpsServerOptions. - - `options.noWriteContinue` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** prevents + - `options.noWriteContinue` **[Boolean][26]** prevents `res.writeContinue()` in `server.on('checkContinue')` when proxing (optional, default `false`) - - `options.ignoreTrailingSlash` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** ignore trailing slash + - `options.ignoreTrailingSlash` **[Boolean][26]** ignore trailing slash on paths (optional, default `false`) - - `options.strictFormatters` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** enables strict formatters + - `options.strictFormatters` **[Boolean][26]** enables strict formatters behavior: a formatter matching the response's content-type is required. If not found, the response's content-type is automatically set to 'application/octet-stream'. If a formatter for that content-type is not @@ -94,7 +94,7 @@ server.listen(8080, function () { }); ``` -Returns **[Server](#server)** server +Returns **[Server][32]** server ## Server @@ -102,47 +102,47 @@ Creates a new Server. **Parameters** -- `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** an options object - - `options.name` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** Name of the server. - - `options.dtrace` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** enable DTrace support (optional, default `false`) +- `options` **[Object][24]** an options object + - `options.name` **[String][25]** Name of the server. + - `options.dtrace` **[Boolean][26]** enable DTrace support (optional, default `false`) - `options.router` **Router** Router - - `options.log` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** [bunyan](https://github.com/trentm/node-bunyan) + - `options.log` **[Object][24]** [bunyan][27] instance. - - `options.url` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** Once listen() is called, this will be filled + - `options.url` **[String][25]?** Once listen() is called, this will be filled in with where the server is running. - - `options.certificate` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Buffer](https://nodejs.org/api/buffer.html))?** If you want to create an HTTPS + - `options.certificate` **([String][25] \| [Buffer][28])?** If you want to create an HTTPS server, pass in a PEM-encoded certificate and key. - - `options.key` **([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Buffer](https://nodejs.org/api/buffer.html))?** If you want to create an HTTPS server, + - `options.key` **([String][25] \| [Buffer][28])?** If you want to create an HTTPS server, pass in a PEM-encoded certificate and key. - - `options.formatters` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Custom response formatters for + - `options.formatters` **[Object][24]?** Custom response formatters for `res.send()`. - - `options.handleUncaughtExceptions` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** When true restify + - `options.handleUncaughtExceptions` **[Boolean][26]** When true restify will use a domain to catch and respond to any uncaught exceptions that occur in it's handler stack. Comes with significant negative performance impact. - [bunyan](https://github.com/trentm/node-bunyan) instance. + [bunyan][27] instance. response header, default is `restify`. Pass empty string to unset the header. (optional, default `false`) - - `options.spdy` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Any options accepted by - [node-spdy](https://github.com/indutny/node-spdy). - - `options.http2` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Any options accepted by - [http2.createSecureServer](https://nodejs.org/api/http2.html). - - `options.handleUpgrades` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Hook the `upgrade` event + - `options.spdy` **[Object][24]?** Any options accepted by + [node-spdy][29]. + - `options.http2` **[Object][24]?** Any options accepted by + [http2.createSecureServer][30]. + - `options.handleUpgrades` **[Boolean][26]** Hook the `upgrade` event from the node HTTP server, pushing `Connection: Upgrade` requests through the regular request handling chain. (optional, default `false`) - - `options.onceNext` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Prevents calling next multiple + - `options.onceNext` **[Boolean][26]** Prevents calling next multiple times (optional, default `false`) - - `options.strictNext` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Throws error when next() is + - `options.strictNext` **[Boolean][26]** Throws error when next() is called more than once, enabled onceNext option (optional, default `false`) - - `options.httpsServerOptions` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Any options accepted by - [node-https Server](http://nodejs.org/api/https.html#https_https). + - `options.httpsServerOptions` **[Object][24]?** Any options accepted by + [node-https Server][31]. If provided the following restify server options will be ignored: spdy, ca, certificate, key, passphrase, rejectUnauthorized, requestCert and ciphers; however these can all be specified on httpsServerOptions. - - `options.noWriteContinue` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** prevents + - `options.noWriteContinue` **[Boolean][26]** prevents `res.writeContinue()` in `server.on('checkContinue')` when proxing (optional, default `false`) - - `options.ignoreTrailingSlash` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** ignore trailing slash + - `options.ignoreTrailingSlash` **[Boolean][26]** ignore trailing slash on paths (optional, default `false`) - - `options.strictFormatters` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** enables strict formatters + - `options.strictFormatters` **[Boolean][26]** enables strict formatters behavior: a formatter matching the response's content-type is required. If not found, the response's content-type is automatically set to 'application/octet-stream'. If a formatter for that content-type is not @@ -163,17 +163,18 @@ server.listen(8080, function () { Gets the server up and listening. Wraps node's -[listen()](http://nodejs.org/docs/latest/api/net.html#net_server_listen_path_callback). +[listen()][33]. **Parameters** -- `port` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** Port -- `host` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Host -- `callback` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?** optionally get notified when listening. +- `port` **[Number][34]** Port +- `host` **[Number][34]?** Host +- `callback` **[Function][35]?** optionally get notified when listening. **Examples** -_You can call like:_ +You can call like: + ```javascript server.listen(80) @@ -181,21 +182,21 @@ server.listen(80, '127.0.0.1') server.listen('/tmp/server.sock') ``` -- Throws **[TypeError](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError)** +- Throws **[TypeError][36]** -Returns **[undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)** no return value +Returns **[undefined][37]** no return value ### close Shuts down this server, and invokes callback (optionally) when done. Wraps node's -[close()](http://nodejs.org/docs/latest/api/net.html#net_event_close). +[close()][38]. **Parameters** -- `callback` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?** callback to invoke when done +- `callback` **[Function][35]?** callback to invoke when done -Returns **[undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined)** no return value +Returns **[undefined][37]** no return value ### get @@ -203,7 +204,7 @@ Mounts a chain on the given path against this HTTP verb **Parameters** -- `opts` **[Server~methodOpts](#servermethodopts)** if string, the URL to handle. +- `opts` **[Server~methodOpts][39]** if string, the URL to handle. if options, the URL to handle, at minimum. **Examples** @@ -223,7 +224,7 @@ Mounts a chain on the given path against this HTTP verb **Parameters** -- `opts` **[Server~methodOpts](#servermethodopts)** if string, the URL to handle. +- `opts` **[Server~methodOpts][39]** if string, the URL to handle. if options, the URL to handle, at minimum. Returns **Route** the newly created route. @@ -234,7 +235,7 @@ Mounts a chain on the given path against this HTTP verb **Parameters** -- `post` **[Server~methodOpts](#servermethodopts)** if string, the URL to handle. +- `post` **[Server~methodOpts][39]** if string, the URL to handle. if options, the URL to handle, at minimum. Returns **Route** the newly created route. @@ -245,7 +246,7 @@ Mounts a chain on the given path against this HTTP verb **Parameters** -- `put` **[Server~methodOpts](#servermethodopts)** if string, the URL to handle. +- `put` **[Server~methodOpts][39]** if string, the URL to handle. if options, the URL to handle, at minimum. Returns **Route** the newly created route. @@ -256,7 +257,7 @@ Mounts a chain on the given path against this HTTP verb **Parameters** -- `patch` **[Server~methodOpts](#servermethodopts)** if string, the URL to handle. +- `patch` **[Server~methodOpts][39]** if string, the URL to handle. if options, the URL to handle, at minimum. Returns **Route** the newly created route. @@ -267,7 +268,7 @@ Mounts a chain on the given path against this HTTP verb **Parameters** -- `opts` **[Server~methodOpts](#servermethodopts)** if string, the URL to handle. +- `opts` **[Server~methodOpts][39]** if string, the URL to handle. if options, the URL to handle, at minimum. Returns **Route** the newly created route. @@ -278,7 +279,7 @@ Mounts a chain on the given path against this HTTP verb **Parameters** -- `opts` **[Server~methodOpts](#servermethodopts)** if string, the URL to handle. +- `opts` **[Server~methodOpts][39]** if string, the URL to handle. if options, the URL to handle, at minimum. Returns **Route** the newly created route. @@ -291,7 +292,7 @@ depends on. Note that req.params will _not_ be set yet. **Parameters** -- `handler` **...([Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function) \| [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array))** Allows you to add handlers that +- `handler` **...([Function][35] \| [Array][40])** Allows you to add handlers that run for all routes. _before_ routing occurs. This gives you a hook to change request headers and the like if you need to. Note that `req.params` will be undefined, as that's filled in _after_ @@ -308,14 +309,15 @@ server.pre(function(req, res, next) { }); ``` -_For example, `pre()` can be used to deduplicate slashes in -URLs_ +For example, `pre()` can be used to deduplicate slashes in +URLs + ```javascript server.pre(restify.pre.dedupeSlashes()); ``` -Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** returns self +Returns **[Object][24]** returns self ### use @@ -329,14 +331,14 @@ You can pass in any combination of functions or array of functions. **Parameters** -- `handler` **...([Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function) \| [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array))** A variable number of handler functions- and/or a +- `handler` **...([Function][35] \| [Array][40])** A variable number of handler functions- and/or a variable number of nested arrays of handler functions -Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** returns self +Returns **[Object][24]** returns self ### param -- **See: ** +- **See: [http://expressjs.com/guide.html#route-param%20pre-conditions][41]** Minimal port of the functionality offered by Express.js Route Param Pre-conditions @@ -352,10 +354,10 @@ Exposes an API: **Parameters** -- `name` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The name of the URL param to respond to -- `fn` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** The middleware function to execute +- `name` **[String][25]** The name of the URL param to respond to +- `fn` **[Function][35]** The middleware function to execute -Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** returns self +Returns **[Object][24]** returns self ### rm @@ -364,18 +366,18 @@ You pass in the route 'blob' you got from a mount call. **Parameters** -- `routeName` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the route name. +- `routeName` **[String][25]** the route name. -- Throws **[TypeError](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError)** on bad input. +- Throws **[TypeError][36]** on bad input. -Returns **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** true if route was removed, false if not. +Returns **[Boolean][26]** true if route was removed, false if not. ### address Returns the server address. Wraps node's -[address()](http://nodejs.org/docs/latest/api/net.html#net_server_address). +[address()][42]. **Examples** @@ -383,19 +385,20 @@ Wraps node's server.address() ``` -_Output:_ +Output: + ```javascript { address: '::', family: 'IPv6', port: 8080 } ``` -Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** Address of server +Returns **[Object][24]** Address of server ### inflightRequests Returns the number of inflight requests currently being handled by the server -Returns **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** number of inflight requests +Returns **[number][34]** number of inflight requests ### debugInfo @@ -407,7 +410,8 @@ Return debug information about the server. server.getDebugInfo() ``` -_Output:_ +Output: + ```javascript { @@ -438,7 +442,7 @@ _Output:_ } ``` -Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** debug info +Returns **[Object][24]** debug info ### toString @@ -450,7 +454,8 @@ toString() the server for easy reading/output. server.toString() ``` -_Output:_ +Output: + ```javascript Accepts: application/json, text/plain, application/octet-stream, @@ -473,12 +478,12 @@ Url: http://[::]:8080 Version: ``` -Returns **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** stringified server +Returns **[String][25]** stringified server ## Events In additional to emitting all the events from node's -[http.Server](http://nodejs.org/docs/latest/api/http.html#http_class_http_server), +[http.Server][43], restify servers also emit a number of additional events that make building REST and web applications much easier. @@ -571,7 +576,7 @@ routable, i.e. one that would result in a `404`. ### uncaughtException If the restify server was created with `handleUncaughtExceptions: true`, -restify will leverage [domains](https://nodejs.org/api/domain.html) to handle +restify will leverage [domains][44] to handle thrown errors in the handler chain. Thrown errors are a result of an explicit `throw` statement, or as a result of programmer errors like a typo or a null ref. These thrown errors are caught by the domain, and will be emitted via this @@ -678,7 +683,7 @@ function(req, res, err, callback) { } - `callback` - a callback function to invoke When using this feature in conjunction with -[restify-errors](https://github.com/restify/errors), restify will emit events +[restify-errors][45], restify will emit events for all of the basic http errors: - `400` - `BadRequestError` @@ -758,13 +763,13 @@ on this event, and if there are none, responds with a default 415 handler. Server method opts -Type: ([String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Regexp](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp) \| [Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)) +Type: ([String][25] \| [Regexp][46] \| [Object][24]) **Properties** -- `name` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** a name for the route -- `path` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** can be any String accepted by - [find-my-way](https://github.com/delvedor/find-my-way) +- `name` **[String][25]** a name for the route +- `path` **[String][25]** can be any String accepted by + [find-my-way][47] **Examples** @@ -780,3 +785,97 @@ server.get({ path: '/foo', }, function(req, res, next) {}); ``` + +[1]: #createserver + +[2]: #server + +[3]: #listen + +[4]: #close + +[5]: #get + +[6]: #head + +[7]: #post + +[8]: #put + +[9]: #patch + +[10]: #del + +[11]: #opts + +[12]: #pre + +[13]: #use + +[14]: #param + +[15]: #rm + +[16]: #address + +[17]: #inflightrequests + +[18]: #debuginfo + +[19]: #tostring + +[20]: #events + +[21]: #errors + +[22]: #types + +[23]: #servermethodopts + +[24]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object + +[25]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String + +[26]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean + +[27]: https://github.com/trentm/node-bunyan + +[28]: https://nodejs.org/api/buffer.html + +[29]: https://github.com/indutny/node-spdy + +[30]: https://nodejs.org/api/http2.html + +[31]: http://nodejs.org/api/https.html#https_https + +[32]: #server + +[33]: http://nodejs.org/docs/latest/api/net.html#net_server_listen_path_callback + +[34]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number + +[35]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function + +[36]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError + +[37]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined + +[38]: http://nodejs.org/docs/latest/api/net.html#net_event_close + +[39]: #servermethodopts + +[40]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array + +[41]: http://expressjs.com/guide.html#route-param%20pre-conditions + +[42]: http://nodejs.org/docs/latest/api/net.html#net_server_address + +[43]: http://nodejs.org/docs/latest/api/http.html#http_class_http_server + +[44]: https://nodejs.org/api/domain.html + +[45]: https://github.com/restify/errors + +[46]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp + +[47]: https://github.com/delvedor/find-my-way diff --git a/docs/config/plugins.yaml b/docs/config/plugins.yaml index f3b7bdfd4..e57fa0d18 100644 --- a/docs/config/plugins.yaml +++ b/docs/config/plugins.yaml @@ -25,6 +25,7 @@ toc: - requestLogger - gzipResponse - serveStatic + - serveStaticFiles - throttle - requestExpiry - inflightRequestThrottle diff --git a/lib/plugins/index.js b/lib/plugins/index.js index 756018074..5fe1e0694 100644 --- a/lib/plugins/index.js +++ b/lib/plugins/index.js @@ -26,6 +26,7 @@ module.exports = { requestExpiry: require('./requestExpiry'), requestLogger: require('./bunyan'), serveStatic: require('./static'), + serveStaticFiles: require('./staticFiles'), throttle: require('./throttle'), urlEncodedBodyParser: require('./formBodyParser'), diff --git a/lib/plugins/staticFiles.js b/lib/plugins/staticFiles.js new file mode 100644 index 000000000..b6f605ff7 --- /dev/null +++ b/lib/plugins/staticFiles.js @@ -0,0 +1,140 @@ +'use strict'; +var assert = require('assert-plus'); +var errors = require('restify-errors'); +var path = require('path'); +var send = require('send'); +var shallowCopy = require('./utils/shallowCopy'); + +///--- Globals +var MethodNotAllowedError = errors.MethodNotAllowedError; +var NotAuthorizedError = errors.NotAuthorizedError; +var ResourceNotFoundError = errors.ResourceNotFoundError; + +/** + * Serves static files, with API similar to expressjs + * + * @public + * @function serveStaticFiles + * @param {String} directory - the directory to serve files from + * @param {Object} opts - an options object, which is optional + * @param {Number} [opts.maxAge=0] - specify max age in millisecs + * @param {Boolean} [opts.etag=true] - enable/disable etag, default = true + * @param {Function} [opts.setHeaders] - set custom headers for the Files + * (synchronously), The function is called as `fn(res, path, stat)`, + * where the arguments are: + * `res` the response object + * `path` the file path that is being sent + * `stat` the stat object of the file that is being sent + * @throws {MethodNotAllowedError} + * @throws {NotAuthorizedError} + * @throws {ResourceNotFoundError} + * @returns {Function} Handler + * @example + * + * The serveStaticFiles plugin allows you to map a GET route to a + * directory on the disk + * + * server.get('/public/*', // don't forget the `/*` + * restify.plugins.serveStaticFiles('./documentation/v1') + * ); + * @example + * + * The GET `route` and `directory` combination will serve a file + * located in `./documentation/v1/index.html` when you attempt to hit + * `http://localhost:8080/public/index.html` + * + * The plugin uses [send](https://github.com/pillarjs/send) under the hood + * which is also used by `expressjs` to serve static files. Most of the options + * that work with `send` will work with this plugin. + * + * The default file the plugin looks for is `index.html` + * + * server.get('/public/*', + * restify.plugins.serveStaticFiles('./documentation/v1', { + * maxAge: 3600000, // this is in millisecs + * etag: false, + * setHeaders: function setCustomHeaders(response, requestedPath, stat) { + * response.setHeader('restify-plugin-x', 'awesome'); + * } + * }) + * ); + */ +function serveStaticFiles(directory, opts) { + // make a copy of the options that will be passed to send + var optionsPlugin = shallowCopy(opts || {}); + var optionsSend = shallowCopy(opts || {}); + // lets assert some options + assert.object(optionsSend, 'options'); + assert.object(optionsPlugin, 'options'); + assert.string(directory, 'directory'); + + // `send` library relies on `root` to specify the root folder + // to look for files + optionsSend.root = path.resolve(directory); + // `setHeaders` is only understood by our plugin + if (optionsSend.setHeaders) { + delete optionsSend.setHeaders; + } + + return function handleServeStaticFiles(req, res, next) { + // Check to make sure that this was either a GET or a HEAD request + if (req.method !== 'GET' && req.method !== 'HEAD') { + return next(new MethodNotAllowedError('%s', req.method)); + } + // we expect the params to have `*`: + // This allows the router to accept any file path + var requestedFile = req.params['*'] || 'index.html'; + // This is used only for sending back correct error message text + var requestedFullPath = req.url; + // Rely on `send` library to create a stream + var stream = send(req, requestedFile, optionsSend); + + // Lets handle the various events being emitted by send module + + // stream has ended, must call `next()` + stream.on('end', function handleEnd() { + return next(); + }); + + // when `send` encounters any `error`, we have the opportunity + // to handle the errors here + stream.on('error', function handleError(err) { + var respondWithError = null; + // When file does not exist + if (err.statusCode === 404) { + respondWithError = new ResourceNotFoundError(requestedFullPath); + } else { + // or action is forbidden (like requesting a directory) + respondWithError = new NotAuthorizedError(requestedFullPath); + } + return next(respondWithError); + }); + + // If the request was for directory and that directory did not + // have index.html, this will be called + stream.on('directory', function handleDirectoryRequest() { + next(new NotAuthorizedError('%s', requestedFullPath)); + return; + }); + + // stream is about to send headers, and custom headers must be + // set now + stream.on('headers', function handleCustomHeaders( + response, + requestedPath, + stat + ) { + if ( + optionsPlugin.setHeaders && + typeof optionsPlugin.setHeaders === 'function' + ) { + optionsPlugin.setHeaders(response, requestedPath, stat); + } + }); + + // pipe the stream into response + return stream.pipe(res); + }; +} + +module.exports = serveStaticFiles; diff --git a/package.json b/package.json index ec8585851..662013dfc 100644 --- a/package.json +++ b/package.json @@ -110,6 +110,7 @@ "qs": "^6.5.2", "restify-errors": "^5.0.0", "semver": "^5.4.1", + "send": "^0.16.2", "spdy": "^3.4.7", "uuid": "^3.1.0", "vasync": "^1.6.4", diff --git a/test/plugins/staticFiles.test.js b/test/plugins/staticFiles.test.js new file mode 100644 index 000000000..3b44dcd9c --- /dev/null +++ b/test/plugins/staticFiles.test.js @@ -0,0 +1,412 @@ +'use strict'; +/* eslint-disable func-names */ + +// core requires +var fs = require('fs'); +var path = require('path'); +var net = require('net'); + +// external requires +var assert = require('chai').assert; +var restify = require('../../lib/index.js'); +var restifyClients = require('restify-clients'); + +// local files +var helper = require('../lib/helper'); + +// local globals +var SERVER; +var CLIENT; +var PORT; + +describe('staticFiles plugin - no options', function() { + beforeEach(function(done) { + SERVER = restify.createServer({ + dtrace: helper.dtrace, + log: helper.getLog('server') + }); + + SERVER.listen(0, '127.0.0.1', function() { + PORT = SERVER.address().port; + CLIENT = restifyClients.createStringClient({ + url: 'http://127.0.0.1:' + PORT, + dtrace: helper.dtrace, + retry: false + }); + + done(); + }); + }); + + afterEach(function(done) { + CLIENT.close(); + SERVER.close(done); + }); + + var STATIC_FILES_PATH = __dirname + '/testStaticFiles'; + function simpleTests(endpoint, filePath, contentType, done) { + var ENDPOINT = endpoint; + var fileSuffixPath = filePath; + var requestPath = path.join(ENDPOINT, fileSuffixPath); + var fileOnDisk = path.join(STATIC_FILES_PATH, fileSuffixPath); + if (fileSuffixPath.endsWith('/')) { + fileOnDisk = path.join(fileOnDisk, 'index.html'); + } + var fileContent = fs.readFileSync(fileOnDisk, 'utf8'); + var fileStat = fs.statSync(fileOnDisk); + SERVER.get( + ENDPOINT + '/*', + restify.plugins.serveStaticFiles(path.resolve(STATIC_FILES_PATH)) + ); + + CLIENT.get(encodeURI(requestPath), function(err, req, res, obj) { + assert.ifError(err); + assert.equal(fileContent, obj); + // Verify headers + assert.equal(res.headers['cache-control'], 'public, max-age=0'); + assert.equal( + res.headers['content-type'], + contentType //'text/html; charset=UTF-8' + ); + assert.exists(res.headers.etag); + assert.equal( + res.headers['last-modified'], + fileStat.mtime.toUTCString() + ); + done(); + }); + } + it('serve static file', function(done) { + simpleTests('/public', 'index.html', 'text/html; charset=UTF-8', done); + }); + it('serve default static file(index.html)', function(done) { + simpleTests('/public', '/', 'text/html; charset=UTF-8', done); + }); + it('serve static file(file1.txt)', function(done) { + simpleTests('/public', 'file1.txt', 'text/plain; charset=UTF-8', done); + }); + it('serve nested static files in request', function(done) { + simpleTests( + '/public', + 'docs/doc.md', + 'text/markdown; charset=UTF-8', + done + ); + }); + it('serve default nested static file(index.html)', function(done) { + simpleTests('/public', 'docs/', 'text/html; charset=UTF-8', done); + }); + it('serve file paths with special chars', function(done) { + simpleTests( + '/public', + 'special/$_$/bad (file).txt', + 'text/plain; charset=UTF-8', + done + ); + }); +}); + +describe('staticFiles plugin - with options', function() { + beforeEach(function(done) { + SERVER = restify.createServer({ + dtrace: helper.dtrace, + log: helper.getLog('server') + }); + + SERVER.listen(0, '127.0.0.1', function() { + PORT = SERVER.address().port; + CLIENT = restifyClients.createStringClient({ + url: 'http://127.0.0.1:' + PORT, + dtrace: helper.dtrace, + retry: false + }); + + done(); + }); + }); + + afterEach(function(done) { + CLIENT.close(); + SERVER.close(done); + }); + + var STATIC_FILES_PATH = __dirname + '/testStaticFiles'; + + var OPTIONS = { + maxAge: 3600000, // this is in millisecs + etag: false, + setHeaders: function setCustomHeaders(response, requestedPath, stat) { + response.setHeader('restify-plugin-x', 'awesome'); + } + }; + + function testsWithOptions(endpoint, filePath, options, contentType, done) { + var ENDPOINT = endpoint; + var fileSuffixPath = filePath; + var requestPath = path.join(ENDPOINT, fileSuffixPath); + var fileOnDisk = path.join(STATIC_FILES_PATH, fileSuffixPath); + if (fileSuffixPath.endsWith('/')) { + fileOnDisk = path.join(fileOnDisk, 'index.html'); + } + var fileContent = fs.readFileSync(fileOnDisk, 'utf8'); + var fileStat = fs.statSync(fileOnDisk); + SERVER.get( + ENDPOINT + '/*', + restify.plugins.serveStaticFiles( + path.resolve(STATIC_FILES_PATH), + options + ) + ); + + CLIENT.get(encodeURI(requestPath), function(err, req, res, obj) { + assert.ifError(err); + assert.equal(fileContent, obj); + // Verify headers + assert.equal(res.headers['cache-control'], 'public, max-age=3600'); + assert.equal( + res.headers['content-type'], + contentType //'text/html; charset=UTF-8' + ); + assert.notExists(res.headers.etag); + assert.equal( + res.headers['last-modified'], + fileStat.mtime.toUTCString() + ); + assert.equal(res.headers['restify-plugin-x'], 'awesome'); + done(); + }); + } + + it('serve static file', function(done) { + testsWithOptions( + '/public', + 'index.html', + OPTIONS, + 'text/html; charset=UTF-8', + done + ); + }); + it('serve default static file(index.html)', function(done) { + testsWithOptions( + '/public', + '/', + OPTIONS, + 'text/html; charset=UTF-8', + done + ); + }); + it('serve static file(file1.txt)', function(done) { + testsWithOptions( + '/public', + 'file1.txt', + OPTIONS, + 'text/plain; charset=UTF-8', + done + ); + }); + it('serve nested static files in request', function(done) { + testsWithOptions( + '/public', + 'docs/doc.md', + OPTIONS, + 'text/markdown; charset=UTF-8', + done + ); + }); + it('serve default nested static file(index.html)', function(done) { + testsWithOptions( + '/public', + 'docs/', + OPTIONS, + 'text/html; charset=UTF-8', + done + ); + }); + it('serve file paths with special chars', function(done) { + testsWithOptions( + '/public', + 'special/$_$/bad (file).txt', + OPTIONS, + 'text/plain; charset=UTF-8', + done + ); + }); +}); + +describe('staticFiles plugin - negative cases', function() { + beforeEach(function(done) { + SERVER = restify.createServer({ + dtrace: helper.dtrace, + log: helper.getLog('server') + }); + + SERVER.listen(0, '127.0.0.1', function() { + PORT = SERVER.address().port; + CLIENT = restifyClients.createStringClient({ + url: 'http://127.0.0.1:' + PORT, + dtrace: helper.dtrace, + retry: false + }); + + done(); + }); + }); + + afterEach(function(done) { + CLIENT.close(); + SERVER.close(done); + }); + + var STATIC_FILES_PATH = __dirname + '/testStaticFiles'; + var OPTIONS = { + maxAge: 3600000, // this is in millisecs + etag: false, + setHeaders: function setCustomHeaders(response, requestedPath, stat) { + response.setHeader('restify-plugin-x', 'awesome'); + } + }; + function negativeTests( + endpoint, + filePath, + expectedStatusCode, + expectedStatusMsg, + done + ) { + var ENDPOINT = endpoint; + var fileSuffixPath = filePath; + var requestPath = path.join(ENDPOINT, fileSuffixPath); + SERVER.get( + ENDPOINT + '/*', + restify.plugins.serveStaticFiles( + path.resolve(STATIC_FILES_PATH), + OPTIONS + ) + ); + + CLIENT.get(encodeURI(requestPath), function(err, req, res, obj) { + assert.exists(err); + assert.equal(res.statusCode, expectedStatusCode); + assert.equal(res.statusMessage, expectedStatusMsg); + done(); + }); + } + it('fail to serve root directory', function(done) { + negativeTests('/public', '', 404, 'Not Found', done); + }); + it('fail to serve nested directory', function(done) { + negativeTests('/public', 'docs', 403, 'Forbidden', done); + }); + it('fail on file not found', function(done) { + negativeTests('/public', 'file2.txt', 404, 'Not Found', done); + }); + it('fail on nested file not found', function(done) { + negativeTests( + '/public', + 'docs/doc_not_there.md', + 404, + 'Not Found', + done + ); + }); + it('fail on missing file special characters', function(done) { + negativeTests( + '/public', + 'special/$_$/bad (file)~notExists.txt', + 404, + 'Not Found', + done + ); + }); + it('fail on POST', function(done) { + var ENDPOINT = '/public'; + var fileSuffixPath = 'docs/'; + var requestPath = path.join(ENDPOINT, fileSuffixPath); + SERVER.post( + ENDPOINT + '/*', + restify.plugins.serveStaticFiles( + path.resolve(STATIC_FILES_PATH), + OPTIONS + ) + ); + + CLIENT.get(encodeURI(requestPath), function(err, req, res, obj) { + assert.exists(err); + assert.equal(res.statusCode, 405); + assert.equal(res.statusMessage, 'Method Not Allowed'); + done(); + }); + }); +}); + +describe('staticFiles plugin - with sockets', function() { + // for some reason the server.close with socket + // takes longer to close + this.timeout(15000); + beforeEach(function(done) { + SERVER = restify.createServer({ + dtrace: helper.dtrace, + log: helper.getLog('server') + }); + + SERVER.listen(0, '127.0.0.1', function() { + PORT = SERVER.address().port; + done(); + }); + }); + + afterEach(function(done) { + SERVER.close(done); + }); + + var STATIC_FILES_PATH = __dirname + '/testStaticFiles'; + + var OPTIONS = { + maxAge: 3600000, // this is in millisecs + etag: false, + setHeaders: function setCustomHeaders(response, requestedPath, stat) { + response.setHeader('restify-plugin-x', 'awesome'); + } + }; + + function testsWithOptions(endpoint, filePath, done) { + var ENDPOINT = endpoint; + var fileSuffixPath = filePath; + var requestPath = path.join(ENDPOINT, fileSuffixPath); + var socket = new net.Socket(); + + SERVER.get( + ENDPOINT + '/*', + restify.plugins.serveStaticFiles( + path.resolve(STATIC_FILES_PATH), + OPTIONS + ) + ); + + var RAW_REQUEST = + 'GET ' + + requestPath + + ' HTTP/1.1\r\n' + + 'Host: 127.0.0.1:' + + PORT + + '\r\n' + + 'User-Agent: curl/7.48.0\r\n' + + 'Accept: */*\r\n' + + '\r\n'; + + socket.connect({ host: '127.0.0.1', port: PORT }, function() { + socket.write(RAW_REQUEST, 'utf8', function(err2, data) { + assert.ifError(err2); + }); + }); + + socket.on('data', function(data) { + var stringData = data.toString('utf8'); + assert.isTrue(stringData.indexOf('restify-plugin-x') > 0); + done(); + }); + } + + it('serve static file', function(done) { + testsWithOptions('/public', 'index.html', done); + }); +}); diff --git a/test/plugins/testStaticFiles/docs/doc.md b/test/plugins/testStaticFiles/docs/doc.md new file mode 100644 index 000000000..6a24b254b --- /dev/null +++ b/test/plugins/testStaticFiles/docs/doc.md @@ -0,0 +1 @@ +#This is doc.md \ No newline at end of file diff --git a/test/plugins/testStaticFiles/docs/index.html b/test/plugins/testStaticFiles/docs/index.html new file mode 100644 index 000000000..c38648df4 --- /dev/null +++ b/test/plugins/testStaticFiles/docs/index.html @@ -0,0 +1,12 @@ + + + + + + + Document + + +

testStaticFiles/docs/index.html

+ + diff --git a/test/plugins/testStaticFiles/file1.txt b/test/plugins/testStaticFiles/file1.txt new file mode 100644 index 000000000..97f701ce3 --- /dev/null +++ b/test/plugins/testStaticFiles/file1.txt @@ -0,0 +1 @@ +This is file1.txt \ No newline at end of file diff --git a/test/plugins/testStaticFiles/index.html b/test/plugins/testStaticFiles/index.html new file mode 100644 index 000000000..e0383605d --- /dev/null +++ b/test/plugins/testStaticFiles/index.html @@ -0,0 +1,12 @@ + + + + + + + Document + + +

testStaticFiles/index.html

+ + diff --git a/test/plugins/testStaticFiles/special/$_$/bad (file).txt b/test/plugins/testStaticFiles/special/$_$/bad (file).txt new file mode 100644 index 000000000..2dcbcf33f --- /dev/null +++ b/test/plugins/testStaticFiles/special/$_$/bad (file).txt @@ -0,0 +1 @@ +This is a very badly named file. \ No newline at end of file diff --git a/tools/docsBuild.js b/tools/docsBuild.js index ce3a6e60d..96a630af4 100644 --- a/tools/docsBuild.js +++ b/tools/docsBuild.js @@ -58,6 +58,7 @@ var docsConfig = [ path.join(__dirname, LIB_PATH, 'plugins/bunyan.js'), path.join(__dirname, LIB_PATH, 'plugins/gzip.js'), path.join(__dirname, LIB_PATH, 'plugins/static.js'), + path.join(__dirname, LIB_PATH, 'plugins/staticFiles.js'), path.join(__dirname, LIB_PATH, 'plugins/throttle.js'), path.join(__dirname, LIB_PATH, 'plugins/requestExpiry.js'), path.join(