Comparing version 0.38.0 to 0.39.0
@@ -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) => { |
@@ -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 }]) | ||
}) | ||
}) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
433864
11222
29
Updated@types/node@^8.5.8
Updatedajv@^6.0.0