Socket
Socket
Sign inDemoInstall

fastify

Package Overview
Dependencies
61
Maintainers
2
Versions
282
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.14.1 to 0.15.0

docs/ContentTypeParser.md

5

docs/Hooks.md

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

You can add more than one function to every hook and as all the others, the api is chainable.
<a name="on-close"></a>

@@ -38,1 +36,4 @@ **'onClose'**

```
<a name="scope"></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`.

62

fastify.js

@@ -17,5 +17,6 @@ 'use strict'

const buildNode = require('./lib/tier-node')
const hooksManager = require('./lib/hooks')
const isValidLogger = require('./lib/validation').isValidLogger
const decorator = require('./lib/decorate')
const ContentTypeParser = require('./lib/ContentTypeParser')
const Hooks = require('./lib/hooks')

@@ -43,7 +44,2 @@ function build (options) {

const hooks = hooksManager()
const onRequest = hooks.get.onRequest
const preRouting = hooks.get.preRouting
const onClose = hooks.get.onClose
const app = avvio(fastify, {})

@@ -73,5 +69,11 @@ // Override to allow the plugin incapsulation

// hooks
fastify.addHook = hooks.add
fastify.addHook = addHook
fastify._hooks = new Hooks()
fastify.close = close
// custom parsers
fastify.addContentTypeParser = addContentTypeParser
fastify.hasContentTypeParser = hasContentTypeParser
fastify._contentTypeParser = new ContentTypeParser()
// plugin

@@ -103,6 +105,7 @@ fastify.register = fastify.use

// onRequest hook
runHooks(
setImmediate(
runHooks,
new State(req, res),
hookIterator,
onRequest(),
fastify._hooks.onRequest,
middlewareCallback

@@ -120,6 +123,7 @@ )

// preRouting hook
runHooks(
setImmediate(
runHooks,
new State(req, res),
hookIterator,
preRouting(),
fastify._hooks.preRouting,
routeCallback

@@ -154,3 +158,3 @@ )

router(stripUrl(this.req.url), this.req, this.res)
router(stripUrl(this.req.url), this.req, this.res, this.req.method)
}

@@ -165,12 +169,14 @@

function override (server, fn) {
function override (instance, fn) {
if (fn[Symbol.for('skip-override')]) {
return server
return instance
}
server = Object.create(server)
server._Reply = buildReply(server._Reply)
server._Request = buildRequest(server._Request)
instance = Object.create(instance)
instance._Reply = buildReply(instance._Reply)
instance._Request = buildRequest(instance._Request)
instance._contentTypeParser = ContentTypeParser.buildContentTypeParser(instance._contentTypeParser)
instance._hooks = Hooks.buildHooks(instance._hooks)
return server
return instance
}

@@ -182,3 +188,3 @@

onCloseIterator,
onClose(),
fastify._hooks.onClose,
onCloseCallback(cb)

@@ -236,3 +242,3 @@ )

}
return route({ method, url, schema, handler, Reply: self._Reply, Request: self._Request })
return route({ method, url, schema, handler, Reply: self._Reply, Request: self._Request, contentTypeParser: self._contentTypeParser, hooks: self._hooks })
}

@@ -254,2 +260,4 @@

opts.Request = opts.Request || this._Request
opts.contentTypeParser = opts.contentTypeParser || this._contentTypeParser
opts.hooks = opts.hooks || this._hooks

@@ -263,3 +271,3 @@ if (map.has(opts.url)) {

} else {
const node = buildNode(opts.url, router, hooks.get)
const node = buildNode(opts.url, router)
node[opts.method] = opts

@@ -305,2 +313,14 @@ map.set(opts.url, node)

function addHook (name, fn) {
return this._hooks.add(name, fn)
}
function addContentTypeParser (contentType, fn) {
return this._contentTypeParser.add(contentType, fn)
}
function hasContentTypeParser (contentType, fn) {
return this._contentTypeParser.hasParser(contentType)
}
// TODO: find a better solution than

@@ -307,0 +327,0 @@ // copy paste the code of the constructor

@@ -10,47 +10,31 @@ 'use strict'

function hooksManager () {
const hooks = {
onRequest: [],
preRouting: [],
preHandler: [],
onClose: []
}
function Hooks () {
this.onRequest = []
this.preRouting = []
this.preHandler = []
this.onClose = []
}
function add (hook, fn) {
if (typeof hook !== 'string') throw new TypeError('The hook name must be a string')
if (typeof fn !== 'function') throw new TypeError('The hook callback must be a function')
if (supportedHooks.indexOf(hook) === -1) {
throw new Error(`${hook} hook not supported!`)
}
hooks[hook].push(fn)
return this
Hooks.prototype.add = function (hook, fn) {
if (typeof hook !== 'string') throw new TypeError('The hook name must be a string')
if (typeof fn !== 'function') throw new TypeError('The hook callback must be a function')
if (supportedHooks.indexOf(hook) === -1) {
throw new Error(`${hook} hook not supported!`)
}
function get () {
return hooks
}
this[hook].push(fn)
}
get.onRequest = function () {
return hooks.onRequest
}
get.preRouting = function () {
return hooks.preRouting
}
get.preHandler = function () {
return hooks.preHandler
}
get.onClose = function () {
return hooks.onClose
}
return {
add: add,
get: get
}
function buildHooks (h) {
function _Hooks () {}
_Hooks.prototype = new Hooks()
const H = new _Hooks()
H.onRequest = h.onRequest
H.preRouting = h.preRouting
H.preHandler = Object.create(h.preHandler)
H.onClose = h.onClose
return H
}
module.exports = hooksManager
module.exports = Hooks
module.exports.buildHooks = buildHooks

@@ -30,2 +30,11 @@ /* eslint-disable no-useless-return */

if (!payload) {
if (!this.res.statusCode) {
this.res.statusCode = 204
}
this.res.setHeader('Content-Length', '0')
setImmediate(wrapReplyEnd, this, '')
return
}
if (payload instanceof Error) {

@@ -41,11 +50,7 @@ if (!this.res.statusCode || this.res.statusCode < 500) {

if (payload && typeof payload.then === 'function') {
if (typeof payload.then === 'function') {
return payload.then(wrapReplySend(this)).catch(wrapReplySend(this))
}
if (!payload && !this.res.statusCode) {
this.res.statusCode = 204
}
if (payload && payload._readableState) {
if (payload._readableState) {
if (!this.res.getHeader('Content-Type')) {

@@ -52,0 +57,0 @@ this.res.setHeader('Content-Type', 'application/octet-stream')

@@ -10,19 +10,12 @@ /* eslint-disable no-useless-return */

function bodyParsed (hooks, handle, params, req, res) {
function parsed (err, body) {
if (err) {
res.statusCode = 422
setImmediate(wrapResEnd, res)
return
}
handler(hooks, handle, params, req, res, body, urlUtil.parse(req.url, true).query)
}
function build (url, router) {
const node = {}
router.on(url, routerHandler(node))
return parsed
return node
}
function routerHandler (node, hooks) {
return function _routeHanlder (params, req, res) {
const handle = node[req.method]
function routerHandler (node) {
return function _routerHandler (params, req, res, method) {
var handle = node[method]
if (!handle) {

@@ -35,11 +28,15 @@ res.statusCode = 404

// Body not required
if (req.method === 'GET' || req.method === 'DELETE' || req.method === 'HEAD') {
return handler(hooks, handle, params, req, res, null, urlUtil.parse(req.url, true).query)
if (method === 'GET' || method === 'DELETE' || method === 'HEAD') {
return handler(handle, params, req, res, null, urlUtil.parse(req.url, true).query)
}
// Optional body
if (req.method === 'OPTIONS') {
if (method === 'OPTIONS') {
if (req.headers['content-type']) {
// application/json content type
if (req.headers['content-type'].indexOf('application/json') > -1) {
return jsonParser(req, bodyParsed(hooks, handle, params, req, res))
return jsonParser(req, bodyParsed(handle, params, req, res))
// custom parser for a given content type
} else if (handle.contentTypeParser.fastHasHeader(req.headers['content-type'])) {
return handle.contentTypeParser.run(req.headers['content-type'], handler, handle, params, req, res, urlUtil.parse(req.url, true).query)
}

@@ -50,10 +47,15 @@ res.statusCode = 415

}
return handler(hooks, handle, params, req, res, null, urlUtil.parse(req.url, true).query)
return handler(handle, params, req, res, null, urlUtil.parse(req.url, true).query)
}
// Body required
if (req.method === 'POST' || req.method === 'PUT' || req.method === 'PATCH') {
if (method === 'POST' || method === 'PUT' || method === 'PATCH') {
// application/json content type
if (req.headers['content-type'] && req.headers['content-type'].indexOf('application/json') > -1) {
return jsonParser(req, bodyParsed(hooks, handle, params, req, res))
return jsonParser(req, bodyParsed(handle, params, req, res))
// custom parser fir a given content type
} else if (handle.contentTypeParser.fastHasHeader(req.headers['content-type'])) {
return handle.contentTypeParser.run(req.headers['content-type'], handler, handle, params, req, res, urlUtil.parse(req.url, true).query)
}
res.statusCode = 415

@@ -70,17 +72,17 @@ setImmediate(wrapResEnd, res)

function build (url, router, hooks) {
const node = {}
router.on(url, routerHandler(node, hooks))
function bodyParsed (handle, params, req, res) {
function parsed (err, body) {
if (err) {
res.statusCode = 422
setImmediate(wrapResEnd, res)
return
}
handler(handle, params, req, res, body, urlUtil.parse(req.url, true).query)
}
return node
return parsed
}
function handler (hooks, handle, params, req, res, body, query) {
if (!handle) {
res.statusCode = 404
setImmediate(wrapResEnd, res)
return
}
const valid = validateSchema(handle, params, body, query)
function handler (handle, params, req, res, body, query) {
var valid = validateSchema(handle, params, body, query)
if (valid !== true) {

@@ -92,10 +94,8 @@ res.statusCode = 400

const request = new handle.Request(params, req, body, query, req.log)
const reply = new handle.Reply(req, res, handle)
// preHandler hook
runHooks(
new State(request, reply, handle),
setImmediate(
runHooks,
new State(new handle.Request(params, req, body, query, req.log), new handle.Reply(req, res, handle), handle),
hookIterator,
hooks.preHandler(),
handle.hooks.preHandler,
preHandlerCallback

@@ -120,3 +120,3 @@ )

}
const result = this.handle.handler(this.request, this.reply)
var result = this.handle.handler(this.request, this.reply)
if (result && typeof result.then === 'function') {

@@ -123,0 +123,0 @@ this.reply.send(result)

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

const outputSchema = Symbol('output-schema')
const paramsSchema = Symbol('params-scehma')
const paramsSchema = Symbol('params-schema')

@@ -14,0 +14,0 @@ const schemas = require('./schemas.json')

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

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

"split2": "^2.1.1",
"standard": "^9.0.2",
"standard": "^10.0.1",
"take-five": "^1.3.3",

@@ -57,0 +57,0 @@ "tap": "^10.3.0",

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

* <a href="https://github.com/fastify/fastify/blob/master/docs/Request.md"><code><b>Request</b></code></a>
* <a href="https://github.com/fastify/fastify/blob/master/docs/ContentTypeParser.md"><code><b>Content Type Parser</b></code></a>
* <a href="https://github.com/fastify/fastify/blob/master/docs/Plugins.md"><code><b>Plugins</b></code></a>

@@ -51,0 +52,0 @@ * <a href="https://github.com/fastify/fastify/blob/master/docs/Testing.md"><code><b>Testing</b></code></a>

@@ -129,2 +129,14 @@ 'use strict'

test('empty response', t => {
t.plan(1)
try {
fastify.get('/empty', function (req, reply) {
reply.code(200).send()
})
t.pass()
} catch (e) {
t.fail()
}
})
fastify.listen(0, err => {

@@ -247,2 +259,16 @@ t.error(err)

})
test('shorthand - empty response', t => {
t.plan(4)
request({
method: 'GET',
uri: 'http://localhost:' + fastify.server.address().port + '/empty'
}, (err, response, body) => {
console.log(body)
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(response.headers['content-length'], '0')
t.deepEqual(body, '')
})
})
})

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

const request = require('request')
const Fastify = require('..')
const fastify = require('..')()

@@ -45,7 +46,2 @@

test('hooks - addHook returns an instance of fastify', t => {
t.plan(1)
t.type(fastify.addHook('preRouting', (req, res, next) => next()), fastify)
})
fastify.get('/', function (req, reply) {

@@ -106,1 +102,203 @@ t.is(req.req.raw, 'the request is coming')

})
test('onRequest hook should not support encapsulation / 1', t => {
t.plan(3)
const fastify = Fastify()
fastify.register((instance, opts, next) => {
instance.addHook('onRequest', () => {})
t.is(instance._hooks.onRequest.length, 1)
next()
})
fastify.ready(err => {
t.error(err)
t.is(fastify._hooks.onRequest.length, 1)
})
})
test('onRequest hook should not support encapsulation / 2', t => {
t.plan(3)
const fastify = Fastify()
fastify.addHook('onRequest', () => {})
fastify.register((instance, opts, next) => {
instance.addHook('onRequest', () => {})
t.is(instance._hooks.onRequest.length, 2)
next()
})
fastify.ready(err => {
t.error(err)
t.is(fastify._hooks.onRequest.length, 2)
})
})
test('onRequest hook should not support encapsulation / 3', t => {
t.plan(13)
const fastify = Fastify()
fastify.addHook('onRequest', (req, res, next) => {
req.first = true
next()
})
fastify.get('/first', (req, reply) => {
t.ok(req.req.first)
t.ok(req.req.second)
reply.send({ hello: 'world' })
})
fastify.register((instance, opts, next) => {
instance.addHook('onRequest', (req, res, next) => {
req.second = true
next()
})
instance.get('/second', (req, reply) => {
t.ok(req.req.first)
t.ok(req.req.second)
reply.send({ hello: 'world' })
})
next()
})
fastify.listen(0, err => {
t.error(err)
fastify.server.unref()
request({
method: 'GET',
uri: 'http://localhost:' + fastify.server.address().port + '/first'
}, (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:' + fastify.server.address().port + '/second'
}, (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('preRouting hook should not support encapsulation / 4', t => {
t.plan(13)
const fastify = Fastify()
fastify.addHook('preRouting', (req, res, next) => {
req.first = true
next()
})
fastify.get('/first', (req, reply) => {
t.ok(req.req.first)
t.ok(req.req.second)
reply.send({ hello: 'world' })
})
fastify.register((instance, opts, next) => {
instance.addHook('preRouting', (req, res, next) => {
req.second = true
next()
})
instance.get('/second', (req, reply) => {
t.ok(req.req.first)
t.ok(req.req.second)
reply.send({ hello: 'world' })
})
next()
})
fastify.listen(0, err => {
t.error(err)
fastify.server.unref()
request({
method: 'GET',
uri: 'http://localhost:' + fastify.server.address().port + '/first'
}, (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:' + fastify.server.address().port + '/second'
}, (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('preHandler hook should support encapsulation / 5', t => {
t.plan(13)
const fastify = Fastify()
fastify.addHook('preHandler', (req, res, next) => {
req.first = true
next()
})
fastify.get('/first', (req, reply) => {
t.ok(req.first)
t.notOk(req.second)
reply.send({ hello: 'world' })
})
fastify.register((instance, opts, next) => {
instance.addHook('preHandler', (req, res, next) => {
req.second = true
next()
})
instance.get('/second', (req, reply) => {
t.ok(req.first)
t.ok(req.second)
reply.send({ hello: 'world' })
})
next()
})
fastify.listen(0, err => {
t.error(err)
fastify.server.unref()
request({
method: 'GET',
uri: 'http://localhost:' + fastify.server.address().port + '/first'
}, (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:' + fastify.server.address().port + '/second'
}, (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' })
})
})
})

@@ -6,29 +6,33 @@ 'use strict'

const hooksManager = require('../../lib/hooks')
const hooks = hooksManager()
const otherHooks = hooksManager()
const Hooks = require('../../lib/hooks')
const noop = () => {}
test('hooks should store an object with the hooks and .get should return it', t => {
t.plan(4)
const h = hooks.get()
t.is(typeof h, 'object')
t.ok(Array.isArray(h.onRequest))
t.ok(Array.isArray(h.preRouting))
t.ok(Array.isArray(h.preHandler))
test('hooks should have 4 array with the registered hooks', t => {
t.plan(5)
const hooks = new Hooks()
t.is(typeof hooks, 'object')
t.ok(Array.isArray(hooks.onRequest))
t.ok(Array.isArray(hooks.preRouting))
t.ok(Array.isArray(hooks.preHandler))
t.ok(Array.isArray(hooks.onClose))
})
test('hooks.add should add an hook to the given hook', t => {
t.plan(6)
t.plan(8)
const hooks = new Hooks()
hooks.add('onRequest', noop)
t.is(hooks.get.onRequest().length, 1)
t.is(typeof hooks.get.onRequest()[0], 'function')
t.is(hooks.onRequest.length, 1)
t.is(typeof hooks.onRequest[0], 'function')
hooks.add('preRouting', noop)
t.is(hooks.get.preRouting().length, 1)
t.is(typeof hooks.get.preRouting()[0], 'function')
t.is(hooks.preRouting.length, 1)
t.is(typeof hooks.preRouting[0], 'function')
hooks.add('preHandler', noop)
t.is(hooks.get.preHandler().length, 1)
t.is(typeof hooks.get.preHandler()[0], 'function')
t.is(hooks.preHandler.length, 1)
t.is(typeof hooks.preHandler[0], 'function')
hooks.add('onClose', noop)
t.is(hooks.onClose.length, 1)
t.is(typeof hooks.onClose[0], 'function')
})

@@ -38,2 +42,3 @@

t.plan(1)
const hooks = new Hooks()
try {

@@ -47,10 +52,4 @@ hooks.add('onUnexistingHook', noop)

test('different instances does not affect each other', t => {
t.plan(1)
hooks.add('onRequest', noop)
t.is(otherHooks.get.onRequest.length, 0)
})
test('should throw on wrong parameters', t => {
const hooks = new Hooks()
t.plan(2)

@@ -57,0 +56,0 @@ try {

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

const buildSchema = require('../../lib/validation').build
const hooksManager = require('../../lib/hooks')
const hooks = hooksManager().get
const Hooks = require('../../lib/hooks')

@@ -28,16 +27,6 @@ test('Request object', t => {

t.plan(1)
const parsed = internals.bodyParsed(hooks, null, null, null, null)
const parsed = internals.bodyParsed(null, null, null, null)
t.is(typeof parsed, 'function')
})
test('handler function - missing handler', t => {
t.plan(2)
const res = {}
res.end = () => {
t.equal(res.statusCode, 404)
t.pass()
}
internals.handler(hooks, null, null, null, res, null, null)
})
test('handler function - invalid schema', t => {

@@ -61,6 +50,7 @@ t.plan(2)

Reply: Reply,
Request: Request
Request: Request,
hooks: new Hooks()
}
buildSchema(handle)
internals.handler(hooks, handle, null, null, res, { hello: 'world' }, null)
internals.handler(handle, null, null, res, { hello: 'world' }, null)
})

@@ -87,6 +77,7 @@

Reply: Reply,
Request: Request
Request: Request,
hooks: new Hooks()
}
buildSchema(handle)
internals.handler(hooks, handle, null, { log: null }, res, null, null)
internals.handler(handle, null, { log: null }, res, null, null)
})

@@ -102,3 +93,3 @@

t.plan(2)
const handle = internals.routerHandler({}, hooks)
const handle = internals.routerHandler({})
const res = {}

@@ -119,3 +110,3 @@ res.end = () => {

'SAD': {}
}, hooks)
})
const res = {}

@@ -140,3 +131,4 @@ res.end = () => {

Reply: Reply,
Request: Request
Request: Request,
hooks: new Hooks()
}

@@ -147,3 +139,3 @@ buildSchema(handleNode)

'GET': handleNode
}, hooks)
})
const res = {}

@@ -164,3 +156,3 @@ res.end = () => {

}
handle(null, req, res)
handle(null, req, res, 'GET')
})

@@ -176,3 +168,4 @@

Reply: Reply,
Request: Request
Request: Request,
hooks: new Hooks()
}

@@ -183,3 +176,3 @@ buildSchema(handleNode)

'GET': handleNode
}, hooks)
})
const res = {}

@@ -197,3 +190,3 @@ res.end = () => {

}
handle(null, req, res)
handle(null, req, res, 'GET')
})
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