Socket
Socket
Sign inDemoInstall

fastify

Package Overview
Dependencies
60
Maintainers
2
Versions
282
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.7.1 to 0.8.0

benchmarks/express-with-middlewares.js

18

fastify.js

@@ -9,2 +9,4 @@ 'use strict'

const pinoHttp = require('pino-http')
const Middie = require('middie')
const Reply = require('./lib/reply')

@@ -26,2 +28,4 @@ const supportedMethods = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT', 'OPTIONS']

const router = wayfarer('/404')
const middie = Middie(_runMiddlewares)
const run = middie.run
const map = new Map()

@@ -54,2 +58,5 @@ pluginLoader(fastify, {})

// middleware support
fastify.use = middie.use
return fastify

@@ -59,2 +66,12 @@

logger(req, res)
run(req, res)
}
function _runMiddlewares (err, req, res) {
if (err) {
const reply = new Reply(req, res, null)
reply.send(err)
return
}
router(stripUrl(req.url), req, res)

@@ -129,2 +146,3 @@ }

}
// chainable api

@@ -131,0 +149,0 @@ return fastify

106

lib/tier-node.js
'use strict'
const urlUtil = require('url')
const pump = require('pump')
const jsonParser = require('body/json')
const safeStringify = require('fast-safe-stringify')
const validation = require('./validation')
const validateSchema = validation.validate
const serialize = validation.serialize
const Reply = require('./reply')
const Request = require('./request')

@@ -20,2 +19,3 @@ function bodyParsed (handle, params, req, res) {

}
return parsed

@@ -66,2 +66,3 @@ }

}
return handle

@@ -93,4 +94,3 @@ }

const reply = new Reply(req, res, handle)
const handler = handle.handler
const result = handler(request, reply)
const result = handle.handler(request, reply)
if (result && typeof result.then === 'function') {

@@ -106,97 +106,3 @@ reply.send(result)

function Reply (req, res, handle) {
this.res = res
this.handle = handle
this.req = req
this.sent = false
}
/**
* Instead of using directly res.end(), we are using setImmediate(…)
* This because we have observed that with this technique we are faster at responding to the various requests,
* since the setImmediate forwards the res.end at the end of the poll phase of libuv in the event loop.
* So we can gather multiple requests and then handle all the replies in a different moment,
* causing a general improvement of performances, ~+10%.
*/
Reply.prototype.send = function (payload) {
if (this.sent) {
throw new Error('Reply already sent')
}
if (payload instanceof Error) {
if (!this.res.statusCode || this.res.statusCode < 500) {
this.res.statusCode = 500
}
setImmediate(wrapReplyEnd, this, safeStringify(payload))
return
}
if (payload && 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 (!this.res.getHeader('Content-Type')) {
this.res.setHeader('Content-Type', 'application/octet-stream')
}
return pump(payload, this.res, wrapPumpCallback(this))
}
if (!this.res.getHeader('Content-Type') || this.res.getHeader('Content-Type') === 'application/json') {
this.res.setHeader('Content-Type', 'application/json')
const str = serialize(this.handle, payload)
if (!this.res.getHeader('Content-Length')) {
this.res.setHeader('Content-Length', Buffer.byteLength(str))
}
setImmediate(wrapReplyEnd, this, str)
return
}
setImmediate(wrapReplyEnd, this, payload)
return
}
Reply.prototype.header = function (key, value) {
this.res.setHeader(key, value)
return this
}
Reply.prototype.code = function (code) {
this.res.statusCode = code
return this
}
function wrapPumpCallback (reply) {
return function pumpCallback (err) {
if (err) {
reply.req.log.error(err)
setImmediate(wrapReplyEnd, reply)
}
}
}
function wrapReplyEnd (reply, payload) {
reply.sent = true
reply.res.end(payload)
}
function wrapReplySend (reply, payload) {
return function send (payload) {
return reply.send(payload)
}
}
function Request (params, req, body, query) {
this.params = params
this.req = req
this.body = body
this.query = query
}
module.exports = build
module.exports[Symbol.for('internals')] = { bodyParsed, routerHandler, Request, handler, Reply }
module.exports[Symbol.for('internals')] = { bodyParsed, routerHandler, handler }
{
"name": "fastify",
"version": "0.7.1",
"version": "0.8.0",
"description": "Fast and low overhead web framework, for Node.js",

@@ -31,26 +31,35 @@ "main": "fastify.js",

"bluebird": "^3.4.7",
"coveralls": "^2.11.15",
"express": "^4.14.0",
"hapi": "^16.0.2",
"koa": "^1.2.4",
"pre-commit": "^1.1.3",
"cors": "^2.8.1",
"coveralls": "^2.11.16",
"dns-prefetch-control": "^0.1.0",
"express": "^4.14.1",
"frameguard": "^3.0.0",
"hapi": "^16.1.0",
"helmet": "^3.4.0",
"hide-powered-by": "^1.0.0",
"hsts": "^2.0.0",
"ienoopen": "^1.0.0",
"koa": "^1.2.5",
"pre-commit": "^1.2.2",
"request": "^2.79.0",
"snazzy": "^5.0.0",
"split2": "^2.1.0",
"snazzy": "^6.0.0",
"split2": "^2.1.1",
"standard": "^8.6.0",
"take-five": "^1.3.1",
"tap": "^9.0.1",
"then-sleep": "^1.0.1"
"take-five": "^1.3.3",
"tap": "^10.1.0",
"then-sleep": "^1.0.1",
"x-xss-protection": "^1.0.0"
},
"dependencies": {
"ajv": "^4.10.4",
"ajv": "^4.11.2",
"body": "^5.1.0",
"boot-in-the-arse": "^0.3.0",
"fast-json-stringify": "^0.10.3",
"fast-safe-stringify": "^1.1.3",
"fast-safe-stringify": "^1.1.6",
"middie": "^0.1.1",
"pathname-match": "^1.2.0",
"pino-http": "^2.2.0",
"pino-http": "^2.4.1",
"pump": "^1.0.2",
"wayfarer": "^6.3.0"
"wayfarer": "^6.4.0"
}
}

@@ -75,3 +75,3 @@ <p align="center">

* Koa: 9640 req/sec
* *Fastify: 19860 req/sec*
* *Fastify: 20256 req/sec*

@@ -96,2 +96,3 @@ All benchmarks where average taken over 5 seconds, on the second run of `autocannon -c 100 -d 5 -p 10 localhost:3000`.

* <a href="#register"><code>fastify.<b>register()</b></code></a>
* <a href="#use"><code>fastify.<b>use()</b></code></a>

@@ -135,3 +136,4 @@ <a name="constructor"></a>

Function called when all the plugins has been loaded.
Function called when all the plugins has been loaded.
Emitted by [boot-in-the-arse](https://github.com/mcollina/boot-in-the-arse).

@@ -142,3 +144,4 @@

Starts the server on the given port after all the plugins are loaded, internally waits for the `.ready()` event.
Starts the server on the given port after all the plugins are loaded, internally waits for the `.ready()` event.
The callback is the same as the Node core.

@@ -166,6 +169,8 @@

[fast-json-stringify][fast-json-stringify].
* `handler(request, reply)`: the function that will handle this request.
`request` is defined in [Request](#request).
`reply` is defined in [Reply](#reply).
* `handler(request, reply)`: the function that will handle this request.
`request` is defined in [Request](#request).
`reply` is defined in [Reply](#reply).
Example:

@@ -275,3 +280,3 @@ ```js

const fs = require('fs')
const stream = fs.createReadStream('some-file', 'utf8')
const stream = fs.createReadStream('some-file', 'utf8')
reply.send(stream)

@@ -325,6 +330,10 @@ })

### fastify.register(plugin, [options], [callback])
Used to register one or more plugins.
`plugin` can be a single function or an array of functions.
In case of the array of functions, the same options object and callback will be passed to them.
[boot-in-the-arse](https://github.com/mcollina/boot-in-the-arse) is used to load the plugins.
Used to register one or more plugins.
`plugin` can be a single function or an array of functions.
In case of the array of functions, the same options object and callback will be passed to them.
[boot-in-the-arse](https://github.com/mcollina/boot-in-the-arse) is used to load the plugins.
Example:

@@ -368,9 +377,44 @@ ```js

<a name="use"></a>
### fastify.use(middleware(req, res, next))
Use to add one or more middlewares, [express](http://npm.im/express)/[connect](https://www.npmjs.com/package/connect) style.
This does not support the full syntax `middleware(err, req, res, next)`,
because error handling is done inside Fastify.
Benchmarks with cors and helmet (used as single modules):
* Express: 9.6k req/sec
* *Fastify: 14.4k req/sec*
Example:
```js
const fastify = require('fastify')()
const cors = require('cors')
const helmet = require('helmet')
fastify
.use(cors())
.use(helmet())
.get('/', function (req, reply) {
reply.header('Content-Type', 'application/json').code(200)
reply.send({ hello: 'world' })
})
fastify.listen(3000, err => {
if (err) throw err
console.log(`server listening on ${fastify.server.address().port}`)
})
```
<a name="logging"></a>
## Logging
Since Fastify is really focused on performances, we choose the best logger to achieve the goal. **[Pino](https://github.com/pinojs/pino)**!
Since Fastify is really focused on performances, we choose the best logger to achieve the goal. **[Pino](https://github.com/pinojs/pino)**!
By default Fastify uses [pino-http](https://github.com/pinojs/pino-http) as logger, with the log level setted to `'fatal'`.
If you want to pass some options to the logger, just pass the logger option to fastify.
You can find all the options [here](https://github.com/pinojs/pino#pinoopts-stream). If you want to pass a custom stream to the Pino instance, just add the stream field to the logger object.
You can find all the options in the [Pino documentation](https://github.com/pinojs/pino/blob/master/docs/API.md#pinooptions-stream). If you want to pass a custom stream to the Pino instance, just add the stream field to the logger object.
```js

@@ -413,2 +457,3 @@ const split = require('split2')

<a name="license"></a>
## License

@@ -415,0 +460,0 @@

@@ -8,7 +8,7 @@ 'use strict'

const internals = require('../../lib/tier-node')[Symbol.for('internals')]
const Reply = require('../../lib/reply')
test('Reply should be an object', t => {
t.plan(1)
t.is(typeof internals.Reply, 'function')
t.is(typeof Reply, 'function')
})

@@ -21,3 +21,3 @@

function handle () {}
const reply = new internals.Reply(request, response, handle)
const reply = new Reply(request, response, handle)
t.is(typeof reply, 'object')

@@ -36,5 +36,5 @@ t.is(typeof reply.send, 'function')

const response = { setHeader: () => {} }
const reply = new internals.Reply(request, response, null)
t.type(reply.code(1), internals.Reply)
t.type(reply.header('hello', 'world'), internals.Reply)
const reply = new Reply(request, response, null)
t.type(reply.code(1), Reply)
t.type(reply.header('hello', 'world'), Reply)
})

@@ -41,0 +41,0 @@

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

const internals = require('../../lib/tier-node')[Symbol.for('internals')]
const Request = require('../../lib/request')
const buildSchema = require('../../lib/validation').build

@@ -12,4 +13,4 @@

t.plan(5)
const req = new internals.Request('params', 'req', 'body', 'query')
t.type(req, internals.Request)
const req = new Request('params', 'req', 'body', 'query')
t.type(req, Request)
t.equal(req.params, 'params')

@@ -169,5 +170,8 @@ t.equal(req.req, 'req')

method: 'GET',
url: 'http://example.com'
url: 'http://example.com',
log: {
error: () => {}
}
}
handle(null, req, res)
})
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