2017-10-21 07:44:27 +02:00
|
|
|
---
|
|
|
|
|
title: Plugins API
|
|
|
|
|
permalink: /docs/plugins-api/
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
|
|
|
|
|
|
|
|
|
### Table of Contents
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- [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]
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
## Usage
|
|
|
|
|
|
|
|
|
|
Restify comes bundled with a selection of useful plugins. These are accessible
|
|
|
|
|
off of `restify.plugins` and `restify.pre`.
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
var server = restify.createServer();
|
|
|
|
|
server.use(restify.plugins.acceptParser(server.acceptable));
|
|
|
|
|
server.use(restify.plugins.authorizationParser());
|
|
|
|
|
server.use(restify.plugins.dateParser());
|
|
|
|
|
server.use(restify.plugins.queryParser());
|
|
|
|
|
server.use(restify.plugins.jsonp());
|
|
|
|
|
server.use(restify.plugins.gzipResponse());
|
|
|
|
|
server.use(restify.plugins.bodyParser());
|
|
|
|
|
server.use(restify.plugins.requestExpiry());
|
|
|
|
|
server.use(restify.plugins.throttle({
|
|
|
|
|
burst: 100,
|
|
|
|
|
rate: 50,
|
|
|
|
|
ip: true,
|
|
|
|
|
overrides: {
|
|
|
|
|
'192.168.1.1': {
|
|
|
|
|
rate: 0, // unlimited
|
|
|
|
|
burst: 0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
server.use(restify.plugins.conditionalRequest());
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## server.pre() plugins
|
|
|
|
|
|
|
|
|
|
This module includes various pre plugins, which are intended to be used prior
|
|
|
|
|
to routing of the URL. To use a plugin before routing, use the `server.pre()`
|
|
|
|
|
method.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### context
|
|
|
|
|
|
2017-10-24 22:22:30 +02:00
|
|
|
This plugin creates `req.set(key, val)` and `req.get(key)` methods for
|
2017-10-21 07:44:27 +02:00
|
|
|
setting and retrieving request specific data.
|
|
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
server.pre(restify.plugins.pre.context());
|
|
|
|
|
server.get('/', [
|
|
|
|
|
function(req, res, next) {
|
|
|
|
|
req.set(myMessage, 'hello world');
|
|
|
|
|
return next();
|
|
|
|
|
},
|
|
|
|
|
function two(req, res, next) {
|
|
|
|
|
res.send(req.get(myMessage)); // => sends 'hello world'
|
|
|
|
|
return next();
|
|
|
|
|
}
|
|
|
|
|
]);
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### dedupeSlashes
|
|
|
|
|
|
|
|
|
|
This plugin deduplicates extra slashes found in the URL. This can help with
|
|
|
|
|
malformed URLs that might otherwise get misrouted.
|
|
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
server.pre(restify.plugins.pre.dedupeSlashes());
|
|
|
|
|
server.get('/hello/:one', function(req, res, next) {
|
|
|
|
|
res.send(200);
|
|
|
|
|
return next();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// the server will now convert requests to /hello//jake => /hello/jake
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### pause
|
|
|
|
|
|
|
|
|
|
This pre handler fixes issues with node hanging when an `asyncHandler` is
|
2017-10-24 22:22:30 +02:00
|
|
|
used prior to `bodyParser`.
|
2019-03-04 10:19:37 -08:00
|
|
|
[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]
|
2017-10-21 07:44:27 +02:00
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### sanitizePath
|
|
|
|
|
|
2017-10-24 22:22:30 +02:00
|
|
|
Cleans up sloppy URLs on the request object,
|
2017-10-21 07:44:27 +02:00
|
|
|
like `/foo////bar///` to `/foo/bar`.
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### reqIdHeaders
|
|
|
|
|
|
2017-10-24 22:22:30 +02:00
|
|
|
This plugin pulls the value from an incoming request header and uses it
|
|
|
|
|
as the value of the request id. Subsequent calls to `req.id()`
|
2017-10-21 07:44:27 +02:00
|
|
|
will return the header values.
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts` **[Object][39]** an options object
|
|
|
|
|
- `opts.headers` **[Array][40]<[String][41]>** array of headers from where to pull existing
|
2017-10-21 07:44:27 +02:00
|
|
|
request id headers. Lookup precedence
|
|
|
|
|
is left to right (lowest index first)
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### strictQueryParams
|
|
|
|
|
|
2017-10-24 22:22:30 +02:00
|
|
|
Prevents `req.urls` non-strict key-value query params
|
|
|
|
|
|
|
|
|
|
The Request-URI is transmitted in the format specified in section 3.2.1.
|
|
|
|
|
If the Request-URI is encoded using the "% HEX HEX" encoding [42],
|
|
|
|
|
the origin server MUST decode the Request-URI
|
|
|
|
|
in order to properly interpret the request.
|
|
|
|
|
Servers SHOULD respond to invalid Request-URIs
|
|
|
|
|
with an appropriate status code.
|
|
|
|
|
|
|
|
|
|
part of Hypertext Transfer Protocol -- HTTP/1.1 | 5.1.2 Request-URI
|
|
|
|
|
RFC 2616 Fielding, et al.
|
|
|
|
|
|
2017-10-21 07:44:27 +02:00
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options` **[Object][39]?** an options object
|
|
|
|
|
- `options.message` **[String][41]?** a custom error message
|
2017-10-24 22:22:30 +02:00
|
|
|
default value:
|
2017-10-21 07:44:27 +02:00
|
|
|
"Url query params does not meet strict format"
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### userAgentConnection
|
|
|
|
|
|
|
|
|
|
This basically exists for `curl`. `curl` on `HEAD` requests usually
|
|
|
|
|
just sits there and hangs, unless you explicitly set
|
|
|
|
|
Connection:close. And in general, you probably want to set
|
|
|
|
|
Connection: close to curl anyway.
|
|
|
|
|
|
|
|
|
|
Also, because curl spits out an annoying message to stderr about
|
|
|
|
|
remaining bytes if content-length is set, this plugin also drops
|
|
|
|
|
the `content-length` header (some user agents handle it and want it,
|
|
|
|
|
curl does not).
|
|
|
|
|
|
|
|
|
|
To be slightly more generic, the options block takes a user
|
|
|
|
|
agent regexp, however.
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options` **[Object][39]?** an options object
|
|
|
|
|
- `options.userAgentRegExp` **[RegExp][42]** matching any
|
2017-10-24 22:22:30 +02:00
|
|
|
user-agents applicable (optional, default `/^curl.+/`)
|
2017-10-21 07:44:27 +02:00
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
## server.use() plugins
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### acceptParser
|
|
|
|
|
|
|
|
|
|
Parses the `Accept` header, and ensures that the server can respond to what
|
|
|
|
|
the client asked for. In almost all cases passing in `server.acceptable` is
|
|
|
|
|
all that's required, as that's an array of content types the server knows
|
|
|
|
|
how to respond to (with the formatters you've registered). If the request is
|
|
|
|
|
for a non-handled type, this plugin will return a `NotAcceptableError` (406).
|
|
|
|
|
|
|
|
|
|
Note you can get the set of types allowed from a restify server by doing
|
|
|
|
|
`server.acceptable`.
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `accepts` **[Array][40]<[String][41]>** array of accept types.
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
server.use(restify.plugins.acceptParser(server.acceptable));
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- Throws **NotAcceptableError**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** restify handler.
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### authorizationParser
|
|
|
|
|
|
2017-10-24 22:22:30 +02:00
|
|
|
Parses out the `Authorization` header as best restify can.
|
|
|
|
|
Currently only HTTP Basic Auth and
|
2019-03-04 10:19:37 -08:00
|
|
|
[HTTP Signature][43]
|
2017-10-21 07:44:27 +02:00
|
|
|
schemes are supported.
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options` **[Object][39]?** an optional options object that is
|
2017-10-24 22:22:30 +02:00
|
|
|
passed to http-signature
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Subsequent handlers will see `req.authorization`, which looks like above.
|
|
|
|
|
|
|
|
|
|
`req.username` will also be set, and defaults to 'anonymous'. If the scheme
|
2017-10-21 07:44:27 +02:00
|
|
|
is unrecognized, the only thing available in `req.authorization` will be
|
2019-03-04 10:19:37 -08:00
|
|
|
`scheme` and `credentials` - it will be up to you to parse out the rest.
|
|
|
|
|
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
{
|
|
|
|
|
scheme: "<Basic|Signature|...>",
|
|
|
|
|
credentials: "<Undecoded value of header>",
|
|
|
|
|
basic: {
|
|
|
|
|
username: $user
|
|
|
|
|
password: $password
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- Throws **InvalidArgumentError**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### dateParser
|
|
|
|
|
|
2017-10-24 22:22:30 +02:00
|
|
|
Parses out the HTTP Date header (if present) and checks for clock skew.
|
|
|
|
|
If the header is invalid, a `InvalidHeaderError` (`400`) is returned.
|
|
|
|
|
If the clock skew exceeds the specified value,
|
2017-10-21 07:44:27 +02:00
|
|
|
a `RequestExpiredError` (`400`) is returned.
|
|
|
|
|
Where expired means the request originated at a time
|
2017-10-24 22:22:30 +02:00
|
|
|
before (`$now - $clockSkew`).
|
2017-10-21 07:44:27 +02:00
|
|
|
The default clockSkew allowance is 5m (thanks
|
|
|
|
|
Kerberos!)
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `clockSkew` **[Number][44]** allowed clock skew in seconds. (optional, default `300`)
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
// Allows clock skew of 1m
|
|
|
|
|
server.use(restify.plugins.dateParser(60));
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- Throws **RequestExpiredError**
|
|
|
|
|
- Throws **InvalidHeaderError**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** restify handler.
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### queryParser
|
|
|
|
|
|
2017-10-24 22:22:30 +02:00
|
|
|
Parses the HTTP query string (i.e., `/foo?id=bar&name=mark`).
|
|
|
|
|
If you use this, the parsed content will always be available in `req.query`,
|
|
|
|
|
additionally params are merged into `req.params`.
|
2017-10-21 07:44:27 +02:00
|
|
|
You can disable by passing in `mapParams: false` in the options object.
|
|
|
|
|
|
|
|
|
|
Many options correspond directly to option defined for the underlying
|
2019-03-04 10:19:37 -08:00
|
|
|
[`qs.parse`][45].
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options` **[Object][39]?** an options object
|
|
|
|
|
- `options.mapParams` **[Object][39]** disable passing (optional, default `true`)
|
|
|
|
|
- `options.mapParams` **[Boolean][46]** Copies parsed query parameters
|
2017-10-21 07:44:27 +02:00
|
|
|
into`req.params`. (optional, default `false`)
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.overrideParams` **[Boolean][46]** Only applies when if
|
2017-10-24 22:22:30 +02:00
|
|
|
mapParams true.
|
2017-10-21 07:44:27 +02:00
|
|
|
When true, will stomp on req.params field when existing value is found. (optional, default `false`)
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.allowDots` **[Boolean][46]** Transform `?foo.bar=baz` to a
|
2017-10-21 07:44:27 +02:00
|
|
|
nested object: `{foo: {bar: 'baz'}}`. (optional, default `false`)
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.arrayLimit` **[Number][44]** Only transform `?a[$index]=b`
|
2017-10-24 22:22:30 +02:00
|
|
|
to an array if `$index` is less than `arrayLimit`. (optional, default `20`)
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.depth` **[Number][44]** The depth limit for parsing
|
2017-10-24 22:22:30 +02:00
|
|
|
nested objects, e.g. `?a[b][c][d][e][f][g][h][i]=j`. (optional, default `5`)
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.parameterLimit` **[Number][44]** Maximum number of query
|
2017-10-24 22:22:30 +02:00
|
|
|
params parsed. Additional params are silently dropped. (optional, default `1000`)
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.parseArrays` **[Boolean][46]** Whether to parse
|
2017-10-24 22:22:30 +02:00
|
|
|
`?a[]=b&a[1]=c` to an array, e.g. `{a: ['b', 'c']}`. (optional, default `true`)
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.plainObjects` **[Boolean][46]** Whether `req.query` is a
|
2017-10-24 22:22:30 +02:00
|
|
|
"plain" object -- does not inherit from `Object`.
|
|
|
|
|
This can be used to allow query params whose names collide with Object
|
2017-10-21 07:44:27 +02:00
|
|
|
methods, e.g. `?hasOwnProperty=blah`. (optional, default `false`)
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.strictNullHandling` **[Boolean][46]** If true, `?a&b=`
|
2017-10-24 22:22:30 +02:00
|
|
|
results in `{a: null, b: ''}`. Otherwise, `{a: '', b: ''}`. (optional, default `false`)
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
server.use(restify.plugins.queryParser({ mapParams: false }));
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### jsonp
|
|
|
|
|
|
|
|
|
|
Parses the jsonp callback out of the request.
|
|
|
|
|
Supports checking the query string for `callback` or `jsonp` and ensuring
|
|
|
|
|
that the content-type is appropriately set if JSONP params are in place.
|
|
|
|
|
There is also a default `application/javascript` formatter to handle this.
|
|
|
|
|
|
|
|
|
|
You _should_ set the `queryParser` plugin to run before this, but if you
|
|
|
|
|
don't this plugin will still parse the query string properly.
|
|
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
var server = restify.createServer();
|
|
|
|
|
server.use(restify.plugins.jsonp());
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### bodyParser
|
|
|
|
|
|
|
|
|
|
Blocks your chain on reading and parsing the HTTP request body. Switches on
|
|
|
|
|
`Content-Type` and does the appropriate logic. `application/json`,
|
|
|
|
|
`application/x-www-form-urlencoded` and `multipart/form-data` are currently
|
|
|
|
|
supported.
|
|
|
|
|
|
2017-10-24 22:22:30 +02:00
|
|
|
Parses `POST` bodies to `req.body`. automatically uses one of the following
|
|
|
|
|
parsers based on content type:
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
- `urlEncodedBodyParser(options)` - parses url encoded form bodies
|
|
|
|
|
- `jsonBodyParser(options)` - parses JSON POST bodies
|
|
|
|
|
- `multipartBodyParser(options)` - parses multipart form bodies
|
|
|
|
|
|
2017-10-24 22:22:30 +02:00
|
|
|
All bodyParsers support the following options:
|
2017-10-21 07:44:27 +02:00
|
|
|
|
2017-10-24 22:22:30 +02:00
|
|
|
- `options.mapParams` - default false. copies parsed post body values onto
|
2017-10-21 07:44:27 +02:00
|
|
|
req.params
|
2017-10-24 22:22:30 +02:00
|
|
|
- `options.overrideParams` - default false. only applies when if
|
|
|
|
|
mapParams true. when true, will stomp on req.params value when
|
2017-10-21 07:44:27 +02:00
|
|
|
existing value is found.
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options` **[Object][39]?** an option object
|
|
|
|
|
- `options.maxBodySize` **[Number][44]?** The maximum size in bytes allowed in
|
2017-10-21 07:44:27 +02:00
|
|
|
the HTTP body. Useful for limiting clients from hogging server memory.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.mapParams` **[Boolean][46]?** if `req.params` should be filled with
|
2017-10-21 07:44:27 +02:00
|
|
|
parsed parameters from HTTP body.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.mapFiles` **[Boolean][46]?** if `req.params` should be filled with
|
2017-10-24 22:22:30 +02:00
|
|
|
the contents of files sent through a multipart request.
|
2019-03-04 10:19:37 -08:00
|
|
|
[formidable][47] is used internally
|
2017-10-24 22:22:30 +02:00
|
|
|
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
|
2017-10-21 07:44:27 +02:00
|
|
|
`mapParams` is true.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.overrideParams` **[Boolean][46]?** if an entry in `req.params`
|
2017-10-24 22:22:30 +02:00
|
|
|
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
|
2017-10-21 07:44:27 +02:00
|
|
|
`happy` if `overrideParams` is `true`, `sad` otherwise.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.multipartHandler` **[Function][35]?** a callback to handle any
|
2017-10-24 22:22:30 +02:00
|
|
|
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
|
2017-10-21 07:44:27 +02:00
|
|
|
the `mapParams`-option.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.multipartFileHandler` **[Function][35]?** a callback to handle any
|
2017-10-24 22:22:30 +02:00
|
|
|
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 `<input type="file" />`.
|
|
|
|
|
If this is not provided, the default behaviour is to map the contents
|
2017-10-21 07:44:27 +02:00
|
|
|
into `req.params`.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.keepExtensions` **[Boolean][46]?** if you want the uploaded
|
2017-10-24 22:22:30 +02:00
|
|
|
files to include the extensions of the original files
|
|
|
|
|
(multipart uploads only).
|
2017-10-21 07:44:27 +02:00
|
|
|
Does nothing if `multipartFileHandler` is defined.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.uploadDir` **[String][41]?** Where uploaded files are
|
2017-10-24 22:22:30 +02:00
|
|
|
intermediately stored during transfer before the contents is mapped
|
|
|
|
|
into `req.params`.
|
2017-10-21 07:44:27 +02:00
|
|
|
Does nothing if `multipartFileHandler` is defined.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.multiples` **[Boolean][46]?** if you want to support html5 multiple
|
2017-10-21 07:44:27 +02:00
|
|
|
attribute in upload fields.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.hash` **[String][41]?** If you want checksums calculated for
|
2017-10-21 07:44:27 +02:00
|
|
|
incoming files, set this to either `sha1` or `md5`.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.rejectUnknown` **[Boolean][46]?** Set to `true` if you want to end
|
2017-10-24 22:22:30 +02:00
|
|
|
the request with a `UnsupportedMediaTypeError` when none of
|
2017-10-21 07:44:27 +02:00
|
|
|
the supported content types was given.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.requestBodyOnGet` **[Boolean][46]** Parse body of a GET
|
2017-10-21 07:44:27 +02:00
|
|
|
request. (optional, default `false`)
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.reviver` **[Function][35]?** `jsonParser` only. If a function,
|
2017-10-24 22:22:30 +02:00
|
|
|
this prescribes how the value originally produced by parsing is transformed,
|
|
|
|
|
before being returned. For more information check out
|
2017-10-21 07:44:27 +02:00
|
|
|
`JSON.parse(text[, reviver])`.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.maxFieldsSize` **[Number][44]** `multipartParser`
|
2017-10-24 22:22:30 +02:00
|
|
|
only.
|
|
|
|
|
Limits the amount of memory all fields together (except files)
|
|
|
|
|
can allocate in bytes.
|
2017-10-21 07:44:27 +02:00
|
|
|
The default size is `2 * 1024 * 1024` bytes _(2MB)_. (optional, default `2*1024*1024`)
|
|
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
server.use(restify.plugins.bodyParser({
|
|
|
|
|
maxBodySize: 0,
|
|
|
|
|
mapParams: true,
|
|
|
|
|
mapFiles: false,
|
|
|
|
|
overrideParams: false,
|
|
|
|
|
multipartHandler: function(part) {
|
|
|
|
|
part.on('data', function(data) {
|
|
|
|
|
// do something with the multipart data
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
multipartFileHandler: function(part) {
|
|
|
|
|
part.on('data', function(data) {
|
|
|
|
|
// do something with the multipart file data
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
keepExtensions: false,
|
|
|
|
|
uploadDir: os.tmpdir(),
|
|
|
|
|
multiples: true,
|
|
|
|
|
hash: 'sha1',
|
|
|
|
|
rejectUnknown: true,
|
|
|
|
|
requestBodyOnGet: false,
|
|
|
|
|
reviver: undefined,
|
|
|
|
|
maxFieldsSize: 2 * 1024 * 1024
|
|
|
|
|
}));
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- Throws **UnsupportedMediaTypeError**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### requestLogger
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Sets up a child [bunyan][48] logger with
|
2017-10-21 07:44:27 +02:00
|
|
|
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.
|
2019-03-04 10:19:37 -08:00
|
|
|
This logger can be used normally, with [req.log][49].
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
This plugin does _not_ log each individual request. Use the Audit Logging
|
|
|
|
|
plugin or a custom middleware for that use.
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options` **[Object][39]?** an options object
|
|
|
|
|
- `options.headers` **[Array][40]?** A list of headers to transfer from
|
2017-10-24 22:22:30 +02:00
|
|
|
the request to top level props on the log.
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
server.use(restify.plugins.requestLogger({
|
|
|
|
|
properties: {
|
|
|
|
|
foo: 'bar'
|
|
|
|
|
},
|
|
|
|
|
serializers: {...}
|
|
|
|
|
}));
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### gzipResponse
|
|
|
|
|
|
|
|
|
|
If the client sends an `accept-encoding: gzip` header (or one with an
|
2017-10-24 22:22:30 +02:00
|
|
|
appropriate q-val), then the server will automatically gzip all
|
2017-10-21 07:44:27 +02:00
|
|
|
response data.
|
2017-10-24 22:22:30 +02:00
|
|
|
Note that only `gzip` is supported, as this is most widely supported by
|
|
|
|
|
clients in the wild.
|
2017-10-21 07:44:27 +02:00
|
|
|
This plugin will overwrite some of the internal streams, so any
|
|
|
|
|
calls to `res.send`, `res.write`, etc., will be compressed. A side effect is
|
|
|
|
|
that the `content-length` header cannot be known, and so
|
2017-10-24 22:22:30 +02:00
|
|
|
`transfer-encoding: chunked` will _always_ be set when this is in effect.
|
|
|
|
|
This plugin has no impact if the client does not send
|
2017-10-21 07:44:27 +02:00
|
|
|
`accept-encoding: gzip`.
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
[https://github.com/restify/node-restify/issues/284][50]
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts` **[Object][39]?** an options object, see: zlib.createGzip
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
server.use(restify.plugins.gzipResponse());
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### serveStatic
|
|
|
|
|
|
2017-10-24 22:22:30 +02:00
|
|
|
Serves static files.
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options` **[Object][39]** an options object
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
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:
|
|
|
|
|
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
```javascript
|
2018-03-20 11:10:28 -07:00
|
|
|
server.get('/docs/current/*', restify.plugins.serveStatic({
|
2017-10-21 07:44:27 +02:00
|
|
|
directory: './documentation/v1',
|
|
|
|
|
default: 'index.html'
|
|
|
|
|
}));
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
The above `route` and `directory` combination will serve a file located in
|
2017-10-24 22:22:30 +02:00
|
|
|
`./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/`),
|
2017-10-21 07:44:27 +02:00
|
|
|
you can set the `appendRequestPath` option to `false`, and the served file
|
2019-03-04 10:19:37 -08:00
|
|
|
would be `./documentation/v1/index.html`, in the previous example.
|
|
|
|
|
|
|
|
|
|
The plugin will enforce that all files under `directory` are served.
|
2017-10-24 22:22:30 +02:00
|
|
|
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.
|
|
|
|
|
You can specify additional restrictions by passing in a `match` parameter,
|
2017-10-21 07:44:27 +02:00
|
|
|
which is just a `RegExp` to check against the requested file name.
|
2017-10-24 22:22:30 +02:00
|
|
|
Additionally, you may set the `charSet` parameter, which will append a
|
|
|
|
|
character set to the content-type detected by the plugin.
|
|
|
|
|
For example, `charSet: 'utf-8'` will result in HTML being served with a
|
2017-10-21 07:44:27 +02:00
|
|
|
`Content-Type` of `text/html; charset=utf-8`.
|
2017-10-24 22:22:30 +02:00
|
|
|
Lastly, you can pass in a `maxAge` numeric, which will set the
|
2019-03-04 10:19:37 -08:00
|
|
|
`Cache-Control` header. Default is `3600` (1 hour).
|
|
|
|
|
|
|
|
|
|
An additional option for serving a static file is to pass `file` in to the
|
2017-10-24 22:22:30 +02:00
|
|
|
serveStatic method as an option. The following will serve index.html from
|
2019-03-04 10:19:37 -08:00
|
|
|
the documentation/v1/ directory anytime a client requests `/home/`.
|
|
|
|
|
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
```javascript
|
2018-03-20 11:10:28 -07:00
|
|
|
server.get('/home/*', restify.plugins.serveStatic({
|
|
|
|
|
directory: './documentation/v1',
|
|
|
|
|
file: 'index.html'
|
|
|
|
|
}));
|
|
|
|
|
// or
|
|
|
|
|
server.get('/home/([a-z]+[.]html)', restify.plugins.serveStatic({
|
2017-10-21 07:44:27 +02:00
|
|
|
directory: './documentation/v1',
|
|
|
|
|
file: 'index.html'
|
|
|
|
|
}));
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- Throws **MethodNotAllowedError** \|
|
|
|
|
|
- Throws **NotAuthorizedError**
|
|
|
|
|
- Throws **ResourceNotFoundError**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
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
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### throttle
|
|
|
|
|
|
|
|
|
|
Creates an API rate limiter that can be plugged into the standard
|
|
|
|
|
restify request handling pipeline.
|
|
|
|
|
|
|
|
|
|
`restify` ships with a fairly comprehensive implementation of
|
2019-03-04 10:19:37 -08:00
|
|
|
[Token bucket][52], with the ability
|
2017-10-24 22:22:30 +02:00
|
|
|
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.
|
2017-10-21 07:44:27 +02:00
|
|
|
Note that you can always place this on per-URL routes to enable
|
2017-10-24 22:22:30 +02:00
|
|
|
different request rates to different resources (if for example, one route,
|
|
|
|
|
like `/my/slow/database` is much easier to overwhlem
|
2017-10-21 07:44:27 +02:00
|
|
|
than `/my/fast/memcache`).
|
|
|
|
|
|
|
|
|
|
If a client has consumed all of their available rate/burst, an HTTP response
|
|
|
|
|
code of `429`
|
2019-03-04 10:19:37 -08:00
|
|
|
[Too Many Requests][53]
|
2017-10-21 07:44:27 +02:00
|
|
|
is returned.
|
|
|
|
|
|
|
|
|
|
This throttle gives you three options on which to throttle:
|
|
|
|
|
username, IP address and 'X-Forwarded-For'. IP/XFF is a /32 match,
|
|
|
|
|
so keep that in mind if using it. Username takes the user specified
|
|
|
|
|
on req.username (which gets automagically set for supported Authorization
|
|
|
|
|
types; otherwise set it yourself with a filter that runs before this).
|
|
|
|
|
|
|
|
|
|
In both cases, you can set a `burst` and a `rate` (in requests/seconds),
|
|
|
|
|
as an integer/float. Those really translate to the `TokenBucket`
|
|
|
|
|
algorithm, so read up on that (or see the comments above...).
|
|
|
|
|
|
|
|
|
|
In either case, the top level options burst/rate set a blanket throttling
|
|
|
|
|
rate, and then you can pass in an `overrides` object with rates for
|
|
|
|
|
specific users/IPs. You should use overrides sparingly, as we make a new
|
|
|
|
|
TokenBucket to track each.
|
|
|
|
|
|
|
|
|
|
On the `options` object ip and username are treated as an XOR.
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `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,
|
2017-10-21 07:44:27 +02:00
|
|
|
limit (burst) and remaining. (optional, default `false`)
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.overrides` **[Object][39]?** overrides
|
|
|
|
|
- `options.tokensTable` **[Object][39]** a storage engine this plugin will
|
2017-10-21 07:44:27 +02:00
|
|
|
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.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `options.maxKeys` **[Number][44]** If using the default
|
2017-10-24 22:22:30 +02:00
|
|
|
implementation, you can specify how large you
|
|
|
|
|
want the table to be. (optional, default `10000`)
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
An example options object with overrides:
|
|
|
|
|
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
{
|
|
|
|
|
burst: 10, // Max 10 concurrent requests (if tokens)
|
|
|
|
|
rate: 0.5, // Steady state: 1 request / 2 seconds
|
|
|
|
|
ip: true, // throttle per IP
|
|
|
|
|
overrides: {
|
|
|
|
|
'192.168.1.1': {
|
|
|
|
|
burst: 0,
|
|
|
|
|
rate: 0 // unlimited
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- Throws **TooManyRequestsError**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### requestExpiry
|
|
|
|
|
|
|
|
|
|
Request Expiry can be used to throttle requests that have already exceeded
|
2017-10-24 22:22:30 +02:00
|
|
|
their client timeouts. Requests can be sent with a configurable client
|
|
|
|
|
timeout header, e.g. 'x-request-expiry-time', which gives in absolute ms
|
2017-10-21 07:44:27 +02:00
|
|
|
since epoch, when this request will be timed out by the client.
|
|
|
|
|
|
|
|
|
|
This plugin will throttle all incoming requests via a 504 where
|
|
|
|
|
'x-request-expiry-time' less than Date.now() -- since these incoming requests
|
|
|
|
|
have already been timed out by the client. This prevents the server from
|
|
|
|
|
processing unnecessary requests.
|
|
|
|
|
|
|
|
|
|
Request expiry will use headers to tell if the incoming request has expired.
|
|
|
|
|
There are two options for this plugin:
|
|
|
|
|
1\. Absolute Time
|
|
|
|
|
_ Time in Milliseconds since Epoch when this request should be
|
|
|
|
|
considered expired
|
|
|
|
|
2\. Timeout
|
|
|
|
|
_ The request start time is supplied
|
|
|
|
|
_ A timeout, in milliseconds, is given
|
|
|
|
|
_ The timeout is added to the request start time to arrive at the
|
|
|
|
|
absolute time in which the request is considered expired
|
|
|
|
|
|
|
|
|
|
#### Using an external storage mechanism for key/bucket mappings.
|
|
|
|
|
|
|
|
|
|
By default, the restify throttling plugin uses an in-memory LRU to store
|
|
|
|
|
mappings between throttling keys (i.e., IP address) to the actual bucket that
|
|
|
|
|
key is consuming. If this suits you, you can tune the maximum number of keys
|
|
|
|
|
to store in memory with `options.maxKeys`; the default is 10000.
|
|
|
|
|
|
|
|
|
|
In some circumstances, you want to offload this into a shared system, such as
|
2017-10-24 22:22:30 +02:00
|
|
|
Redis, if you have a fleet of API servers and you're not getting steady
|
2017-10-21 07:44:27 +02:00
|
|
|
and/or uniform request distribution. To enable this, you can pass in
|
2017-10-24 22:22:30 +02:00
|
|
|
`options.tokensTable`, which is simply any Object that supports `put` and
|
2017-10-21 07:44:27 +02:00
|
|
|
`get` with a `String` key, and an `Object` value.
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts` **[Object][39]** an options object
|
|
|
|
|
- `opts.absoluteHeader` **[String][41]?** The header key to be used for
|
2017-10-21 07:44:27 +02:00
|
|
|
the expiry time of each request.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts.startHeader` **[String][41]** The header key for the start time
|
2017-10-21 07:44:27 +02:00
|
|
|
of the request.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts.timeoutHeader` **[String][41]** The header key for the time in
|
2017-10-21 07:44:27 +02:00
|
|
|
milliseconds that should ellapse before
|
|
|
|
|
the request is considered expired.
|
|
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
The only option provided is `header` which is the request header used
|
|
|
|
|
to specify the client timeout.
|
|
|
|
|
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
server.use(restify.plugins.requestExpiry({
|
|
|
|
|
header: 'x-request-expiry-time'
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### inflightRequestThrottle
|
|
|
|
|
|
|
|
|
|
The `inflightRequestThrottle` module allows you to specify an upper limit to
|
|
|
|
|
the maximum number of inflight requests your server is able to handle. This
|
|
|
|
|
is a simple heuristic for protecting against event loop contention between
|
|
|
|
|
requests causing unacceptable latencies.
|
|
|
|
|
|
|
|
|
|
The custom error is optional, and allows you to specify your own response
|
|
|
|
|
and status code when rejecting incoming requests due to too many inflight
|
|
|
|
|
requests. It defaults to `503 ServiceUnavailableError`.
|
|
|
|
|
|
|
|
|
|
This plugin should be registered as early as possibly in the middleware stack
|
|
|
|
|
using `pre` to avoid performing unnecessary work.
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts` **[Object][39]** configure this plugin
|
|
|
|
|
- `opts.limit` **[Number][44]** maximum number of inflight requests the server
|
2017-10-21 07:44:27 +02:00
|
|
|
will handle before returning an error
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts.err` **[Error][54]** A restify error used as a response when the
|
2017-10-24 22:22:30 +02:00
|
|
|
inflight request limit is exceeded
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts.server` **[Function][35]** the instance of the restify server this
|
2017-10-24 22:22:30 +02:00
|
|
|
plugin will throttle.
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
var errors = require('restify-errors');
|
|
|
|
|
var restify = require('restify');
|
|
|
|
|
|
|
|
|
|
var server = restify.createServer();
|
|
|
|
|
const options = { limit: 600, server: server };
|
|
|
|
|
options.res = new errors.InternalServerError();
|
|
|
|
|
server.pre(restify.plugins.inflightRequestThrottle(options));
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** middleware to be registered on server.pre
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### cpuUsageThrottle
|
|
|
|
|
|
|
|
|
|
cpuUsageThrottle is a middleware that rejects a variable number of requests
|
|
|
|
|
(between 0% and 100%) based on a historical view of CPU utilization of a
|
|
|
|
|
Node.js process. Essentially, this plugin allows you to define what
|
|
|
|
|
constitutes a saturated Node.js process via CPU utilization and it will
|
|
|
|
|
handle dropping a % of requests based on that definiton. This is useful when
|
|
|
|
|
you would like to keep CPU bound tasks from piling up causing an increased
|
|
|
|
|
per-request latency.
|
|
|
|
|
|
|
|
|
|
The algorithm asks you for a maximum CPU utilization rate, which it uses to
|
2017-11-08 12:14:03 +01:00
|
|
|
determine at what point it should be rejecting 100% of traffic. For a normal
|
2017-10-21 07:44:27 +02:00
|
|
|
Node.js service, this is 1 since Node is single threaded. It uses this,
|
|
|
|
|
paired with a limit that you provide to determine the total % of traffic it
|
|
|
|
|
should be rejecting. For example, if you specify a limit of .5 and a max of
|
|
|
|
|
1, and the current EWMA (next paragraph) value reads .75, this plugin will
|
|
|
|
|
reject approximately 50% of all requests.
|
|
|
|
|
|
|
|
|
|
When looking at the process' CPU usage, this algorithm will take a load
|
|
|
|
|
average over a user specified interval. example, if given an interval of
|
|
|
|
|
250ms, this plugin will attempt to record the average CPU utilization over
|
|
|
|
|
250ms intervals. Due to contention for resources, the duration of each
|
|
|
|
|
average may be wider or narrower than 250ms. To compensate for this, we use
|
|
|
|
|
an exponentially weighted moving average. The EWMA algorithm is provided by
|
|
|
|
|
the ewma module. The parameter for configuring the EWMA is halfLife. This
|
|
|
|
|
value controls how quickly each load average measurment decays to half it's
|
|
|
|
|
value when being represented in the current average. For example, if you
|
|
|
|
|
have an interval of 250, and a halfLife of 250, you will take the previous
|
|
|
|
|
ewma value multiplied by 0.5 and add it to the new CPU utilization average
|
|
|
|
|
measurement multiplied by 0.5. The previous value and the new measurement
|
|
|
|
|
would each represent 50% of the new value. A good way of thinking about the
|
|
|
|
|
halfLife is in terms of how responsive this plugin will be to spikes in CPU
|
|
|
|
|
utilization. The higher the halfLife, the longer CPU utilization will have
|
|
|
|
|
to remain above your defined limit before this plugin begins rejecting
|
|
|
|
|
requests and, converserly, the longer it will have to drop below your limit
|
|
|
|
|
before the plugin begins accepting requests again. This is a knob you will
|
|
|
|
|
want to with play when trying to determine the ideal value for your use
|
|
|
|
|
case.
|
|
|
|
|
|
|
|
|
|
For a better understanding of the EWMA algorithn, refer to the documentation
|
|
|
|
|
for the ewma module.
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts` **[Object][39]** Configure this plugin.
|
|
|
|
|
- `opts.limit` **[Number][44]?** The point at which restify will begin
|
2017-10-24 22:22:30 +02:00
|
|
|
rejecting a % of all requests at the front door.
|
|
|
|
|
This value is a percentage.
|
2017-10-21 07:44:27 +02:00
|
|
|
For example 0.8 === 80% average CPU utilization. Defaults to 0.75.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts.max` **[Number][44]?** The point at which restify will reject 100% of
|
2017-10-24 22:22:30 +02:00
|
|
|
all requests at the front door. This is used in conjunction with limit to
|
2017-10-21 07:44:27 +02:00
|
|
|
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.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts.interval` **[Number][44]?** How frequently we calculate the average CPU
|
2017-10-21 07:44:27 +02:00
|
|
|
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,
|
|
|
|
|
the higher the resolution our load average will be and the more frequently
|
|
|
|
|
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.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts.halfLife` **[Number][44]?** When we sample the CPU usage on an
|
2017-10-24 22:22:30 +02:00
|
|
|
interval, we create a series of data points.
|
|
|
|
|
We take these points and calculate a
|
2017-10-21 07:44:27 +02:00
|
|
|
moving average. The halfLife indicates how quickly a point "decays" to
|
|
|
|
|
half it's value in the moving average. The lower the halfLife, the more
|
|
|
|
|
impact newer data points have on the average. If you want to be extremely
|
|
|
|
|
responsive to spikes in CPU usage, set this to a lower value. If you want
|
|
|
|
|
your process to put more emphasis on recent historical CPU usage when
|
|
|
|
|
determininng whether it should shed load, set this to a higher value. The
|
|
|
|
|
unit is in ms. Defaults to 250.
|
|
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
var restify = require('restify');
|
|
|
|
|
|
|
|
|
|
var server = restify.createServer();
|
|
|
|
|
const options = {
|
|
|
|
|
limit: .75,
|
|
|
|
|
max: 1,
|
|
|
|
|
interval: 250,
|
|
|
|
|
halfLife: 500,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
server.pre(restify.plugins.cpuUsageThrottle(options));
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
You can also update the plugin during runtime using the `.update()` function.
|
|
|
|
|
This function accepts the same `opts` object as a constructor.
|
|
|
|
|
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
var plugin = restify.plugins.cpuUsageThrottle(options);
|
|
|
|
|
server.pre(plugin);
|
|
|
|
|
|
|
|
|
|
plugin.update({ limit: .4, halfLife: 5000 });
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** middleware to be registered on server.pre
|
2017-10-21 07:44:27 +02:00
|
|
|
|
2018-03-20 11:10:28 -07:00
|
|
|
### conditionalHandler
|
|
|
|
|
|
|
|
|
|
Runs first handler that matches to the condition
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `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'
|
2018-03-20 11:10:28 -07:00
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
server.use(restify.plugins.conditionalHandler({
|
|
|
|
|
contentType: 'application/json',
|
|
|
|
|
version: '1.0.0',
|
|
|
|
|
handler: function (req, res, next) {
|
|
|
|
|
next();
|
|
|
|
|
})
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
server.get('/hello/:name', restify.plugins.conditionalHandler([
|
|
|
|
|
{
|
|
|
|
|
version: '1.0.0',
|
|
|
|
|
handler: function(req, res, next) { res.send('1.x'); }
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
version: ['1.5.0', '2.0.0'],
|
|
|
|
|
handler: function(req, res, next) { res.send('1.5.x, 2.x'); }
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
version: '3.0.0',
|
|
|
|
|
contentType: ['text/html', 'text/html']
|
|
|
|
|
handler: function(req, res, next) { res.send('3.x, text'); }
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
version: '3.0.0',
|
|
|
|
|
contentType: 'application/json'
|
|
|
|
|
handler: function(req, res, next) { res.send('3.x, json'); }
|
|
|
|
|
},
|
|
|
|
|
// Array of handlers
|
|
|
|
|
{
|
|
|
|
|
version: '4.0.0',
|
|
|
|
|
handler: [
|
|
|
|
|
function(req, res, next) { next(); },
|
|
|
|
|
function(req, res, next) { next(); },
|
|
|
|
|
function(req, res, next) { res.send('4.x') }
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
]);
|
|
|
|
|
// 'accept-version': '^1.1.0' => 1.5.x, 2.x'
|
|
|
|
|
// 'accept-version': '3.x', accept: 'application/json' => '3.x, json'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- Throws **InvalidVersionError**
|
|
|
|
|
- Throws **UnsupportedMediaTypeError**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2018-03-20 11:10:28 -07:00
|
|
|
|
2017-10-21 07:44:27 +02:00
|
|
|
### conditionalRequest
|
|
|
|
|
|
|
|
|
|
Returns a set of plugins that will compare an already set `ETag` header with
|
|
|
|
|
the client's `If-Match` and `If-None-Match` header, and an already set
|
|
|
|
|
Last-Modified header with the client's `If-Modified-Since` and
|
|
|
|
|
`If-Unmodified-Since` header.
|
|
|
|
|
|
|
|
|
|
You can use this handler to let clients do nice HTTP semantics with the
|
|
|
|
|
"match" headers. Specifically, with this plugin in place, you would set
|
|
|
|
|
`res.etag=$yourhashhere`, and then this plugin will do one of:
|
|
|
|
|
|
|
|
|
|
- return `304` (Not Modified) [and stop the handler chain]
|
|
|
|
|
- return `412` (Precondition Failed) [and stop the handler chain]
|
|
|
|
|
- Allow the request to go through the handler chain.
|
|
|
|
|
|
|
|
|
|
The specific headers this plugin looks at are:
|
|
|
|
|
|
|
|
|
|
- `Last-Modified`
|
|
|
|
|
- `If-Match`
|
|
|
|
|
- `If-None-Match`
|
|
|
|
|
- `If-Modified-Since`
|
|
|
|
|
- `If-Unmodified-Since`
|
|
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
server.use(restify.plugins.conditionalRequest());
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
server.use(function setETag(req, res, next) {
|
|
|
|
|
res.header('ETag', 'myETag');
|
|
|
|
|
res.header('Last-Modified', new Date());
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
server.use(restify.plugins.conditionalRequest());
|
|
|
|
|
|
|
|
|
|
server.get('/hello/:name', function(req, res, next) {
|
|
|
|
|
res.send('hello ' + req.params.name);
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- Throws **BadRequestError**
|
|
|
|
|
- Throws **PreconditionFailedError**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Array][40]<[Function][35]>** Handlers
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### auditLogger
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts` **[Object][39]** The options object.
|
|
|
|
|
- `opts.log` **[Object][39]** The logger.
|
|
|
|
|
- `opts.event` **[String][41]** The event from the server which initiates the
|
2017-10-21 07:44:27 +02:00
|
|
|
log, one of 'pre', 'routed', or 'after'
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts.context` **[Function][35]?** The optional context function of signature
|
2017-10-21 07:44:27 +02:00
|
|
|
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.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts.server` **[Object][39]?** The restify server, used to emit
|
2017-10-24 22:22:30 +02:00
|
|
|
the audit log object programmatically
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts.printLog` **[boolean][46]** Whether to print the log
|
2017-10-21 07:44:27 +02:00
|
|
|
via the logger. (optional, default `true`)
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts.serializers` **[Object][39]?** Override the default logger serializers
|
|
|
|
|
for err, req and res
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Audit logging is a special plugin, as you don't use it with `.use()`
|
|
|
|
|
but with the `after` event:
|
|
|
|
|
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
server.on('after', restify.plugins.auditLogger({
|
|
|
|
|
log: bunyan.createLogger({
|
|
|
|
|
name: 'audit',
|
|
|
|
|
stream: process.stdout
|
|
|
|
|
}),
|
2017-12-18 18:59:17 +01:00
|
|
|
event: 'after',
|
2017-10-21 07:44:27 +02:00
|
|
|
server: SERVER,
|
|
|
|
|
logMetrics : logBuffer,
|
|
|
|
|
printLog : true
|
|
|
|
|
}));
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
You pass in the auditor a bunyan logger, optionally server object,
|
2017-10-21 07:44:27 +02:00
|
|
|
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
|
2019-03-04 10:19:37 -08:00
|
|
|
record lookling like this:
|
|
|
|
|
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
{
|
|
|
|
|
"name": "audit",
|
|
|
|
|
"hostname": "your.host.name",
|
|
|
|
|
"audit": true,
|
|
|
|
|
"remoteAddress": "127.0.0.1",
|
|
|
|
|
"remotePort": 57692,
|
|
|
|
|
"req_id": "ed634c3e-1af0-40e4-ad1e-68c2fb67c8e1",
|
|
|
|
|
"req": {
|
|
|
|
|
"method": "GET",
|
|
|
|
|
"url": "/foo",
|
|
|
|
|
"headers": {
|
|
|
|
|
"authorization": "Basic YWRtaW46am95cGFzczEyMw==",
|
|
|
|
|
"user-agent": "curl/7.19.7 (universal-apple-darwin10.0)
|
|
|
|
|
libcurl/7.19.7 OpenSSL/0.9.8r zlib/1.2.3",
|
|
|
|
|
"host": "localhost:8080",
|
|
|
|
|
"accept": "application/json"
|
|
|
|
|
},
|
|
|
|
|
"httpVersion": "1.1",
|
|
|
|
|
"query": {
|
|
|
|
|
"foo": "bar"
|
|
|
|
|
},
|
|
|
|
|
"trailers": {},
|
|
|
|
|
"version": "*",
|
|
|
|
|
"timers": {
|
|
|
|
|
"bunyan": 52,
|
|
|
|
|
"saveAction": 8,
|
|
|
|
|
"reqResTracker": 213,
|
|
|
|
|
"addContext": 8,
|
|
|
|
|
"addModels": 4,
|
|
|
|
|
"resNamespaces": 5,
|
|
|
|
|
"parseQueryString": 11,
|
|
|
|
|
"instanceHeaders": 20,
|
|
|
|
|
"xForwardedProto": 7,
|
|
|
|
|
"httpsRedirector": 14,
|
|
|
|
|
"readBody": 21,
|
|
|
|
|
"parseBody": 6,
|
|
|
|
|
"xframe": 7,
|
|
|
|
|
"restifyCookieParser": 15,
|
|
|
|
|
"fooHandler": 23,
|
|
|
|
|
"barHandler": 14,
|
|
|
|
|
"carHandler": 14
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"res": {
|
|
|
|
|
"statusCode": 200,
|
|
|
|
|
"headers": {
|
|
|
|
|
"access-control-allow-origin": "*",
|
|
|
|
|
"access-control-allow-headers": "Accept, Accept-Version,
|
|
|
|
|
Content-Length, Content-MD5, Content-Type, Date, Api-Version",
|
|
|
|
|
"access-control-expose-headers": "Api-Version, Request-Id,
|
|
|
|
|
Response-Time",
|
|
|
|
|
"server": "Joyent SmartDataCenter 7.0.0",
|
|
|
|
|
"x-request-id": "ed634c3e-1af0-40e4-ad1e-68c2fb67c8e1",
|
|
|
|
|
"access-control-allow-methods": "GET",
|
|
|
|
|
"x-api-version": "1.0.0",
|
|
|
|
|
"connection": "close",
|
|
|
|
|
"content-length": 158,
|
|
|
|
|
"content-md5": "zkiRn2/k3saflPhxXI7aXA==",
|
|
|
|
|
"content-type": "application/json",
|
|
|
|
|
"date": "Tue, 07 Feb 2012 20:30:31 GMT",
|
|
|
|
|
"x-response-time": 1639
|
|
|
|
|
},
|
|
|
|
|
"trailer": false
|
|
|
|
|
},
|
|
|
|
|
"route": {
|
|
|
|
|
"name": "GetFoo",
|
|
|
|
|
"version": ["1.0.0"]
|
|
|
|
|
},
|
|
|
|
|
"secure": false,
|
|
|
|
|
"level": 30,
|
|
|
|
|
"msg": "GetFoo handled: 200",
|
|
|
|
|
"time": "2012-02-07T20:30:31.896Z",
|
|
|
|
|
"v": 0
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
The `timers` field shows the time each handler took to run in microseconds.
|
2017-10-21 07:44:27 +02:00
|
|
|
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
|
2019-03-04 10:19:37 -08:00
|
|
|
[startHandlerTimer][55] and
|
|
|
|
|
[endHandlerTimer][56] API.
|
2017-10-21 07:44:27 +02:00
|
|
|
You can also listen to auditlog event and get same above log object when
|
2019-03-04 10:19:37 -08:00
|
|
|
log event emits. For example
|
|
|
|
|
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
|
SERVER.on('auditlog', function (data) {
|
|
|
|
|
//do some process with log
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** Handler
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
### metrics
|
|
|
|
|
|
|
|
|
|
The module includes the following plugins to be used with restify's `after`
|
2018-02-09 01:39:36 +01:00
|
|
|
event, e.g., `server.on('after', restify.plugins.metrics());`:
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
A plugin that listens to the server's after event and emits information
|
|
|
|
|
about that request.
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `opts` **[Object][39]** an options obj
|
2017-10-21 07:44:27 +02:00
|
|
|
- `opts.server` **Server** restify server
|
|
|
|
|
- `callback` **createMetrics~callback** a callback fn
|
|
|
|
|
|
|
|
|
|
**Examples**
|
|
|
|
|
|
|
|
|
|
```javascript
|
2018-02-09 01:39:36 +01:00
|
|
|
server.on('after', restify.plugins.metrics({ server: server },
|
|
|
|
|
function (err, metrics, req, res, route) {
|
|
|
|
|
// metrics is an object containing information about the request
|
2017-10-21 07:44:27 +02:00
|
|
|
}));
|
|
|
|
|
```
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[Function][35]** returns a function suitable to be used
|
2017-10-21 07:44:27 +02:00
|
|
|
with restify server's `after` event
|
|
|
|
|
|
|
|
|
|
## Types
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### metrics~callback
|
|
|
|
|
|
|
|
|
|
Callback used by metrics plugin
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Type: [Function][35]
|
2017-10-21 07:44:27 +02:00
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `err` **[Error][54]**
|
|
|
|
|
- `metrics` **[Object][39]** metrics about the request
|
|
|
|
|
- `metrics.statusCode` **[Number][44]** status code of the response. can be
|
2017-10-21 07:44:27 +02:00
|
|
|
undefined in the case of an uncaughtException
|
2019-03-04 10:19:37 -08:00
|
|
|
- `metrics.method` **[String][41]** http request verb
|
|
|
|
|
- `metrics.totalLatency` **[Number][44]** latency includes both request is flushed
|
2018-03-20 11:10:28 -07:00
|
|
|
and all handlers finished
|
2019-03-04 10:19:37 -08:00
|
|
|
- `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
|
2017-10-21 07:44:27 +02:00
|
|
|
in restify.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `metrics.unifinishedRequests` **[Number][44]** Same as `inflightRequests`
|
|
|
|
|
- `metrics.connectionState` **[String][41]** can be either `'close'` or
|
2018-03-20 11:10:28 -07:00
|
|
|
`undefined`. If this value is set, err will be a
|
|
|
|
|
corresponding `RequestCloseError`.
|
2017-10-21 07:44:27 +02:00
|
|
|
If connectionState is either
|
2018-03-20 11:10:28 -07:00
|
|
|
`'close'`, then the `statusCode` is not applicable since the
|
2017-10-21 07:44:27 +02:00
|
|
|
connection was severed before a response was written.
|
2019-03-04 10:19:37 -08:00
|
|
|
- `req` **[Request][57]** the request obj
|
|
|
|
|
- `res` **[Response][58]** the response obj
|
2017-10-21 07:44:27 +02:00
|
|
|
- `route` **Route** the route obj that serviced the request
|
2019-01-09 16:38:09 -08:00
|
|
|
|
|
|
|
|
## req.set
|
|
|
|
|
|
|
|
|
|
Set context value by key
|
|
|
|
|
Requires the context plugin.
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `key` **[String][41]** key
|
2019-01-09 16:38:09 -08:00
|
|
|
- `value` **any** value
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
Returns **[undefined][59]** no return value
|
2019-01-09 16:38:09 -08:00
|
|
|
|
|
|
|
|
## req.get
|
|
|
|
|
|
|
|
|
|
Get context value by key.
|
|
|
|
|
Requires the context plugin.
|
|
|
|
|
|
|
|
|
|
**Parameters**
|
|
|
|
|
|
2019-03-04 10:19:37 -08:00
|
|
|
- `key` **[String][41]** key
|
2019-01-09 16:38:09 -08:00
|
|
|
|
|
|
|
|
Returns **any** value stored in context
|
|
|
|
|
|
|
|
|
|
## req.getAll
|
|
|
|
|
|
|
|
|
|
Get all context
|
|
|
|
|
Requires the context plugin.
|
|
|
|
|
|
|
|
|
|
Returns **any** value stored in context
|
2019-03-04 10:19:37 -08:00
|
|
|
|
|
|
|
|
[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
|