Socket
Socket
Sign inDemoInstall

fastify

Package Overview
Dependencies
123
Maintainers
3
Versions
282
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.26.2 to 0.27.0

benchmarks/fastify-big-json.js

12

docs/Decorators.md

@@ -39,15 +39,19 @@ <h1 align="center">Fastify</h1>

```js
fastify.decorateReply('utility', () => {
fastify.decorateReply('utility', function () {
// something very useful
})
Note: using an arrow function will break the binding of `this` to the Fastify `reply` instance.
```
<a name="decorate-request"></a>
**decorateRequest**
<a name="decorate-request"></a>
**decorateRequest**
As above, this api is needed if you want to add new methods to the `Request` core object.
Just call the `decorateRequest` api and pass the name of the new property and its value.
```js
fastify.decorateRequest('utility', () => {
fastify.decorateRequest('utility', function () {
// something very useful
})
Note: using an arrow function will break the binding of `this` to the Fastify `request` instance.
```

@@ -54,0 +58,0 @@

@@ -93,3 +93,3 @@ <h1 align="center">Fastify</h1>

module.exports = function (fastify, options, next) {
fastify.get('/', schema, function (req, reply) {
fastify.get('/', function (req, reply) {
reply.send({ hello: 'world' })

@@ -96,0 +96,0 @@ })

@@ -7,4 +7,4 @@ <h1 align="center">Fastify</h1>

- `'onRequest'`
- `'preRouting'`
- `'preHandler'`
- `'onResponse'`
- `'onClose'`

@@ -18,2 +18,12 @@

})
fastify.addHook('preHandler', (req, reply, next) => {
// some code
next()
})
fastify.addHook('onResponse', (res, next) => {
// some code
next()
})
```

@@ -25,7 +35,8 @@

If you want to pass a custom error code to the user, just pass it as second parameter to `next()`:
If you want to pass a custom error code to the user, just use `reply.code()`:
```js
fastify.addHook('onRequest', (req, res, next) => {
// some code
next(new Error('some error'), 400)
reply.code(400)
next(new Error('some error'))
})

@@ -35,3 +46,3 @@ ```

The function signature is always the same, `request`, `response`, `next`, it changes a little bit only in the `'preHandler'` hook, where the first two arguments are [`request`](https://github.com/fastify/fastify/blob/master/docs/Request.md) and [`reply`](https://github.com/fastify/fastify/blob/master/docs/Reply.md) core Fastify objects.
Note that in the `'preHandler'` hook the request and rply objects are different from `'onRequest'`, because the two arguments are [`request`](https://github.com/fastify/fastify/blob/master/docs/Request.md) and [`reply`](https://github.com/fastify/fastify/blob/master/docs/Reply.md) core Fastify objects.

@@ -50,3 +61,3 @@ <a name="on-close"></a>

### Scope
Talking about scope, the hooks works in a slightly different way from the Request/Reply encapsulation model. For instance, `onRequest`, `preRouting` and `onClose` are never encapsulated, not matter where you are declaring them, while the `preHandler` hook is always encapsulated if you declare it inside a `register`.
Except for `'onClose'` all the hooks are encapsulated this means that you can decide where your hooks should run by using `register` as explained in the [plugins guide](https://github.com/fastify/fastify/blob/master/docs/Plugins-Guide.md).

@@ -53,0 +64,0 @@ <a name="before-handler"></a>

@@ -11,23 +11,23 @@ <h1 align="center">Fastify</h1>

└─▶ onRequest Hook
4**/5** ◀─┴─▶ run Middlewares
4**/5** ◀─┴─▶ preRouting Hook
4**/5** ◀─┴─▶ Routing
404 ◀─┴─▶ Parsing
415 ◀─┴─▶ Validation
400 ◀─┴─▶ preHandler Hook
4**/5** ◀─┴─▶ beforeHandler
4**/5** ◀─┴─▶ User Handler
└─▶ Reply
└─▶ Outgoing Response
└─▶ Routing
404 ◀─┴─▶ onRequest Hook
4**/5** ◀─┴─▶ run Middlewares
4**/5** ◀─┴─▶ Parsing
415 ◀─┴─▶ Validation
400 ◀─┴─▶ preHandler Hook
4**/5** ◀─┴─▶ beforeHandler
4**/5** ◀─┴─▶ User Handler
└─▶ Reply
│ │
│ └─▶ Outgoing Response
└─▶ onResponse Hook
```

@@ -32,2 +32,3 @@ <h1 align="center">Fastify</h1>

Also remember that middlewares can be encapsulated, this means that you can decide where your middlewares should run by using `register` as explained in the [plugins guide](https://github.com/fastify/fastify/blob/master/docs/Plugins-Guide.md).

@@ -34,0 +35,0 @@ <a name="restrict-usage"></a>

@@ -42,3 +42,3 @@ <h1 align="center">Fastify</h1>

The Fastify's plugin model is fully reentrant and graph-based, it handles without any kind of problem asynchronous code and it guarantees the load order of the plugins, event the close order! *How?* Glad you asked, checkout [`avvio`](https://github.com/mcollina/avvio)!
The Fastify's plugin model is fully reentrant and graph-based, it handles without any kind of problem asynchronous code and it guarantees the load order of the plugins, even the close order! *How?* Glad you asked, checkout [`avvio`](https://github.com/mcollina/avvio)!

@@ -132,3 +132,3 @@ Inside a plugin you can do whatever you want, register routes, utilities (we'll see this in a moment) and do nested registers, just remember to call `next` when everything is set up!

```js
fastify.decorateReply('html', payload => {
fastify.decorateReply('html', function (payload) {
this.type('text/html') // this is the 'Reply' object

@@ -160,3 +160,3 @@ this.send(generateHtml(payload))

```js
fastify.decorateRequest('setHeader', header => {
fastify.decorateRequest('setHeader', function (header) {
this.isHappy = this.req.headers[header]

@@ -250,3 +250,2 @@ })

```
*Note that middlewares executed [before](https://github.com/fastify/fastify/blob/master/docs/Lifecycle.md) routing and the encapsulation model is not applied, this means that if you declare a middleware inside a plugin it will run for all the plugins.*

@@ -253,0 +252,0 @@ <a name="distribution"></a>

@@ -44,4 +44,3 @@ <h1 align="center">Fastify</h1>

### Serialize
Usually you will send your data to the clients via JSON, and Fastify has two powerful tools to help you, [fast-json-stringify](https://www.npmjs.com/package/fast-json-stringify) and [fast-safe-stringify](https://www.npmjs.com/package/fast-safe-stringify).
The first one is used if you have provided an output schema in the route options, otherwise the second one will do de job. We encourage you to use an output schema, it will increase your throughput by x1-4 depending by your payload.
Usually you will send your data to the clients via JSON, and Fastify has a powerful tools to help you: [fast-json-stringify](https://www.npmjs.com/package/fast-json-stringify), which is used if you have provided an output schema in the route options. We encourage you to use an output schema, as it will increase your throughput by x1-4 depending on your payload, and it will prevent accidental disclosure of sensitive information.

@@ -48,0 +47,0 @@ Example:

@@ -25,6 +25,2 @@ 'use strict'

})
.addHook('preRouting', function (req, res, next) {
console.log('preRouting')
next()
})
.addHook('preHandler', function (request, reply, next) {

@@ -34,2 +30,6 @@ console.log('preHandler')

})
.addHook('onResponse', function (res, next) {
console.log('onResponse')
next()
})

@@ -36,0 +36,0 @@ fastify.get('/', opts, function (req, reply) {

@@ -7,5 +7,4 @@ 'use strict'

const https = require('https')
const pinoHttp = require('pino-http')
const Middie = require('middie')
const fastseries = require('fastseries')
const runHooks = require('fastseries')()
var shot = null

@@ -23,3 +22,3 @@ try { shot = require('shot') } catch (e) { }

const Hooks = require('./lib/hooks')
const serializers = require('./lib/serializers')
const loggerUtils = require('./lib/logger')

@@ -33,17 +32,21 @@ function build (options) {

var logger
if (options.logger && isValidLogger(options.logger)) {
logger = pinoHttp({ logger: options.logger, serializers })
if (isValidLogger(options.logger)) {
logger = loggerUtils.createLogger({ logger: options.logger, serializers: loggerUtils.serializers })
} else {
options.logger = options.logger || {}
options.logger.level = options.logger.level || 'fatal'
options.logger.serializers = options.logger.serializers || serializers
logger = pinoHttp(options.logger)
options.logger.serializers = options.logger.serializers || loggerUtils.serializers
logger = loggerUtils.createLogger(options.logger)
}
const router = FindMyWay({ defaultRoute: defaultRoute })
const middie = Middie(_runMiddlewares)
const run = middie.run
const map = new Map()
const runHooks = fastseries()
// logger utils
const genReqId = loggerUtils.reqIdGenFactory()
const now = loggerUtils.now
const OnResponseState = loggerUtils.OnResponseState
const onResponseIterator = loggerUtils.onResponseIterator
const onResponseCallback = loggerUtils.onResponseCallback
const app = avvio(fastify, {})

@@ -119,3 +122,5 @@ // Override to allow the plugin incapsulation

// middleware support
fastify.use = middie.use
fastify.use = use
fastify._middie = Middie(onRunMiddlewares)
fastify._middlewares = []

@@ -131,54 +136,71 @@ // exposes the routes map

function fastify (req, res) {
logger(req, res)
req.id = genReqId()
req.log = res.log = logger.child({ req: req })
// onRequest hook
setImmediate(
runHooks,
new State(req, res),
hookIterator,
fastify._hooks.onRequest,
middlewareCallback
)
res._startTime = now()
res._context = null
res.on('finish', onResFinished)
res.on('error', onResFinished)
router.lookup(req, res)
}
function _runMiddlewares (err, req, res) {
if (err) {
const reply = new Reply(req, res, null)
reply.send(err)
return
function onResFinished (err) {
this.removeListener('finish', onResFinished)
this.removeListener('error', onResFinished)
var ctx = this._context
if (ctx !== null && ctx.onResponse.length > 0) {
// deferring this with setImmediate will
// slow us by 10%
runHooks(new OnResponseState(err, this),
onResponseIterator,
ctx.onResponse,
wrapOnResponseCallback)
} else {
onResponseCallback(err, this)
}
}
// preRouting hook
setImmediate(
runHooks,
new State(req, res),
hookIterator,
fastify._hooks.preRouting,
routeCallback
)
function wrapOnResponseCallback (err) {
onResponseCallback(this.err || err, this.res)
}
function State (req, res) {
this.req = req
this.res = res
function listen (port, address, cb) {
const hasAddress = arguments.length === 3
const _cb = (hasAddress) ? cb : address
fastify.ready(function (err) {
if (err) return _cb(err)
if (hasAddress) {
server.listen(port, address, _cb)
} else {
server.listen(port, _cb)
}
listening = true
})
}
function hookIterator (fn, cb) {
fn(this.req, this.res, cb)
function startHooks (req, res, params, store) {
res._context = store
runHooks(
new State(req, res, params, store),
hookIterator,
store.onRequest,
middlewareCallback
)
}
function middlewareCallback (err, code) {
function middlewareCallback (err) {
if (err) {
const reply = new Reply(this.req, this.res, null)
if (code[0]) reply.code(code[0])
const reply = new Reply(this.req, this.res, this.store)
reply.send(err)
return
}
run(this.req, this.res)
this.store._middie.run(this.req, this.res, this)
}
function routeCallback (err, code) {
function onRunMiddlewares (err, req, res, ctx) {
if (err) {
const reply = new Reply(this.req, this.res, null)
if (code[0]) reply.code(code[0])
const reply = new Reply(req, res, ctx.store)
reply.send(err)

@@ -188,19 +210,16 @@ return

router.lookup(this.req, this.res)
handleRequest(req, res, ctx.params, ctx.store)
}
function listen (port, address, cb) {
const hasAddress = arguments.length === 3
const _cb = (hasAddress) ? cb : address
fastify.ready(function (err) {
if (err) return _cb(err)
if (hasAddress) {
server.listen(port, address, _cb)
} else {
server.listen(port, _cb)
}
listening = true
})
function State (req, res, params, store) {
this.req = req
this.res = res
this.params = params
this.store = store
}
function hookIterator (fn, cb) {
fn(this.req, this.res, cb)
}
function override (instance, fn, opts) {

@@ -211,2 +230,3 @@ if (fn[Symbol.for('skip-override')]) {

const middlewares = Object.assign([], instance._middlewares)
instance = Object.create(instance)

@@ -218,3 +238,9 @@ instance._Reply = Reply.buildReply(instance._Reply)

instance._RoutePrefix = buildRoutePrefix(instance._RoutePrefix, opts)
instance._middlewares = []
instance._middie = Middie(onRunMiddlewares)
for (var i = 0; i < middlewares.length; i++) {
instance.use.apply(instance, middlewares[i])
}
return instance

@@ -282,6 +308,9 @@ }

contentTypeParser: self._contentTypeParser,
onRequest: self._hooks.onRequest,
preHandler: self._hooks.preHandler,
RoutePrefix: self._RoutePrefix,
beforeHandler: options.beforeHandler,
config: options.config
onResponse: options.onResponse,
config: options.config,
middie: self._middie
})

@@ -318,4 +347,7 @@ }

opts.contentTypeParser || _fastify._contentTypeParser,
opts.onRequest || _fastify._hooks.onRequest,
[],
config
opts.onResponse || _fastify._hooks.onResponse,
config,
opts.middie || _fastify._middie
)

@@ -337,3 +369,3 @@

map.get(url)[opts.method] = store
router.on(opts.method, url, handleRequest, store)
router.on(opts.method, url, startHooks, store)
} else {

@@ -343,3 +375,3 @@ const node = {}

map.set(url, node)
router.on(opts.method, url, handleRequest, store)
router.on(opts.method, url, startHooks, store)
}

@@ -353,3 +385,3 @@ done()

function Store (schema, handler, Reply, Request, contentTypeParser, preHandler, config) {
function Store (schema, handler, Reply, Request, contentTypeParser, onRequest, preHandler, onResponse, config, middie) {
this.schema = schema

@@ -360,4 +392,7 @@ this.handler = handler

this.contentTypeParser = contentTypeParser
this.onRequest = onRequest
this.preHandler = preHandler
this.onResponse = onResponse
this.config = config
this._middie = middie
}

@@ -411,2 +446,12 @@

function use (url, fn) {
if (typeof url === 'string') {
const prefix = this._RoutePrefix.prefix
url = prefix + (url === '/' && prefix.length > 0 ? '' : url)
}
this._middlewares.push([url, fn])
this._middie.use(url, fn)
return this
}
function addHook (name, fn) {

@@ -432,3 +477,3 @@ this._hooks.add(name, fn)

})
logger.logger.error(e, 'client error')
logger.error(e, 'client error')
socket.end(`HTTP/1.1 400 Bad Request\r\nContent-Length: ${body.length}\r\nContent-Type: 'application/json'\r\n\r\n${body}`)

@@ -435,0 +480,0 @@ }

@@ -5,4 +5,4 @@ 'use strict'

'onRequest',
'preRouting',
'preHandler',
'onResponse',
'onClose'

@@ -13,4 +13,4 @@ ]

this.onRequest = []
this.preRouting = []
this.preHandler = []
this.onResponse = []
this._fastify = fastify

@@ -37,5 +37,5 @@ }

const H = new _Hooks()
H.onRequest = h.onRequest
H.preRouting = h.preRouting
H.onRequest = Object.create(h.onRequest)
H.preHandler = Object.create(h.preHandler)
H.onResponse = Object.create(h.onResponse)
H._fastify = h._fastify

@@ -42,0 +42,0 @@ return H

@@ -6,3 +6,2 @@ /* eslint-disable no-useless-return */

const pump = require('pump')
const safeStringify = require('fast-safe-stringify')
const xtend = require('xtend')

@@ -54,3 +53,3 @@ const validation = require('./validation')

this,
safeStringify(payload.output.payload)
stringify(payload.output.payload)
)

@@ -65,3 +64,3 @@ return

this._req.log.error(payload)
this._req.log.error({ res: this.res, error: payload }, payload.message)
this.res.setHeader('Content-Type', 'application/json')

@@ -68,0 +67,0 @@ setImmediate(

'use strict'
const fastJsonStringify = require('fast-json-stringify')
const fastSafeStringify = require('fast-safe-stringify')
const Ajv = require('ajv')

@@ -76,3 +75,3 @@ const ajv = new Ajv({ coerceTypes: true })

if (!responseSchemaDef) {
return fastSafeStringify(data)
return JSON.stringify(data)
}

@@ -86,6 +85,10 @@ if (responseSchemaDef[statusCode]) {

}
return fastSafeStringify(data)
return JSON.stringify(data)
}
function isValidLogger (logger) {
if (!logger) {
return false
}
var result = true

@@ -92,0 +95,0 @@ const methods = ['info', 'error', 'debug', 'fatal', 'warn', 'trace', 'child']

{
"name": "fastify",
"version": "0.26.2",
"version": "0.27.0",
"description": "Fast and low overhead web framework, for Node.js",

@@ -51,2 +51,3 @@ "main": "fastify.js",

"fast-json-body": "^1.1.0",
"fast-safe-stringify": "^1.2.0",
"fastify-plugin": "^0.1.0",

@@ -78,3 +79,2 @@ "frameguard": "^3.0.0",

"fast-json-stringify": "^0.12.2",
"fast-safe-stringify": "^1.2.0",
"fastify-cli": "^0.6.1",

@@ -84,4 +84,4 @@ "fastseries": "^1.7.2",

"flatstr": "^1.0.5",
"middie": "^1.0.0",
"pino-http": "^2.6.1",
"middie": "^2.0.0",
"pino": "^4.7.1",
"pump": "^1.0.2",

@@ -88,0 +88,0 @@ "xtend": "^4.0.1"

@@ -114,2 +114,3 @@ <div align="center">

- [`fastify-accepts-serializer`](https://github.com/fastify/fastify-accepts-serializer) to serialize to output according to `Accept` header
- [`fastify-sse`](https://github.com/lolo32/fastify-sse) to provide Server-Sent Events with `reply.sse( … )` to Fastify
- *More coming soon*

@@ -116,0 +117,0 @@

@@ -45,2 +45,7 @@ 'use strict'

fastify.addHook('onResponse', function (res, next) {
t.ok('onResponse called')
next()
})
fastify.get('/', function (req, reply) {

@@ -102,3 +107,3 @@ t.is(req.req.raw, 'the request is coming')

test('onRequest hook should not support encapsulation / 1', t => {
test('onRequest hook should support encapsulation / 1', t => {
t.plan(3)

@@ -115,7 +120,7 @@ const fastify = Fastify()

t.error(err)
t.is(fastify._hooks.onRequest.length, 1)
t.is(fastify._hooks.onRequest.length, 0)
})
})
test('onRequest hook should not support encapsulation / 2', t => {
test('onRequest hook should support encapsulation / 2', t => {
t.plan(3)

@@ -134,7 +139,7 @@ const fastify = Fastify()

t.error(err)
t.is(fastify._hooks.onRequest.length, 2)
t.is(fastify._hooks.onRequest.length, 1)
})
})
test('onRequest hook should not support encapsulation / 3', t => {
test('onRequest hook should support encapsulation / 3', t => {
t.plan(13)

@@ -150,3 +155,3 @@ const fastify = Fastify()

t.ok(req.req.first)
t.ok(req.req.second)
t.notOk(req.req.second)
reply.send({ hello: 'world' })

@@ -196,7 +201,7 @@ })

test('preRouting hook should not support encapsulation / 4', t => {
test('preHandler hook should support encapsulation / 5', t => {
t.plan(13)
const fastify = Fastify()
fastify.addHook('preRouting', (req, res, next) => {
fastify.addHook('preHandler', (req, res, next) => {
req.first = true

@@ -207,4 +212,4 @@ next()

fastify.get('/first', (req, reply) => {
t.ok(req.req.first)
t.ok(req.req.second)
t.ok(req.first)
t.notOk(req.second)
reply.send({ hello: 'world' })

@@ -214,3 +219,3 @@ })

fastify.register((instance, opts, next) => {
instance.addHook('preRouting', (req, res, next) => {
instance.addHook('preHandler', (req, res, next) => {
req.second = true

@@ -221,4 +226,4 @@ next()

instance.get('/second', (req, reply) => {
t.ok(req.req.first)
t.ok(req.req.second)
t.ok(req.first)
t.ok(req.second)
reply.send({ hello: 'world' })

@@ -256,14 +261,46 @@ })

test('preHandler hook should support encapsulation / 5', t => {
t.plan(13)
test('onResponse hook should support encapsulation / 1', t => {
t.plan(3)
const fastify = Fastify()
fastify.addHook('preHandler', (req, res, next) => {
req.first = true
fastify.register((instance, opts, next) => {
instance.addHook('onResponse', () => {})
t.is(instance._hooks.onResponse.length, 1)
next()
})
fastify.ready(err => {
t.error(err)
t.is(fastify._hooks.onResponse.length, 0)
})
})
test('onResponse hook should support encapsulation / 2', t => {
t.plan(3)
const fastify = Fastify()
fastify.addHook('onResponse', () => {})
fastify.register((instance, opts, next) => {
instance.addHook('onResponse', () => {})
t.is(instance._hooks.onResponse.length, 2)
next()
})
fastify.ready(err => {
t.error(err)
t.is(fastify._hooks.onResponse.length, 1)
})
})
test('onResponse hook should support encapsulation / 3', t => {
t.plan(12)
const fastify = Fastify()
fastify.addHook('onResponse', (res, next) => {
t.ok('onResponse called')
next()
})
fastify.get('/first', (req, reply) => {
t.ok(req.first)
t.notOk(req.second)
reply.send({ hello: 'world' })

@@ -273,4 +310,4 @@ })

fastify.register((instance, opts, next) => {
instance.addHook('preHandler', (req, res, next) => {
req.second = true
instance.addHook('onResponse', (res, next) => {
t.ok('onResponse called')
next()

@@ -280,4 +317,2 @@ })

instance.get('/second', (req, reply) => {
t.ok(req.first)
t.ok(req.second)
reply.send({ hello: 'world' })

@@ -284,0 +319,0 @@ })

@@ -14,4 +14,4 @@ 'use strict'

t.ok(Array.isArray(hooks.onRequest))
t.ok(Array.isArray(hooks.preRouting))
t.ok(Array.isArray(hooks.preHandler))
t.ok(Array.isArray(hooks.onResponse))
})

@@ -26,9 +26,9 @@

hooks.add('preRouting', noop)
t.is(hooks.preRouting.length, 1)
t.is(typeof hooks.preRouting[0], 'function')
hooks.add('preHandler', noop)
t.is(hooks.preHandler.length, 1)
t.is(typeof hooks.preHandler[0], 'function')
hooks.add('onResponse', noop)
t.is(hooks.onResponse.length, 1)
t.is(typeof hooks.onResponse[0], 'function')
})

@@ -35,0 +35,0 @@

@@ -30,10 +30,12 @@ 'use strict'

test('reply.header, reply.code and reply-serializer should return an instance of Reply', t => {
t.plan(3)
test('reply.send throw with circular JSON', t => {
t.plan(1)
const request = {}
const response = { setHeader: () => {} }
const reply = new Reply(request, response, null)
t.type(reply.code(1), Reply)
t.type(reply.serializer(() => {}), Reply)
t.type(reply.header('hello', 'world'), Reply)
t.throws(() => {
var obj = {}
obj.obj = obj
reply.send(JSON.stringify(obj))
})
})

@@ -40,0 +42,0 @@

@@ -37,1 +37,23 @@ 'use strict'

})
test('register after listen using Promise.resolve()', t => {
t.plan(2)
const f = Fastify()
const handler = (req, res) => res.send({})
Promise.resolve()
.then(() => {
f.get('/', handler)
f.register((f2, options, done) => {
f2.get('/plugin', handler)
done()
})
})
.then(() => {
f.listen(0, '127.0.0.1', (err) => {
t.error(err)
t.pass()
f.close()
})
})
})

@@ -8,24 +8,23 @@ 'use strict'

const Fastify = require('..')
var fastify = null
var stream = split(JSON.parse)
try {
fastify = Fastify({
logger: {
stream: stream,
level: 'info'
}
test('test log stream', t => {
t.plan(7)
var fastify = null
var stream = split(JSON.parse)
try {
fastify = Fastify({
logger: {
stream: stream,
level: 'info'
}
})
} catch (e) {
t.fail()
}
fastify.get('/', function (req, reply) {
t.ok(req.log)
reply.send({ hello: 'world' })
})
t.pass()
} catch (e) {
t.fail()
}
fastify.get('/', function (req, reply) {
t.ok(req.log)
reply.send({ hello: 'world' })
})
test('test log stream', t => {
t.plan(6)
fastify.listen(0, err => {

@@ -42,3 +41,2 @@ t.error(err)

t.equal(line.res.statusCode, 200, 'statusCode is 200')
t.end()
})

@@ -48,20 +46,47 @@ })

test('can use external logger instance', t => {
test('test error log stream', t => {
t.plan(7)
var fastify = null
var stream = split(JSON.parse)
try {
fastify = Fastify({
logger: {
stream: stream,
level: 'info'
}
})
} catch (e) {
t.fail()
}
const lines = []
fastify.get('/error', function (req, reply) {
t.ok(req.log)
reply.send(new Error('kaboom'))
})
fastify.listen(0, err => {
t.error(err)
fastify.server.unref()
http.get('http://localhost:' + fastify.server.address().port + '/error')
stream.once('data', line => {
t.ok(line.req, 'req is defined')
t.ok(line.res, 'res is defined')
t.equal(line.msg, 'kaboom', 'message is set')
t.equal(line.req.method, 'GET', 'method is get')
t.equal(line.res.statusCode, 500, 'statusCode is 500')
})
})
})
test('can use external logger instance', t => {
const lines = ['log success', 'request completed']
t.plan(lines.length + 2)
const splitStream = split(JSON.parse)
splitStream.on('data', (line) => {
lines.push(line)
t.is(line.msg, lines.shift())
})
splitStream.on('end', () => {
t.is(lines.length, 4)
t.is(lines[0].msg, 'log success')
t.is(lines[1].msg, 'log success')
t.is(lines[2].msg, 'log success')
t.is(lines[3].msg, 'request completed')
})
const logger = require('pino')(splitStream)
logger.info('log success')

@@ -74,8 +99,2 @@ const localFastify = Fastify({logger: logger})

reply.send({ hello: 'world' })
setImmediate(() => {
localFastify.server.close(() => {
splitStream.end()
localFastify.server.unref()
})
})
})

@@ -85,4 +104,8 @@

t.error(err)
logger.info('log success')
http.get('http://localhost:' + localFastify.server.address().port + '/foo')
http.get('http://localhost:' + localFastify.server.address().port + '/foo', (res) => {
res.resume()
res.on('end', () => {
localFastify.server.close()
})
})
})

@@ -93,4 +116,17 @@ })

t.plan(2)
var fastify = null
var stream = split(JSON.parse)
try {
fastify = Fastify({
logger: {
stream: stream,
level: 'info'
}
})
} catch (e) {
t.fail()
}
t.ok(fastify.logger)
t.is(typeof fastify.logger, 'function')
t.is(typeof fastify.logger, 'object')
})

@@ -122,1 +122,362 @@ 'use strict'

})
test('middlewares should support encapsulation / 1', t => {
t.plan(9)
const instance = fastify()
instance.register((i, opts, done) => {
t.ok(i._middlewares.length === 0)
i.use(function (req, res, next) {
t.fail('this should not be called')
next()
})
t.ok(i._middlewares.length > 0)
done()
})
instance.get('/', function (request, reply) {
t.ok(instance._middlewares.length === 0)
reply.send({ hello: 'world' })
})
instance.listen(0, err => {
t.error(err)
t.ok(instance._middlewares.length === 0)
t.tearDown(instance.server.close.bind(instance.server))
request({
method: 'GET',
uri: 'http://localhost:' + instance.server.address().port
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(response.headers['content-length'], '' + body.length)
t.deepEqual(JSON.parse(body), { hello: 'world' })
})
})
})
test('middlewares should support encapsulation / 2', t => {
t.plan(13)
const instance = fastify()
instance.use(function (req, res, next) {
req.global = true
next()
})
instance.register((i, opts, done) => {
i.use(function (req, res, next) {
req.local = true
next()
})
i.get('/local', function (request, reply) {
t.ok(request.req.global)
t.ok(request.req.local)
reply.send({ hello: 'world' })
})
done()
})
instance.get('/global', function (request, reply) {
t.ok(request.req.global)
t.notOk(request.req.local)
reply.send({ hello: 'world' })
})
instance.listen(0, err => {
t.error(err)
t.tearDown(instance.server.close.bind(instance.server))
request({
method: 'GET',
uri: 'http://localhost:' + instance.server.address().port + '/global'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(response.headers['content-length'], '' + body.length)
t.deepEqual(JSON.parse(body), { hello: 'world' })
request({
method: 'GET',
uri: 'http://localhost:' + instance.server.address().port + '/local'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(response.headers['content-length'], '' + body.length)
t.deepEqual(JSON.parse(body), { hello: 'world' })
})
})
})
})
test('middlewares should support encapsulation / 3', t => {
t.plan(15)
const instance = fastify()
instance.use(function (req, res, next) {
req.global = true
next()
})
instance.register((i, opts, done) => {
i.use(function (req, res, next) {
req.firstLocal = true
next()
})
i.use(function (req, res, next) {
req.secondLocal = true
next()
})
i.get('/local', function (request, reply) {
t.ok(request.req.global)
t.ok(request.req.firstLocal)
t.ok(request.req.secondLocal)
reply.send({ hello: 'world' })
})
done()
})
instance.get('/global', function (request, reply) {
t.ok(request.req.global)
t.notOk(request.req.firstLocal)
t.notOk(request.req.secondLocal)
reply.send({ hello: 'world' })
})
instance.listen(0, err => {
t.error(err)
t.tearDown(instance.server.close.bind(instance.server))
request({
method: 'GET',
uri: 'http://localhost:' + instance.server.address().port + '/global'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(response.headers['content-length'], '' + body.length)
t.deepEqual(JSON.parse(body), { hello: 'world' })
request({
method: 'GET',
uri: 'http://localhost:' + instance.server.address().port + '/local'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(response.headers['content-length'], '' + body.length)
t.deepEqual(JSON.parse(body), { hello: 'world' })
})
})
})
})
test('middlewares should support encapsulation / 4', t => {
t.plan(25)
const instance = fastify()
instance.use(function (req, res, next) {
req.global = true
next()
})
instance.register((i, opts, done) => {
i.use(function (req, res, next) {
req.firstLocal = true
next()
})
i.register((f, opts, d) => {
f.use(function (req, res, next) {
req.secondLocal = true
next()
})
f.get('/secondLocal', function (request, reply) {
t.ok(request.req.global)
t.ok(request.req.firstLocal)
t.ok(request.req.secondLocal)
t.ok(request.req.thirdLocal)
reply.send({ hello: 'world' })
})
f.use(function (req, res, next) {
req.thirdLocal = true
next()
})
d()
}, done)
i.get('/firstLocal', function (request, reply) {
t.ok(request.req.global)
t.ok(request.req.firstLocal)
t.notOk(request.req.secondLocal)
t.notOk(request.req.thirdLocal)
reply.send({ hello: 'world' })
})
})
instance.get('/global', function (request, reply) {
t.ok(request.req.global)
t.notOk(request.req.firstLocal)
t.notOk(request.req.secondLocal)
t.notOk(request.req.thirdLocal)
reply.send({ hello: 'world' })
})
instance.listen(0, err => {
t.error(err)
t.tearDown(instance.server.close.bind(instance.server))
request({
method: 'GET',
uri: 'http://localhost:' + instance.server.address().port + '/global'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(response.headers['content-length'], '' + body.length)
t.deepEqual(JSON.parse(body), { hello: 'world' })
request({
method: 'GET',
uri: 'http://localhost:' + instance.server.address().port + '/firstLocal'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(response.headers['content-length'], '' + body.length)
t.deepEqual(JSON.parse(body), { hello: 'world' })
request({
method: 'GET',
uri: 'http://localhost:' + instance.server.address().port + '/secondLocal'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(response.headers['content-length'], '' + body.length)
t.deepEqual(JSON.parse(body), { hello: 'world' })
})
})
})
})
})
test('middlewares should support encapsulation / 5', t => {
t.plan(9)
const instance = fastify()
instance.use(function (req, res, next) {
req.global = true
next()
})
instance.register((i, opts, done) => {
i.use(function (req, res, next) {
next(new Error('kaboom!'))
})
i.get('/local', function (request, reply) {
t.fail('this should not be called')
})
done()
})
instance.get('/global', function (request, reply) {
t.ok(request.req.global)
reply.send({ hello: 'world' })
})
instance.listen(0, err => {
t.error(err)
t.tearDown(instance.server.close.bind(instance.server))
request({
method: 'GET',
uri: 'http://localhost:' + instance.server.address().port + '/global'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(response.headers['content-length'], '' + body.length)
t.deepEqual(JSON.parse(body), { hello: 'world' })
request({
method: 'GET',
uri: 'http://localhost:' + instance.server.address().port + '/local'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 500)
t.deepEqual(JSON.parse(body), {
error: 'Internal Server Error',
message: 'kaboom!',
statusCode: 500
})
})
})
})
})
test('middlewares should support encapsulation with prefix', t => {
t.plan(9)
const instance = fastify()
instance.use(function (req, res, next) {
req.global = true
next()
})
instance.register((i, opts, done) => {
i.use(function (req, res, next) {
next(new Error('kaboom!'))
})
i.get('/', function (request, reply) {
t.fail('this should not be called')
})
done()
}, { prefix: '/local' })
instance.get('/global', function (request, reply) {
t.ok(request.req.global)
reply.send({ hello: 'world' })
})
instance.listen(0, err => {
t.error(err)
t.tearDown(instance.server.close.bind(instance.server))
request({
method: 'GET',
uri: 'http://localhost:' + instance.server.address().port + '/global'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(response.headers['content-length'], '' + body.length)
t.deepEqual(JSON.parse(body), { hello: 'world' })
request({
method: 'GET',
uri: 'http://localhost:' + instance.server.address().port + '/local'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 500)
t.deepEqual(JSON.parse(body), {
error: 'Internal Server Error',
message: 'kaboom!',
statusCode: 500
})
})
})
})
})

@@ -73,3 +73,3 @@ 'use strict'

test('preHandler hook error handling with code inside done', t => {
test('onRequest hook error handling with external done', t => {
t.plan(2)

@@ -79,4 +79,5 @@ const fastify = Fastify()

fastify.addHook('preHandler', (req, reply, done) => {
done(err, 400)
fastify.addHook('onRequest', (req, res, done) => {
res.statusCode = 400
done(err)
})

@@ -102,56 +103,2 @@

test('preRouting hook error handling with code inside done', t => {
t.plan(2)
const fastify = Fastify()
const err = new Error('winter is coming')
fastify.addHook('preRouting', (req, reply, done) => {
done(err, 400)
})
fastify.get('/', () => {})
fastify.inject({
method: 'GET',
url: '/'
}, res => {
t.strictEqual(res.statusCode, 400)
t.deepEqual(
{
error: statusCodes['400'],
message: err.message,
statusCode: 400
},
JSON.parse(res.payload)
)
})
})
test('onRequest hook error handling with code inside done', t => {
t.plan(2)
const fastify = Fastify()
const err = new Error('winter is coming')
fastify.addHook('onRequest', (req, reply, done) => {
done(err, 400)
})
fastify.get('/', () => {})
fastify.inject({
method: 'GET',
url: '/'
}, res => {
t.strictEqual(res.statusCode, 400)
t.deepEqual(
{
error: statusCodes['400'],
message: err.message,
statusCode: 400
},
JSON.parse(res.payload)
)
})
})
test('support for boom', t => {

@@ -158,0 +105,0 @@ t.plan(3)

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc