Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fastify

Package Overview
Dependencies
Maintainers
2
Versions
289
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fastify - npm Package Compare versions

Comparing version 0.38.0 to 0.39.0

5

docs/Getting-Started.md

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

fastify.register(require('./our-db-connector'), {
url: 'mongodb://mongo/db'
url: 'mongodb://localhost:27017/'
})

@@ -122,3 +122,4 @@ fastify.register(require('./our-first-route'))

async function routes (fastify, options) {
const collection = fastify.mongo.collection('test')
const database = fastify.mongo.db('db')
const collection = database.collection('test')

@@ -125,0 +126,0 @@ fastify.get('/', async (request, reply) => {

4

docs/Lifecycle.md

@@ -9,5 +9,5 @@ <h1 align="center">Fastify</h1>

└─▶ Instance Logger
└─▶ Routing
└─▶ Routing
└─▶ Instance Logger

@@ -14,0 +14,0 @@ 404 ◀─┴─▶ onRequest Hook

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

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

@@ -164,0 +164,0 @@

@@ -185,1 +185,25 @@ <h1 align="center">Fastify</h1>

Be aware that if you use [`fastify-plugin`](https://github.com/fastify/fastify-plugin) this option won't work.
<a name="custom-log-level"></a>
### Custom Log Level
It could happen that you need different log levels in your routes, with Fastify achieve this is very straightforward.<br/>
You just need to pass the option `logLevel` to the plugin option or the route option with the [value](https://github.com/pinojs/pino/blob/master/docs/API.md#discussion-3) that you need.
Be aware that if you set the `logLevel` at plugin level, also the [`setNotFoundHandler`](https://github.com/fastify/fastify/blob/master/docs/Server-Methods.md#setnotfoundhandler) and [`setErrorHandler`](https://github.com/fastify/fastify/blob/master/docs/Server-Methods.md#seterrorhandler) will be affected.
```js
// server.js
const fastify = require('fastify')({ logger: true })
fastify.register(require('./routes/user'), { logLevel: 'warn' })
fastify.register(require('./routes/events'), { logLevel: 'debug' })
fastify.listen(3000)
```
Or you can directly pass it to a route:
```js
fastify.get('/', { logLevel: 'warn' }, (req, reply) => {
reply.send({ hello: 'world' })
})
```
*Remember that the custom log level is applied only to the routes, and not to the global Fastify Logger, accessible with `fastify.log`*

@@ -80,12 +80,13 @@ 'use strict'

var server
const httpHandler = router.lookup.bind(router)
if (options.https) {
if (options.http2) {
server = http2().createSecureServer(options.https, fastify)
server = http2().createSecureServer(options.https, httpHandler)
} else {
server = https.createServer(options.https, fastify)
server = https.createServer(options.https, httpHandler)
}
} else if (options.http2) {
server = http2().createServer(fastify)
server = http2().createServer(httpHandler)
} else {
server = http.createServer(fastify)
server = http.createServer(httpHandler)
}

@@ -121,2 +122,3 @@

fastify._routePrefix = ''
fastify._logLevel = ''

@@ -172,5 +174,6 @@ // expose logger instance

function fastify (req, res) {
function fastify (req, res, params, context) {
res._context = context
req.id = genReqId(req)
req.log = res.log = log.child({ reqId: req.id })
req.log = res.log = log.child({ reqId: req.id, level: context.logLevel })
req.originalUrl = req.url

@@ -181,7 +184,14 @@

res._startTime = now()
res._context = null
res.on('finish', onResFinished)
res.on('error', onResFinished)
router.lookup(req, res)
if (context.onRequest !== null) {
context.onRequest(
hookIterator,
new State(req, res, params, context),
middlewareCallback
)
} else {
middlewareCallback(null, new State(req, res, params, context))
}
}

@@ -259,15 +269,2 @@

function startHooks (req, res, params, context) {
res._context = context
if (context.onRequest !== null) {
context.onRequest(
hookIterator,
new State(req, res, params, context),
middlewareCallback
)
} else {
middlewareCallback(null, new State(req, res, params, context))
}
}
function State (req, res, params, context) {

@@ -320,2 +317,3 @@ this.req = req

instance._routePrefix = buildRoutePrefix(instance._routePrefix, opts.prefix)
instance._logLevel = opts.logLevel || instance._logLevel
instance._middlewares = []

@@ -393,3 +391,4 @@ instance._middie = Middie(onRunMiddlewares)

schemaCompiler: options.schemaCompiler,
jsonBodyLimit: options.jsonBodyLimit
jsonBodyLimit: options.jsonBodyLimit,
logLevel: options.logLevel
})

@@ -439,2 +438,3 @@ }

jsonBodyLimit,
opts.logLevel || _fastify._logLevel,
_fastify

@@ -472,3 +472,3 @@ )

}
router.on(opts.method, url, startHooks, context)
router.on(opts.method, url, fastify, context)
} else {

@@ -484,3 +484,3 @@ const node = {}

map.set(url, node)
router.on(opts.method, url, startHooks, context)
router.on(opts.method, url, fastify, context)
}

@@ -494,3 +494,3 @@ done(notHandledErr)

function Context (schema, handler, Reply, Request, contentTypeParser, config, errorHandler, middie, jsonBodyLimit, fastify) {
function Context (schema, handler, Reply, Request, contentTypeParser, config, errorHandler, middie, jsonBodyLimit, logLevel, fastify) {
this.schema = schema

@@ -512,2 +512,3 @@ this.handler = handler

this._fastify = fastify
this.logLevel = logLevel
}

@@ -549,3 +550,3 @@

if (started) {
return lightMyRequest(this, opts, cb)
return lightMyRequest(httpHandler, opts, cb)
}

@@ -556,3 +557,3 @@

if (err) throw err
return lightMyRequest(this, opts, cb)
return lightMyRequest(httpHandler, opts, cb)
})

@@ -565,3 +566,3 @@ } else {

})
}).then(() => lightMyRequest(this, opts))
}).then(() => lightMyRequest(httpHandler, opts))
}

@@ -621,2 +622,12 @@ }

// we can
req.id = genReqId(req)
req.log = res.log = log.child({ reqId: req.id })
req.originalUrl = req.url
req.log.info({ req }, 'incoming request')
res._startTime = now()
res.on('finish', onResFinished)
res.on('error', onResFinished)
req.log.warn('the default handler for 404 did not catch this, this is likely a fastify bug, please report it')

@@ -655,2 +666,3 @@ req.log.warn(fourOhFour.prettyPrint())

this._jsonBodyLimit,
this._logLevel,
null

@@ -673,4 +685,4 @@ )

fourOhFour.all(prefix + '/*', startHooks, context)
fourOhFour.all(prefix || '/', startHooks, context)
fourOhFour.all(prefix + '/*', fastify, context)
fourOhFour.all(prefix || '/', fastify, context)
} else {

@@ -677,0 +689,0 @@ this._404Context.handler = handler

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

}).catch((err) => {
reply.sent = false
reply._isError = true

@@ -163,0 +164,0 @@ reply.send(err)

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

var contentType = reply.res.getHeader('Content-Type')
if (payload !== null && payload._readableState) {
if (payload !== null && typeof payload.pipe === 'function') {
if (!contentType) {

@@ -172,9 +172,7 @@ reply.res.setHeader('Content-Type', 'application/octet-stream')

return function _pumpCallback (err) {
const headersSent = reply.res.headersSent
if (err) {
if (!headersSent) {
handleError(reply, err)
} else {
reply.res.log.info('response terminated with an error with headers already sent')
}
if (!err) return
if (reply.res.headersSent) {
reply.request.log.error(err, 'response terminated with an error with headers already sent')
} else {
handleError(reply, err)
}

@@ -226,2 +224,3 @@ }

}
reply.res.setHeader('Content-Type', 'application/json')

@@ -237,3 +236,2 @@ if (cb) {

reply.res.setHeader('Content-Length', '' + Buffer.byteLength(payload))
reply.res.setHeader('Content-Type', 'application/json')
reply.sent = true

@@ -240,0 +238,0 @@ reply.res.end(payload)

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

@@ -74,3 +74,3 @@ "main": "fastify.js",

"fast-json-body": "^1.1.0",
"fast-safe-stringify": "^1.2.1",
"fast-safe-stringify": "^1.2.2",
"fastify-plugin": "^0.2.1",

@@ -85,2 +85,3 @@ "frameguard": "^3.0.0",

"joi": "~11.3.4",
"jsonstream": "^1.0.3",
"pre-commit": "^1.2.2",

@@ -99,6 +100,6 @@ "semver": "^5.4.1",

"dependencies": {
"@types/node": "^8.5.2",
"@types/node": "^8.5.8",
"@types/pino": "^4.7.0",
"abstract-logging": "^1.0.0",
"ajv": "^5.5.2",
"ajv": "^6.0.0",
"avvio": "^4.0.1",

@@ -105,0 +106,0 @@ "fast-iterator": "^0.2.1",

@@ -203,1 +203,25 @@ /* eslint-disable no-useless-return */

})
test('request should respond with an error if an unserialized payload is sent inside an an async handler', t => {
t.plan(3)
const fastify = require('../..')()
fastify.get('/', (request, reply) => {
reply.type('text/html')
return Promise.resolve(request.headers)
})
fastify.inject({
method: 'GET',
url: '/'
}, (err, res) => {
t.error(err)
t.strictEqual(res.statusCode, 500)
t.deepEqual(JSON.parse(res.payload), {
error: 'Internal Server Error',
message: 'Attempted to send payload of invalid type \'object\' without serialization. Expected a string or Buffer.',
statusCode: 500
})
})
})

@@ -384,2 +384,36 @@ 'use strict'

test('error object with a content type that is not application/json should work', t => {
t.plan(6)
const fastify = require('../..')()
fastify.get('/text', function (req, reply) {
reply.type('text/plain')
reply.send(new Error('some application error'))
})
fastify.get('/html', function (req, reply) {
reply.type('text/html')
reply.send(new Error('some application error'))
})
fastify.inject({
method: 'GET',
url: '/text'
}, (err, res) => {
t.error(err)
t.strictEqual(res.statusCode, 500)
t.strictEqual(JSON.parse(res.payload).message, 'some application error')
})
fastify.inject({
method: 'GET',
url: '/html'
}, (err, res) => {
t.error(err)
t.strictEqual(res.statusCode, 500)
t.strictEqual(JSON.parse(res.payload).message, 'some application error')
})
})
test('undefined payload should be sent as-is', t => {

@@ -386,0 +420,0 @@ t.plan(6)

@@ -286,1 +286,286 @@ 'use strict'

})
test('Should set a custom logLevel for a plugin', t => {
const lines = ['incoming request', 'Hello', 'request completed']
t.plan(7)
const splitStream = split(JSON.parse)
splitStream.on('data', (line) => {
t.is(line.msg, lines.shift())
})
const logger = pino({ level: 'error' }, splitStream)
const fastify = Fastify({
logger
})
fastify.get('/', (req, reply) => {
req.log.info('Hello') // we should not see this log
reply.send({ hello: 'world' })
})
fastify.register(function (instance, opts, next) {
instance.get('/plugin', (req, reply) => {
req.log.info('Hello') // we should see this log
reply.send({ hello: 'world' })
})
next()
}, { logLevel: 'info' })
fastify.inject({
method: 'GET',
url: '/'
}, (err, res) => {
t.error(err)
const payload = JSON.parse(res.payload)
t.deepEqual(payload, { hello: 'world' })
})
fastify.inject({
method: 'GET',
url: '/plugin'
}, (err, res) => {
t.error(err)
const payload = JSON.parse(res.payload)
t.deepEqual(payload, { hello: 'world' })
})
})
test('Should set a custom logLevel for every plugin', t => {
const lines = ['incoming request', 'request completed', 'info', 'debug']
t.plan(18)
const splitStream = split(JSON.parse)
splitStream.on('data', (line) => {
t.ok(line.level === 30 || line.level === 20)
t.ok(lines.indexOf(line.msg) > -1)
})
const logger = pino({ level: 'error' }, splitStream)
const fastify = Fastify({
logger
})
fastify.get('/', (req, reply) => {
req.log.warn('Hello') // we should not see this log
reply.send({ hello: 'world' })
})
fastify.register(function (instance, opts, next) {
instance.get('/info', (req, reply) => {
req.log.info('info') // we should see this log
req.log.debug('hidden log')
reply.send({ hello: 'world' })
})
next()
}, { logLevel: 'info' })
fastify.register(function (instance, opts, next) {
instance.get('/debug', (req, reply) => {
req.log.debug('debug') // we should see this log
req.log.trace('hidden log')
reply.send({ hello: 'world' })
})
next()
}, { logLevel: 'debug' })
fastify.inject({
method: 'GET',
url: '/'
}, (err, res) => {
t.error(err)
const payload = JSON.parse(res.payload)
t.deepEqual(payload, { hello: 'world' })
})
fastify.inject({
method: 'GET',
url: '/info'
}, (err, res) => {
t.error(err)
const payload = JSON.parse(res.payload)
t.deepEqual(payload, { hello: 'world' })
})
fastify.inject({
method: 'GET',
url: '/debug'
}, (err, res) => {
t.error(err)
const payload = JSON.parse(res.payload)
t.deepEqual(payload, { hello: 'world' })
})
})
test('Should increase the log level for a specific plugin', t => {
t.plan(4)
const splitStream = split(JSON.parse)
splitStream.on('data', (line) => {
t.is(line.msg, 'Hello')
t.ok(line.level === 50)
})
const logger = pino({ level: 'info' }, splitStream)
const fastify = Fastify({
logger
})
fastify.register(function (instance, opts, next) {
instance.get('/', (req, reply) => {
req.log.error('Hello') // we should see this log
reply.send({ hello: 'world' })
})
next()
}, { logLevel: 'error' })
fastify.inject({
method: 'GET',
url: '/'
}, (err, res) => {
t.error(err)
const payload = JSON.parse(res.payload)
t.deepEqual(payload, { hello: 'world' })
})
})
test('Should set the log level for the customized 404 handler', t => {
t.plan(4)
const splitStream = split(JSON.parse)
splitStream.on('data', (line) => {
t.is(line.msg, 'Hello')
t.ok(line.level === 50)
})
const logger = pino({ level: 'warn' }, splitStream)
const fastify = Fastify({
logger
})
fastify.register(function (instance, opts, next) {
instance.setNotFoundHandler(function (req, reply) {
req.log.error('Hello')
reply.code(404).send()
})
next()
}, { logLevel: 'error' })
fastify.inject({
method: 'GET',
url: '/'
}, (err, res) => {
t.error(err)
t.strictEqual(res.statusCode, 404)
})
})
test('Should set the log level for the customized 500 handler', t => {
t.plan(4)
const splitStream = split(JSON.parse)
splitStream.on('data', (line) => {
t.is(line.msg, 'Hello')
t.ok(line.level === 60)
})
const logger = pino({ level: 'warn' }, splitStream)
const fastify = Fastify({
logger
})
fastify.register(function (instance, opts, next) {
instance.get('/', (req, reply) => {
req.log.error('kaboom')
reply.send(new Error('kaboom'))
})
instance.setErrorHandler(function (e, reply) {
reply.res.log.fatal('Hello')
reply.code(500).send()
})
next()
}, { logLevel: 'fatal' })
fastify.inject({
method: 'GET',
url: '/'
}, (err, res) => {
t.error(err)
t.strictEqual(res.statusCode, 500)
})
})
test('Should set a custom log level for a specific route', t => {
const lines = ['incoming request', 'Hello', 'request completed']
t.plan(7)
const splitStream = split(JSON.parse)
splitStream.on('data', (line) => {
t.is(line.msg, lines.shift())
})
const logger = pino({ level: 'error' }, splitStream)
const fastify = Fastify({
logger
})
fastify.get('/log', { logLevel: 'info' }, (req, reply) => {
req.log.info('Hello')
reply.send({ hello: 'world' })
})
fastify.get('/no-log', (req, reply) => {
req.log.info('Hello')
reply.send({ hello: 'world' })
})
fastify.inject({
method: 'GET',
url: '/log'
}, (err, res) => {
t.error(err)
const payload = JSON.parse(res.payload)
t.deepEqual(payload, { hello: 'world' })
})
fastify.inject({
method: 'GET',
url: '/no-log'
}, (err, res) => {
t.error(err)
const payload = JSON.parse(res.payload)
t.deepEqual(payload, { hello: 'world' })
})
})
test('The default 404 handler logs the incoming request', t => {
t.plan(5)
const expectedMessages = ['incoming request', 'Not found', 'request completed']
const splitStream = split(JSON.parse)
splitStream.on('data', (line) => {
t.is(line.msg, expectedMessages.shift())
})
const logger = pino({ level: 'trace' }, splitStream)
const fastify = Fastify({
logger
})
fastify.inject({
method: 'GET',
url: '/not-found'
}, (err, res) => {
t.error(err)
t.strictEqual(res.statusCode, 404)
})
})

@@ -11,2 +11,3 @@ 'use strict'

const Fastify = require('..')
const JSONStream = require('jsonstream')

@@ -174,1 +175,25 @@ test('should respond with a stream', t => {

})
test('should respond with a stream1', t => {
t.plan(5)
const fastify = Fastify()
fastify.get('/', function (req, reply) {
const stream = JSONStream.stringify()
reply.code(200).type('application/json').send(stream)
stream.write({ hello: 'world' })
stream.end({ a: 42 })
})
fastify.listen(0, err => {
t.error(err)
fastify.server.unref()
sget(`http://localhost:${fastify.server.address().port}`, function (err, response, body) {
t.error(err)
t.strictEqual(response.headers['content-type'], 'application/json')
t.strictEqual(response.statusCode, 200)
t.deepEqual(JSON.parse(body), [{ hello: 'world' }, { a: 42 }])
})
})
})
SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc