Socket
Socket
Sign inDemoInstall

fastify

Package Overview
Dependencies
55
Maintainers
3
Versions
282
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 4.4.0 to 4.5.0

test/upgrade.test.js

2

build/build-validation.js

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

pluginTimeout: { type: 'integer', default: defaultInitOptions.pluginTimeout },
requestIdHeader: { type: 'string', default: defaultInitOptions.requestIdHeader },
requestIdHeader: { anyOf: [{ enum: [false] }, { type: 'string' }], default: defaultInitOptions.requestIdHeader },
requestIdLogLabel: { type: 'string', default: defaultInitOptions.requestIdLogLabel },

@@ -103,0 +103,0 @@ http2SessionTimeout: { type: 'integer', default: defaultInitOptions.http2SessionTimeout },

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

on HTTP and HTTPS.
- [`fastify-https-always`](https://github.com/mattbishop/fastify-https-always)
Lightweight, proxy-aware redirect plugin from HTTP to HTTPS.
- [`fastify-https-redirect`](https://github.com/tomsvogel/fastify-https-redirect)

@@ -430,2 +432,4 @@ Fastify plugin for auto-redirect from HTTP to HTTPS.

across every part of your server.
- [`fastify-osm`](https://github.com/gzileni/fastify-osm) Fastify
OSM plugin to run overpass queries by OpenStreetMap.
- [`fastify-peekaboo`](https://github.com/simone-sanfratello/fastify-peekaboo)

@@ -432,0 +436,0 @@ Fastify plugin for memoize responses by expressive settings.

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

> const append = require('vary').append
> fastify.addHook('onSend', async (req, reply) => {
> fastify.addHook('onSend', (req, reply, payload, done) => {
> if (req.headers['accept-version']) { // or the custom header you are using

@@ -670,2 +670,3 @@ > let value = reply.getHeader('Vary') || ''

> }
> done()
> })

@@ -672,0 +673,0 @@ > ```

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

- [close](#close)
- [decorate\*](#decorate)
- [decorate*](#decorate)
- [register](#register)

@@ -492,7 +492,14 @@ - [addHook](#addhook)

The header name used to know the request-id. See [the
The header name used to set the request-id. See [the
request-id](./Logging.md#logging-request-id) section.
Setting `requestIdHeader` to `false` will always use [genReqId](#genreqid)
+ Default: `'request-id'`
```js
const fastify = require('fastify')({
requestIdHeader: 'x-custom-id', // -> use 'X-Custom-Id' header if available
//requestIdHeader: false, // -> always use genReqId
})
```
### `requestIdLogLabel`

@@ -1117,8 +1124,11 @@ <a id="factory-request-id-log-label"></a>

Name of the current plugin. The root plugin is called `'fastify'`. There are
three ways to define a name (in order).
different ways to define a name (in order).
1. If you use [fastify-plugin](https://github.com/fastify/fastify-plugin) the
metadata `name` is used.
2. If you `module.exports` a plugin the filename is used.
3. If you use a regular [function
2. If the exported plugin has the `Symbol.for('fastify.display-name')` property,
then the value of that property is used.
Example: `pluginFn[Symbol.for('fastify.display-name')] = "Custom Name"`
3. If you `module.exports` a plugin the filename is used.
4. If you use a regular [function
declaration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#Defining_functions)

@@ -1125,0 +1135,0 @@ the function name is used.

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

{"params":{"hello":["1"]}}
{"params":{"ids":["1"]}}
```

@@ -274,0 +274,0 @@

@@ -126,3 +126,3 @@ import * as http from 'http'

caseSensitive?: boolean,
requestIdHeader?: string,
requestIdHeader?: string | false,
requestIdLogLabel?: string;

@@ -129,0 +129,0 @@ jsonShorthand?: boolean;

'use strict'
const VERSION = '4.4.0'
const VERSION = '4.5.0'

@@ -101,4 +101,4 @@ const Avvio = require('avvio')

const requestIdHeader = options.requestIdHeader || defaultInitOptions.requestIdHeader
const genReqId = options.genReqId || reqIdGenFactory()
const requestIdHeader = (options.requestIdHeader === false) ? false : (options.requestIdHeader || defaultInitOptions.requestIdHeader)
const genReqId = reqIdGenFactory(requestIdHeader, options.genReqId)
const requestIdLogLabel = options.requestIdLogLabel || 'reqId'

@@ -105,0 +105,0 @@ const bodyLimit = options.bodyLimit || defaultInitOptions.bodyLimit

@@ -6,3 +6,3 @@ // This file is autogenerated by build/build-validation.js, do not edit

module.exports.default = validate10;
const schema11 = {"type":"object","additionalProperties":false,"properties":{"connectionTimeout":{"type":"integer","default":0},"keepAliveTimeout":{"type":"integer","default":72000},"forceCloseConnections":{"oneOf":[{"type":"string","pattern":"idle"},{"type":"boolean"}]},"maxRequestsPerSocket":{"type":"integer","default":0,"nullable":true},"requestTimeout":{"type":"integer","default":0},"bodyLimit":{"type":"integer","default":1048576},"caseSensitive":{"type":"boolean","default":true},"allowUnsafeRegex":{"type":"boolean","default":false},"http2":{"type":"boolean"},"https":{"if":{"not":{"oneOf":[{"type":"boolean"},{"type":"null"},{"type":"object","additionalProperties":false,"required":["allowHTTP1"],"properties":{"allowHTTP1":{"type":"boolean"}}}]}},"then":{"setDefaultValue":true}},"ignoreTrailingSlash":{"type":"boolean","default":false},"ignoreDuplicateSlashes":{"type":"boolean","default":false},"disableRequestLogging":{"type":"boolean","default":false},"jsonShorthand":{"type":"boolean","default":true},"maxParamLength":{"type":"integer","default":100},"onProtoPoisoning":{"type":"string","default":"error"},"onConstructorPoisoning":{"type":"string","default":"error"},"pluginTimeout":{"type":"integer","default":10000},"requestIdHeader":{"type":"string","default":"request-id"},"requestIdLogLabel":{"type":"string","default":"reqId"},"http2SessionTimeout":{"type":"integer","default":72000},"exposeHeadRoutes":{"type":"boolean","default":true},"versioning":{"type":"object","additionalProperties":true,"required":["storage","deriveVersion"],"properties":{"storage":{},"deriveVersion":{}}},"constraints":{"type":"object","additionalProperties":{"type":"object","required":["name","storage","validate","deriveConstraint"],"additionalProperties":true,"properties":{"name":{"type":"string"},"storage":{},"validate":{},"deriveConstraint":{}}}}}};
const schema11 = {"type":"object","additionalProperties":false,"properties":{"connectionTimeout":{"type":"integer","default":0},"keepAliveTimeout":{"type":"integer","default":72000},"forceCloseConnections":{"oneOf":[{"type":"string","pattern":"idle"},{"type":"boolean"}]},"maxRequestsPerSocket":{"type":"integer","default":0,"nullable":true},"requestTimeout":{"type":"integer","default":0},"bodyLimit":{"type":"integer","default":1048576},"caseSensitive":{"type":"boolean","default":true},"allowUnsafeRegex":{"type":"boolean","default":false},"http2":{"type":"boolean"},"https":{"if":{"not":{"oneOf":[{"type":"boolean"},{"type":"null"},{"type":"object","additionalProperties":false,"required":["allowHTTP1"],"properties":{"allowHTTP1":{"type":"boolean"}}}]}},"then":{"setDefaultValue":true}},"ignoreTrailingSlash":{"type":"boolean","default":false},"ignoreDuplicateSlashes":{"type":"boolean","default":false},"disableRequestLogging":{"type":"boolean","default":false},"jsonShorthand":{"type":"boolean","default":true},"maxParamLength":{"type":"integer","default":100},"onProtoPoisoning":{"type":"string","default":"error"},"onConstructorPoisoning":{"type":"string","default":"error"},"pluginTimeout":{"type":"integer","default":10000},"requestIdHeader":{"anyOf":[{"enum":[false]},{"type":"string"}],"default":"request-id"},"requestIdLogLabel":{"type":"string","default":"reqId"},"http2SessionTimeout":{"type":"integer","default":72000},"exposeHeadRoutes":{"type":"boolean","default":true},"versioning":{"type":"object","additionalProperties":true,"required":["storage","deriveVersion"],"properties":{"storage":{},"deriveVersion":{}}},"constraints":{"type":"object","additionalProperties":{"type":"object","required":["name","storage","validate","deriveConstraint"],"additionalProperties":true,"properties":{"name":{"type":"string"},"storage":{},"validate":{},"deriveConstraint":{}}}}}};
const func2 = Object.prototype.hasOwnProperty;

@@ -841,2 +841,19 @@ const pattern0 = new RegExp("idle", "u");

const _errs57 = errors;
const _errs58 = errors;
let valid6 = false;
const _errs59 = errors;
if(!(data19 === false)){
const err12 = {instancePath:instancePath+"/requestIdHeader",schemaPath:"#/properties/requestIdHeader/anyOf/0/enum",keyword:"enum",params:{allowedValues: schema11.properties.requestIdHeader.anyOf[0].enum},message:"must be equal to one of the allowed values"};
if(vErrors === null){
vErrors = [err12];
}
else {
vErrors.push(err12);
}
errors++;
}
var _valid3 = _errs59 === errors;
valid6 = valid6 || _valid3;
if(!valid6){
const _errs60 = errors;
if(typeof data19 !== "string"){

@@ -853,6 +870,12 @@ let dataType21 = typeof data19;

else {
validate10.errors = [{instancePath:instancePath+"/requestIdHeader",schemaPath:"#/properties/requestIdHeader/type",keyword:"type",params:{type: "string"},message:"must be string"}];
return false;
const err13 = {instancePath:instancePath+"/requestIdHeader",schemaPath:"#/properties/requestIdHeader/anyOf/1/type",keyword:"type",params:{type: "string"},message:"must be string"};
if(vErrors === null){
vErrors = [err13];
}
else {
vErrors.push(err13);
}
errors++;
}
}
if(coerced21 !== undefined){

@@ -865,6 +888,32 @@ data19 = coerced21;

}
var _valid3 = _errs60 === errors;
valid6 = valid6 || _valid3;
}
if(!valid6){
const err14 = {instancePath:instancePath+"/requestIdHeader",schemaPath:"#/properties/requestIdHeader/anyOf",keyword:"anyOf",params:{},message:"must match a schema in anyOf"};
if(vErrors === null){
vErrors = [err14];
}
else {
vErrors.push(err14);
}
errors++;
validate10.errors = vErrors;
return false;
}
else {
errors = _errs58;
if(vErrors !== null){
if(_errs58){
vErrors.length = _errs58;
}
else {
vErrors = null;
}
}
}
var valid0 = _errs57 === errors;
if(valid0){
let data20 = data.requestIdLogLabel;
const _errs59 = errors;
const _errs62 = errors;
if(typeof data20 !== "string"){

@@ -892,6 +941,6 @@ let dataType22 = typeof data20;

}
var valid0 = _errs59 === errors;
var valid0 = _errs62 === errors;
if(valid0){
let data21 = data.http2SessionTimeout;
const _errs61 = errors;
const _errs64 = errors;
if(!(((typeof data21 == "number") && (!(data21 % 1) && !isNaN(data21))) && (isFinite(data21)))){

@@ -917,6 +966,6 @@ let dataType23 = typeof data21;

}
var valid0 = _errs61 === errors;
var valid0 = _errs64 === errors;
if(valid0){
let data22 = data.exposeHeadRoutes;
const _errs63 = errors;
const _errs66 = errors;
if(typeof data22 !== "boolean"){

@@ -943,8 +992,8 @@ let coerced24 = undefined;

}
var valid0 = _errs63 === errors;
var valid0 = _errs66 === errors;
if(valid0){
if(data.versioning !== undefined){
let data23 = data.versioning;
const _errs65 = errors;
if(errors === _errs65){
const _errs68 = errors;
if(errors === _errs68){
if(data23 && typeof data23 == "object" && !Array.isArray(data23)){

@@ -962,3 +1011,3 @@ let missing1;

}
var valid0 = _errs65 === errors;
var valid0 = _errs68 === errors;
}

@@ -971,9 +1020,9 @@ else {

let data24 = data.constraints;
const _errs68 = errors;
if(errors === _errs68){
const _errs71 = errors;
if(errors === _errs71){
if(data24 && typeof data24 == "object" && !Array.isArray(data24)){
for(const key2 in data24){
let data25 = data24[key2];
const _errs71 = errors;
if(errors === _errs71){
const _errs74 = errors;
if(errors === _errs74){
if(data25 && typeof data25 == "object" && !Array.isArray(data25)){

@@ -1018,4 +1067,4 @@ let missing2;

}
var valid6 = _errs71 === errors;
if(!valid6){
var valid7 = _errs74 === errors;
if(!valid7){
break;

@@ -1030,3 +1079,3 @@ }

}
var valid0 = _errs68 === errors;
var valid0 = _errs71 === errors;
}

@@ -1033,0 +1082,0 @@ else {

'use strict'
module.exports = function () {
module.exports = function (requestIdHeader, optGenReqId) {
// 2,147,483,647 (2^31 − 1) stands for max SMI value (an internal optimization of V8).

@@ -11,6 +11,17 @@ // With this upper bound, if you'll be generating 1k ids/sec, you're going to hit it in ~25 days.

let nextReqId = 0
return function genReqId (req) {
function defaultGenReqId (req) {
nextReqId = (nextReqId + 1) & maxInt
return `req-${nextReqId.toString(36)}`
}
const genReqId = optGenReqId || defaultGenReqId
if (requestIdHeader) {
// requestIdHeader = typeof requestIdHeader === 'string' ? requestIdHeader : 'request-id'
return function (req) {
return req.headers[requestIdHeader] || genReqId(req)
}
}
return genReqId
}

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

let fourOhFour
let requestIdHeader
let requestIdLogLabel

@@ -78,3 +77,2 @@ let logger

globalExposeHeadRoutes = options.exposeHeadRoutes
requestIdHeader = options.requestIdHeader
requestIdLogLabel = options.requestIdLogLabel

@@ -402,3 +400,3 @@ genReqId = options.genReqId

const id = req.headers[requestIdHeader] || genReqId(req)
const id = genReqId(req)

@@ -405,0 +403,0 @@ const loggerBinding = {

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

const closeSecondary = () => { secondaryServer.close(() => {}) }
secondaryServer.on('upgrade', mainServer.emit.bind(mainServer, 'upgrade'))
mainServer.on('unref', closeSecondary)

@@ -137,0 +138,0 @@ mainServer.on('close', closeSecondary)

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

@@ -140,4 +140,2 @@ "main": "fastify.js",

"branch-comparer": "^1.1.0",
"cors": "^2.8.5",
"dns-prefetch-control": "^0.3.0",
"eslint": "^8.16.0",

@@ -154,6 +152,3 @@ "eslint-config-standard": "^17.0.0-1",

"form-data": "^4.0.0",
"frameguard": "^4.0.0",
"h2url": "^0.2.0",
"helmet": "^5.1.0",
"hide-powered-by": "^1.1.0",
"http-errors": "^2.0.0",

@@ -169,3 +164,2 @@ "joi": "^17.6.0",

"send": "^0.18.0",
"serve-static": "^1.15.0",
"simple-get": "^4.0.1",

@@ -179,3 +173,3 @@ "snazzy": "^9.0.0",

"undici": "^5.4.0",
"x-xss-protection": "^2.0.0",
"vary": "^1.1.2",
"yup": "^0.32.11"

@@ -182,0 +176,0 @@ },

@@ -333,2 +333,47 @@ 'use strict'

test('The request id header key can be ignored', t => {
t.plan(9)
const REQUEST_ID = 'ignore-me'
const stream = split(JSON.parse)
const fastify = Fastify({
logger: { stream, level: 'info' },
requestIdHeader: false
})
t.teardown(() => fastify.close())
fastify.get('/', (req, reply) => {
t.equal(req.id, 'req-1')
req.log.info('some log message')
reply.send({ id: req.id })
})
fastify.inject({
method: 'GET',
url: '/',
headers: {
'request-id': REQUEST_ID
}
}, (err, res) => {
t.error(err)
const payload = JSON.parse(res.payload)
t.equal(payload.id, 'req-1')
stream.once('data', line => {
t.equal(line.reqId, 'req-1')
t.equal(line.msg, 'incoming request', 'message is set')
stream.once('data', line => {
t.equal(line.reqId, 'req-1')
t.equal(line.msg, 'some log message', 'message is set')
stream.once('data', line => {
t.equal(line.reqId, 'req-1')
t.equal(line.msg, 'request completed', 'message is set')
})
})
})
})
})
test('The request id header key can be customized along with a custom id generator', t => {

@@ -397,2 +442,65 @@ t.plan(12)

test('The request id header key can be ignored along with a custom id generator', t => {
t.plan(12)
const REQUEST_ID = 'ignore-me'
const stream = split(JSON.parse)
const fastify = Fastify({
logger: { stream, level: 'info' },
requestIdHeader: false,
genReqId (req) {
return 'foo'
}
})
t.teardown(() => fastify.close())
fastify.get('/one', (req, reply) => {
t.equal(req.id, 'foo')
req.log.info('some log message')
reply.send({ id: req.id })
})
fastify.get('/two', (req, reply) => {
t.equal(req.id, 'foo')
req.log.info('some log message 2')
reply.send({ id: req.id })
})
const matches = [
{ reqId: 'foo', msg: /incoming request/ },
{ reqId: 'foo', msg: /some log message/ },
{ reqId: 'foo', msg: /request completed/ },
{ reqId: 'foo', msg: /incoming request/ },
{ reqId: 'foo', msg: /some log message 2/ },
{ reqId: 'foo', msg: /request completed/ }
]
let i = 0
stream.on('data', line => {
t.match(line, matches[i])
i += 1
})
fastify.inject({
method: 'GET',
url: '/one',
headers: {
'request-id': REQUEST_ID
}
}, (err, res) => {
t.error(err)
const payload = JSON.parse(res.payload)
t.equal(payload.id, 'foo')
})
fastify.inject({
method: 'GET',
url: '/two'
}, (err, res) => {
t.error(err)
const payload = JSON.parse(res.payload)
t.equal(payload.id, 'foo')
})
})
test('The request id log label can be changed', t => {

@@ -399,0 +507,0 @@ t.plan(6)

@@ -512,2 +512,56 @@ 'use strict'

test('should be able to handle formats of ajv-formats when added by plugins option', t => {
t.plan(3)
const fastify = Fastify({
ajv: {
plugins: [
require('ajv-formats')
]
}
})
const schema = {
body: {
type: 'object',
properties: {
id: { type: 'string', format: 'uuid' },
email: { type: 'string', format: 'email' }
},
required: ['id', 'email']
}
}
fastify.post('/', { schema }, function (req, reply) {
reply.code(200).send(req.body.id)
})
fastify.inject({
method: 'POST',
payload: {
id: '254381a5-888c-4b41-8116-e3b1a54980bd',
email: 'info@fastify.io'
},
url: '/'
}, (_err, res) => {
t.equal(res.body, '254381a5-888c-4b41-8116-e3b1a54980bd')
t.equal(res.statusCode, 200)
})
fastify.inject({
method: 'POST',
payload: {
id: 'invalid',
email: 'info@fastify.io'
},
url: '/'
}, (_err, res) => {
t.same(JSON.parse(res.payload), {
statusCode: 400,
error: 'Bad Request',
message: 'body/id must match format "uuid"'
})
})
})
test('should return localized error messages with ajv-i18n', t => {

@@ -514,0 +568,0 @@ t.plan(3)

@@ -124,2 +124,3 @@ import fastify, {

expectAssignable<FastifyInstance>(fastify({ requestIdHeader: 'request-id' }))
expectAssignable<FastifyInstance>(fastify({ requestIdHeader: false }))
expectAssignable<FastifyInstance>(fastify({ genReqId: () => 'request-id' }))

@@ -126,0 +127,0 @@ expectAssignable<FastifyInstance>(fastify({ trustProxy: true }))

@@ -270,3 +270,3 @@ import { expectAssignable, expectDeprecated, expectError, expectNotDeprecated, expectType } from 'tsd'

pluginTimeout?: number,
requestIdHeader?: string,
requestIdHeader?: string | false,
requestIdLogLabel?: string,

@@ -273,0 +273,0 @@ http2SessionTimeout?: number

@@ -576,3 +576,3 @@ import { FastifyError } from '@fastify/error'

pluginTimeout?: number,
requestIdHeader?: string,
requestIdHeader?: string | false,
requestIdLogLabel?: string,

@@ -579,0 +579,0 @@ http2SessionTimeout?: number

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