fastify 3.4.1 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/ContentTypeParser.md +3 -0
- package/docs/Decorators.md +2 -0
- package/docs/Ecosystem.md +2 -1
- package/docs/Lifecycle.md +2 -2
- package/docs/Logging.md +1 -1
- package/docs/Reply.md +18 -0
- package/docs/Request.md +5 -1
- package/docs/Routes.md +2 -2
- package/docs/Server.md +55 -4
- package/docs/TypeScript.md +2 -1
- package/docs/Validation-and-Serialization.md +11 -5
- package/examples/simple.mjs +27 -0
- package/fastify.js +55 -7
- package/lib/contentTypeParser.js +4 -0
- package/lib/context.js +1 -16
- package/lib/errors.js +10 -2
- package/lib/fourOhFour.js +4 -3
- package/lib/logger.js +1 -1
- package/lib/pluginUtils.js +15 -0
- package/lib/reply.js +3 -3
- package/lib/request.js +26 -1
- package/lib/route.js +7 -3
- package/lib/symbols.js +2 -1
- package/lib/validation.js +1 -0
- package/lib/warnings.js +3 -0
- package/lib/wrapThenable.js +2 -2
- package/package.json +5 -5
- package/test/custom-parser.test.js +30 -0
- package/test/emit-warning.test.js +31 -0
- package/test/esm/index.test.js +15 -2
- package/test/esm/named-exports.mjs +13 -0
- package/test/fastify-instance.test.js +33 -1
- package/test/http2/secure.test.js +11 -0
- package/test/https/https.test.js +26 -0
- package/test/internals/request.test.js +8 -5
- package/test/internals/version.test.js +43 -0
- package/test/listen.test.js +16 -0
- package/test/logger.test.js +1 -1
- package/test/plugin.test.js +108 -0
- package/test/request-error.test.js +81 -0
- package/test/route.test.js +27 -0
- package/test/trust-proxy.test.js +42 -5
- package/test/types/decorate-request-reply.test-d.ts +18 -0
- package/test/types/instance.test-d.ts +27 -9
- package/test/types/logger.test-d.ts +63 -1
- package/test/types/register.test-d.ts +16 -0
- package/test/types/request.test-d.ts +1 -1
- package/test/types/schema.test-d.ts +5 -0
- package/test/validation-error-handling.test.js +66 -0
- package/types/instance.d.ts +7 -13
- package/types/logger.d.ts +90 -10
- package/types/register.d.ts +1 -0
- package/types/request.d.ts +20 -11
- package/types/schema.d.ts +2 -2
package/lib/request.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const proxyAddr = require('proxy-addr')
|
|
4
|
+
const semver = require('semver')
|
|
4
5
|
const warning = require('./warnings')
|
|
5
6
|
|
|
6
7
|
function Request (id, params, req, query, log, context) {
|
|
@@ -78,6 +79,17 @@ function buildRequestWithTrustProxy (R, trustProxy) {
|
|
|
78
79
|
}
|
|
79
80
|
return this.headers.host || this.headers[':authority']
|
|
80
81
|
}
|
|
82
|
+
},
|
|
83
|
+
protocol: {
|
|
84
|
+
get () {
|
|
85
|
+
if (this.headers['x-forwarded-proto']) {
|
|
86
|
+
const proto = this.headers['x-forwarded-proto']
|
|
87
|
+
// we use the last one if the header is set more than once
|
|
88
|
+
const lastIndex = proto.lastIndexOf(',')
|
|
89
|
+
return lastIndex === -1 ? proto.trim() : proto.slice(lastIndex + 1).trim()
|
|
90
|
+
}
|
|
91
|
+
return this.socket.encrypted ? 'https' : 'http'
|
|
92
|
+
}
|
|
81
93
|
}
|
|
82
94
|
})
|
|
83
95
|
|
|
@@ -118,12 +130,20 @@ Object.defineProperties(Request.prototype, {
|
|
|
118
130
|
},
|
|
119
131
|
connection: {
|
|
120
132
|
get () {
|
|
133
|
+
if (semver.gte(process.versions.node, '13.0.0')) {
|
|
134
|
+
warning.emit('FSTDEP005')
|
|
135
|
+
}
|
|
121
136
|
return this.raw.connection
|
|
122
137
|
}
|
|
123
138
|
},
|
|
139
|
+
socket: {
|
|
140
|
+
get () {
|
|
141
|
+
return this.raw.socket
|
|
142
|
+
}
|
|
143
|
+
},
|
|
124
144
|
ip: {
|
|
125
145
|
get () {
|
|
126
|
-
return this.
|
|
146
|
+
return this.socket.remoteAddress
|
|
127
147
|
}
|
|
128
148
|
},
|
|
129
149
|
hostname: {
|
|
@@ -131,6 +151,11 @@ Object.defineProperties(Request.prototype, {
|
|
|
131
151
|
return this.raw.headers.host || this.raw.headers[':authority']
|
|
132
152
|
}
|
|
133
153
|
},
|
|
154
|
+
protocol: {
|
|
155
|
+
get () {
|
|
156
|
+
return this.socket.encrypted ? 'https' : 'http'
|
|
157
|
+
}
|
|
158
|
+
},
|
|
134
159
|
headers: {
|
|
135
160
|
get () {
|
|
136
161
|
return this.raw.headers
|
package/lib/route.js
CHANGED
|
@@ -40,7 +40,8 @@ const {
|
|
|
40
40
|
kRequest,
|
|
41
41
|
kRequestPayloadStream,
|
|
42
42
|
kDisableRequestLogging,
|
|
43
|
-
kSchemaErrorFormatter
|
|
43
|
+
kSchemaErrorFormatter,
|
|
44
|
+
kErrorHandler
|
|
44
45
|
} = require('./symbols.js')
|
|
45
46
|
|
|
46
47
|
function buildRouting (options) {
|
|
@@ -116,7 +117,10 @@ function buildRouting (options) {
|
|
|
116
117
|
}
|
|
117
118
|
|
|
118
119
|
// Route management
|
|
119
|
-
function route (
|
|
120
|
+
function route (options) {
|
|
121
|
+
// Since we are mutating/assigning only top level props, it is fine to have a shallow copy using the spread operator
|
|
122
|
+
const opts = { ...options }
|
|
123
|
+
|
|
120
124
|
throwIfAlreadyStarted('Cannot add route when fastify instance is already started!')
|
|
121
125
|
|
|
122
126
|
if (Array.isArray(opts.method)) {
|
|
@@ -210,7 +214,7 @@ function buildRouting (options) {
|
|
|
210
214
|
this[kRequest],
|
|
211
215
|
this[kContentTypeParser],
|
|
212
216
|
config,
|
|
213
|
-
opts.errorHandler || this
|
|
217
|
+
opts.errorHandler || this[kErrorHandler],
|
|
214
218
|
opts.bodyLimit,
|
|
215
219
|
opts.logLevel,
|
|
216
220
|
opts.logSerializers,
|
package/lib/symbols.js
CHANGED
|
@@ -38,7 +38,8 @@ const keys = {
|
|
|
38
38
|
kDisableRequestLogging: Symbol('fastify.disableRequestLogging'),
|
|
39
39
|
kPluginNameChain: Symbol('fastify.pluginNameChain'),
|
|
40
40
|
// This symbol is only meant to be used for fastify tests and should not be used for any other purpose
|
|
41
|
-
kTestInternals: Symbol('fastify.testInternals')
|
|
41
|
+
kTestInternals: Symbol('fastify.testInternals'),
|
|
42
|
+
kErrorHandler: Symbol('fastify.errorHandler')
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
module.exports = keys
|
package/lib/validation.js
CHANGED
package/lib/warnings.js
CHANGED
|
@@ -8,6 +8,7 @@ const warning = require('fastify-warning')()
|
|
|
8
8
|
* - FSTDEP002
|
|
9
9
|
* - FSTDEP003
|
|
10
10
|
* - FSTDEP004
|
|
11
|
+
* - FSTDEP005
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
warning.create('FastifyDeprecation', 'FSTDEP001', 'You are accessing the Node.js core request object via "request.req", Use "request.raw" instead.')
|
|
@@ -18,4 +19,6 @@ warning.create('FastifyDeprecation', 'FSTDEP003', 'You are using the legacy Cont
|
|
|
18
19
|
|
|
19
20
|
warning.create('FastifyDeprecation', 'FSTDEP004', 'You are using the legacy preParsing hook signature. Use the one suggested in the documentation instead.')
|
|
20
21
|
|
|
22
|
+
warning.create('FastifyDeprecation', 'FSTDEP005', 'You are accessing the deprecated "request.connection" property. Use "request.socket" instead.')
|
|
23
|
+
|
|
21
24
|
module.exports = warning
|
package/lib/wrapThenable.js
CHANGED
|
@@ -6,7 +6,7 @@ const {
|
|
|
6
6
|
kReplySentOverwritten
|
|
7
7
|
} = require('./symbols')
|
|
8
8
|
|
|
9
|
-
const {
|
|
9
|
+
const { FST_ERR_PROMISE_NOT_FULFILLED } = require('./errors')
|
|
10
10
|
|
|
11
11
|
function wrapThenable (thenable, reply) {
|
|
12
12
|
thenable.then(function (payload) {
|
|
@@ -27,7 +27,7 @@ function wrapThenable (thenable, reply) {
|
|
|
27
27
|
reply.send(err)
|
|
28
28
|
}
|
|
29
29
|
} else if (reply[kReplySent] === false) {
|
|
30
|
-
reply.log.error({ err: new
|
|
30
|
+
reply.log.error({ err: new FST_ERR_PROMISE_NOT_FULFILLED() }, "Promise may not be fulfilled with 'undefined' when statusCode is not 204")
|
|
31
31
|
}
|
|
32
32
|
}, function (err) {
|
|
33
33
|
if (reply[kReplySentOverwritten] === true) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastify",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"description": "Fast and low overhead web framework, for Node.js",
|
|
5
5
|
"main": "fastify.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -114,8 +114,8 @@
|
|
|
114
114
|
"devDependencies": {
|
|
115
115
|
"@hapi/joi": "^17.1.1",
|
|
116
116
|
"@sinonjs/fake-timers": "^6.0.1",
|
|
117
|
-
"@types/node": "^14.0.1",
|
|
118
117
|
"@types/pino": "^6.0.1",
|
|
118
|
+
"@types/node": "^14.10.3",
|
|
119
119
|
"@typescript-eslint/eslint-plugin": "^2.29.0",
|
|
120
120
|
"@typescript-eslint/parser": "^2.29.0",
|
|
121
121
|
"JSONStream": "^1.3.5",
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
"eslint-plugin-standard": "^4.0.1",
|
|
139
139
|
"events.once": "^2.0.2",
|
|
140
140
|
"fast-json-body": "^1.1.0",
|
|
141
|
-
"fastify-plugin": "^
|
|
141
|
+
"fastify-plugin": "^3.0.0",
|
|
142
142
|
"fluent-schema": "^1.0.0",
|
|
143
143
|
"form-data": "^3.0.0",
|
|
144
144
|
"frameguard": "^3.1.0",
|
|
@@ -152,7 +152,6 @@
|
|
|
152
152
|
"pre-commit": "^1.2.2",
|
|
153
153
|
"proxyquire": "^2.1.3",
|
|
154
154
|
"pump": "^3.0.0",
|
|
155
|
-
"semver": "^7.3.2",
|
|
156
155
|
"send": "^0.17.1",
|
|
157
156
|
"serve-static": "^1.14.1",
|
|
158
157
|
"simple-get": "^4.0.0",
|
|
@@ -177,12 +176,13 @@
|
|
|
177
176
|
"fastify-warning": "^0.2.0",
|
|
178
177
|
"find-my-way": "^3.0.0",
|
|
179
178
|
"flatstr": "^1.0.12",
|
|
180
|
-
"light-my-request": "^4.0
|
|
179
|
+
"light-my-request": "^4.2.0",
|
|
181
180
|
"pino": "^6.2.1",
|
|
182
181
|
"proxy-addr": "^2.0.5",
|
|
183
182
|
"readable-stream": "^3.4.0",
|
|
184
183
|
"rfdc": "^1.1.4",
|
|
185
184
|
"secure-json-parse": "^2.0.0",
|
|
185
|
+
"semver": "^7.3.2",
|
|
186
186
|
"tiny-lru": "^7.0.0"
|
|
187
187
|
},
|
|
188
188
|
"standard": {
|
|
@@ -1214,3 +1214,33 @@ test('route bodyLimit should take precedence over a custom parser bodyLimit', t
|
|
|
1214
1214
|
})
|
|
1215
1215
|
})
|
|
1216
1216
|
})
|
|
1217
|
+
|
|
1218
|
+
test('should be able to use default parser for extra content type', t => {
|
|
1219
|
+
t.plan(4)
|
|
1220
|
+
const fastify = Fastify()
|
|
1221
|
+
t.tearDown(() => fastify.close())
|
|
1222
|
+
|
|
1223
|
+
fastify.post('/', (request, reply) => {
|
|
1224
|
+
reply.send(request.body)
|
|
1225
|
+
})
|
|
1226
|
+
|
|
1227
|
+
fastify.addContentTypeParser('text/json', { parseAs: 'string' }, fastify.getDefaultJsonParser('ignore', 'ignore'))
|
|
1228
|
+
|
|
1229
|
+
fastify.listen(0, err => {
|
|
1230
|
+
t.error(err)
|
|
1231
|
+
|
|
1232
|
+
sget({
|
|
1233
|
+
method: 'POST',
|
|
1234
|
+
url: 'http://localhost:' + fastify.server.address().port,
|
|
1235
|
+
body: '{"hello":"world"}',
|
|
1236
|
+
headers: {
|
|
1237
|
+
'Content-Type': 'text/json'
|
|
1238
|
+
}
|
|
1239
|
+
}, (err, response, body) => {
|
|
1240
|
+
t.error(err)
|
|
1241
|
+
t.strictEqual(response.statusCode, 200)
|
|
1242
|
+
t.strictDeepEqual(JSON.parse(body.toString()), { hello: 'world' })
|
|
1243
|
+
fastify.close()
|
|
1244
|
+
})
|
|
1245
|
+
})
|
|
1246
|
+
})
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const sget = require('simple-get').concat
|
|
4
4
|
const { test } = require('tap')
|
|
5
5
|
const Fastify = require('..')
|
|
6
|
+
const semver = require('semver')
|
|
6
7
|
|
|
7
8
|
process.removeAllListeners('warning')
|
|
8
9
|
|
|
@@ -129,3 +130,33 @@ test('Should emit a warning when using payload less preParsing hook', t => {
|
|
|
129
130
|
})
|
|
130
131
|
})
|
|
131
132
|
})
|
|
133
|
+
|
|
134
|
+
if (semver.gte(process.versions.node, '13.0.0')) {
|
|
135
|
+
test('Should emit a warning when accessing request.connection instead of request.socket on Node process greater than 13.0.0', t => {
|
|
136
|
+
t.plan(4)
|
|
137
|
+
|
|
138
|
+
process.on('warning', onWarning)
|
|
139
|
+
function onWarning (warning) {
|
|
140
|
+
t.strictEqual(warning.name, 'FastifyDeprecation')
|
|
141
|
+
t.strictEqual(warning.code, 'FSTDEP005')
|
|
142
|
+
t.strictEqual(warning.message, 'You are accessing the deprecated "request.connection" property. Use "request.socket" instead.')
|
|
143
|
+
|
|
144
|
+
// removed listener before light-my-request emit second warning
|
|
145
|
+
process.removeListener('warning', onWarning)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const fastify = Fastify()
|
|
149
|
+
|
|
150
|
+
fastify.get('/', (request, reply) => {
|
|
151
|
+
reply.send(request.connection)
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
fastify.inject({
|
|
155
|
+
method: 'GET',
|
|
156
|
+
path: '/'
|
|
157
|
+
}, (err, res) => {
|
|
158
|
+
t.error(err)
|
|
159
|
+
process.removeListener('warning', onWarning)
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
}
|
package/test/esm/index.test.js
CHANGED
|
@@ -4,8 +4,7 @@ const t = require('tap')
|
|
|
4
4
|
const semver = require('semver')
|
|
5
5
|
|
|
6
6
|
if (semver.lt(process.versions.node, '13.3.0')) {
|
|
7
|
-
t.skip('Skip because Node version <= 13.3.0')
|
|
8
|
-
t.end()
|
|
7
|
+
t.skip('Skip esm because Node version <= 13.3.0')
|
|
9
8
|
} else {
|
|
10
9
|
// Node v8 throw a `SyntaxError: Unexpected token import`
|
|
11
10
|
// even if this branch is never touch in the code,
|
|
@@ -17,3 +16,17 @@ if (semver.lt(process.versions.node, '13.3.0')) {
|
|
|
17
16
|
})
|
|
18
17
|
})
|
|
19
18
|
}
|
|
19
|
+
|
|
20
|
+
if (semver.lt(process.versions.node, '14.13.0')) {
|
|
21
|
+
t.skip('Skip named exports because Node version < 14.13.0')
|
|
22
|
+
} else {
|
|
23
|
+
// Node v8 throw a `SyntaxError: Unexpected token import`
|
|
24
|
+
// even if this branch is never touch in the code,
|
|
25
|
+
// by using `eval` we can avoid this issue.
|
|
26
|
+
// eslint-disable-next-line
|
|
27
|
+
new Function('module', 'return import(module)')('./named-exports.mjs').catch((err) => {
|
|
28
|
+
process.nextTick(() => {
|
|
29
|
+
throw err
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import t from 'tap'
|
|
2
|
+
import { fastify } from '../../fastify.js'
|
|
3
|
+
|
|
4
|
+
t.test('named exports support', async t => {
|
|
5
|
+
const app = fastify()
|
|
6
|
+
|
|
7
|
+
app.register(import('./plugin.mjs'), { foo: 'bar' })
|
|
8
|
+
app.register(import('./other.mjs'))
|
|
9
|
+
|
|
10
|
+
await app.ready()
|
|
11
|
+
|
|
12
|
+
t.strictEqual(app.foo, 'bar')
|
|
13
|
+
})
|
|
@@ -4,7 +4,8 @@ const t = require('tap')
|
|
|
4
4
|
const test = t.test
|
|
5
5
|
const Fastify = require('..')
|
|
6
6
|
const {
|
|
7
|
-
kOptions
|
|
7
|
+
kOptions,
|
|
8
|
+
kErrorHandler
|
|
8
9
|
} = require('../lib/symbols')
|
|
9
10
|
|
|
10
11
|
test('root fastify instance is an object', t => {
|
|
@@ -65,3 +66,34 @@ test('fastify instance get invalid ajv options.plugins', t => {
|
|
|
65
66
|
}
|
|
66
67
|
}))
|
|
67
68
|
})
|
|
69
|
+
|
|
70
|
+
test('fastify instance should contain default errorHandler', t => {
|
|
71
|
+
t.plan(3)
|
|
72
|
+
const fastify = Fastify()
|
|
73
|
+
t.ok(fastify[kErrorHandler] instanceof Function)
|
|
74
|
+
t.same(fastify.errorHandler, fastify[kErrorHandler])
|
|
75
|
+
t.same(Object.getOwnPropertyDescriptor(fastify, 'errorHandler').set, undefined)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
test('errorHandler in plugin should be separate from the external one', async t => {
|
|
79
|
+
t.plan(4)
|
|
80
|
+
const fastify = Fastify()
|
|
81
|
+
|
|
82
|
+
fastify.register((instance, opts, next) => {
|
|
83
|
+
const inPluginErrHandler = (_, __, reply) => {
|
|
84
|
+
reply.send({ plugin: 'error-object' })
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
instance.setErrorHandler(inPluginErrHandler)
|
|
88
|
+
|
|
89
|
+
t.notSame(instance.errorHandler, fastify.errorHandler)
|
|
90
|
+
t.equal(instance.errorHandler.name, 'bound inPluginErrHandler')
|
|
91
|
+
|
|
92
|
+
next()
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
await fastify.ready()
|
|
96
|
+
|
|
97
|
+
t.ok(fastify[kErrorHandler] instanceof Function)
|
|
98
|
+
t.same(fastify.errorHandler, fastify[kErrorHandler])
|
|
99
|
+
})
|
|
@@ -25,6 +25,9 @@ try {
|
|
|
25
25
|
fastify.get('/', function (req, reply) {
|
|
26
26
|
reply.code(200).send(msg)
|
|
27
27
|
})
|
|
28
|
+
fastify.get('/proto', function (req, reply) {
|
|
29
|
+
reply.code(200).send({ proto: req.protocol })
|
|
30
|
+
})
|
|
28
31
|
|
|
29
32
|
fastify.listen(0, err => {
|
|
30
33
|
t.error(err)
|
|
@@ -40,4 +43,12 @@ fastify.listen(0, err => {
|
|
|
40
43
|
t.strictEqual(res.headers['content-length'], '' + JSON.stringify(msg).length)
|
|
41
44
|
t.deepEqual(JSON.parse(res.body), msg)
|
|
42
45
|
})
|
|
46
|
+
|
|
47
|
+
test('https get request without trust proxy - protocol', async (t) => {
|
|
48
|
+
t.plan(2)
|
|
49
|
+
|
|
50
|
+
const url = `https://localhost:${fastify.server.address().port}/proto`
|
|
51
|
+
t.deepEqual(JSON.parse((await h2url.concat({ url })).body), { proto: 'https' })
|
|
52
|
+
t.deepEqual(JSON.parse((await h2url.concat({ url, headers: { 'X-Forwarded-Proto': 'lorem' } })).body), { proto: 'https' })
|
|
53
|
+
})
|
|
43
54
|
})
|
package/test/https/https.test.js
CHANGED
|
@@ -25,6 +25,9 @@ test('https get', t => {
|
|
|
25
25
|
fastify.get('/', function (req, reply) {
|
|
26
26
|
reply.code(200).send({ hello: 'world' })
|
|
27
27
|
})
|
|
28
|
+
fastify.get('/proto', function (req, reply) {
|
|
29
|
+
reply.code(200).send({ proto: req.protocol })
|
|
30
|
+
})
|
|
28
31
|
t.pass()
|
|
29
32
|
} catch (e) {
|
|
30
33
|
t.fail()
|
|
@@ -48,4 +51,27 @@ fastify.listen(0, err => {
|
|
|
48
51
|
t.deepEqual(JSON.parse(body), { hello: 'world' })
|
|
49
52
|
})
|
|
50
53
|
})
|
|
54
|
+
|
|
55
|
+
test('https get request without trust proxy - protocol', t => {
|
|
56
|
+
t.plan(4)
|
|
57
|
+
sget({
|
|
58
|
+
method: 'GET',
|
|
59
|
+
url: 'https://localhost:' + fastify.server.address().port + '/proto',
|
|
60
|
+
rejectUnauthorized: false
|
|
61
|
+
}, (err, response, body) => {
|
|
62
|
+
t.error(err)
|
|
63
|
+
t.deepEqual(JSON.parse(body), { proto: 'https' })
|
|
64
|
+
})
|
|
65
|
+
sget({
|
|
66
|
+
method: 'GET',
|
|
67
|
+
url: 'https://localhost:' + fastify.server.address().port + '/proto',
|
|
68
|
+
rejectUnauthorized: false,
|
|
69
|
+
headers: {
|
|
70
|
+
'x-forwarded-proto': 'lorem'
|
|
71
|
+
}
|
|
72
|
+
}, (err, response, body) => {
|
|
73
|
+
t.error(err)
|
|
74
|
+
t.deepEqual(JSON.parse(body), { proto: 'https' })
|
|
75
|
+
})
|
|
76
|
+
})
|
|
51
77
|
})
|
|
@@ -12,7 +12,7 @@ test('Regular request', t => {
|
|
|
12
12
|
const req = {
|
|
13
13
|
method: 'GET',
|
|
14
14
|
url: '/',
|
|
15
|
-
|
|
15
|
+
socket: { remoteAddress: 'ip' },
|
|
16
16
|
headers
|
|
17
17
|
}
|
|
18
18
|
const request = new Request('id', 'params', req, 'query', 'log')
|
|
@@ -29,7 +29,7 @@ test('Regular request', t => {
|
|
|
29
29
|
t.strictEqual(request.body, null)
|
|
30
30
|
t.strictEqual(request.method, 'GET')
|
|
31
31
|
t.strictEqual(request.url, '/')
|
|
32
|
-
t.deepEqual(request.
|
|
32
|
+
t.deepEqual(request.socket, req.socket)
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
test('Regular request - hostname from authority', t => {
|
|
@@ -40,7 +40,7 @@ test('Regular request - hostname from authority', t => {
|
|
|
40
40
|
const req = {
|
|
41
41
|
method: 'GET',
|
|
42
42
|
url: '/',
|
|
43
|
-
|
|
43
|
+
socket: { remoteAddress: 'ip' },
|
|
44
44
|
headers
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -58,7 +58,7 @@ test('Regular request - host header has precedence over authority', t => {
|
|
|
58
58
|
const req = {
|
|
59
59
|
method: 'GET',
|
|
60
60
|
url: '/',
|
|
61
|
-
|
|
61
|
+
socket: { remoteAddress: 'ip' },
|
|
62
62
|
headers
|
|
63
63
|
}
|
|
64
64
|
const request = new Request('id', 'params', req, 'query', 'log')
|
|
@@ -75,6 +75,9 @@ test('Request with trust proxy', t => {
|
|
|
75
75
|
const req = {
|
|
76
76
|
method: 'GET',
|
|
77
77
|
url: '/',
|
|
78
|
+
// Some dependencies (proxy-addr, forwarded) still depend on the deprecated
|
|
79
|
+
// .connection property, we use .socket. Include both to satisfy everyone.
|
|
80
|
+
socket: { remoteAddress: 'ip' },
|
|
78
81
|
connection: { remoteAddress: 'ip' },
|
|
79
82
|
headers
|
|
80
83
|
}
|
|
@@ -94,7 +97,7 @@ test('Request with trust proxy', t => {
|
|
|
94
97
|
t.strictEqual(request.body, null)
|
|
95
98
|
t.strictEqual(request.method, 'GET')
|
|
96
99
|
t.strictEqual(request.url, '/')
|
|
97
|
-
t.deepEqual(request.
|
|
100
|
+
t.deepEqual(request.socket, req.socket)
|
|
98
101
|
})
|
|
99
102
|
|
|
100
103
|
test('Request with trust proxy - no x-forwarded-host header', t => {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const t = require('tap')
|
|
4
|
+
const test = t.test
|
|
5
|
+
const proxyquire = require('proxyquire')
|
|
6
|
+
|
|
7
|
+
test('should output an undefined version in case of package.json not available', t => {
|
|
8
|
+
const Fastify = proxyquire('../..', { fs: { accessSync: () => { throw Error('error') } } })
|
|
9
|
+
t.plan(1)
|
|
10
|
+
const srv = Fastify()
|
|
11
|
+
t.is(srv.version, undefined)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('should output an undefined version in case of package.json is not the fastify one', t => {
|
|
15
|
+
const Fastify = proxyquire('../..', { fs: { accessSync: () => { }, readFileSync: () => JSON.stringify({ name: 'foo', version: '6.6.6' }) } })
|
|
16
|
+
t.plan(1)
|
|
17
|
+
const srv = Fastify()
|
|
18
|
+
t.is(srv.version, undefined)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('should skip the version check if the version is undefined', t => {
|
|
22
|
+
const Fastify = proxyquire('../..', { fs: { accessSync: () => { }, readFileSync: () => JSON.stringify({ name: 'foo', version: '6.6.6' }) } })
|
|
23
|
+
t.plan(3)
|
|
24
|
+
const srv = Fastify()
|
|
25
|
+
t.is(srv.version, undefined)
|
|
26
|
+
|
|
27
|
+
plugin[Symbol.for('skip-override')] = false
|
|
28
|
+
plugin[Symbol.for('plugin-meta')] = {
|
|
29
|
+
name: 'plugin',
|
|
30
|
+
fastify: '>=99.0.0'
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
srv.register(plugin)
|
|
34
|
+
|
|
35
|
+
srv.ready((err) => {
|
|
36
|
+
t.error(err)
|
|
37
|
+
t.pass('everything right')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
function plugin (instance, opts, next) {
|
|
41
|
+
next()
|
|
42
|
+
}
|
|
43
|
+
})
|
package/test/listen.test.js
CHANGED
|
@@ -351,3 +351,19 @@ test('listen logs the port as info', t => {
|
|
|
351
351
|
t.ok(/http:\/\//.test(msgs[0]))
|
|
352
352
|
})
|
|
353
353
|
})
|
|
354
|
+
|
|
355
|
+
test('listen when firstArg is string(pipe) and without backlog', async t => {
|
|
356
|
+
t.plan(1)
|
|
357
|
+
const fastify = Fastify()
|
|
358
|
+
t.tearDown(fastify.close.bind(fastify))
|
|
359
|
+
const address = await fastify.listen('\\\\.\\pipe\\testPipe')
|
|
360
|
+
t.is(address, '\\\\.\\pipe\\testPipe')
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
test('listen when firstArg is string(pipe) and with backlog', async t => {
|
|
364
|
+
t.plan(1)
|
|
365
|
+
const fastify = Fastify()
|
|
366
|
+
t.tearDown(fastify.close.bind(fastify))
|
|
367
|
+
const address = await fastify.listen('\\\\.\\pipe\\testPipe', 511)
|
|
368
|
+
t.is(address, '\\\\.\\pipe\\testPipe')
|
|
369
|
+
})
|
package/test/logger.test.js
CHANGED
|
@@ -1423,7 +1423,7 @@ test('should redact the authorization header if so specified', t => {
|
|
|
1423
1423
|
headers: req.headers,
|
|
1424
1424
|
hostname: req.hostname,
|
|
1425
1425
|
remoteAddress: req.ip,
|
|
1426
|
-
remotePort: req.
|
|
1426
|
+
remotePort: req.socket.remotePort
|
|
1427
1427
|
}
|
|
1428
1428
|
}
|
|
1429
1429
|
}
|
package/test/plugin.test.js
CHANGED
|
@@ -817,3 +817,111 @@ test('pluginTimeout default', t => {
|
|
|
817
817
|
|
|
818
818
|
t.tearDown(clock.uninstall)
|
|
819
819
|
})
|
|
820
|
+
|
|
821
|
+
test('plugin metadata - version', t => {
|
|
822
|
+
t.plan(1)
|
|
823
|
+
const fastify = Fastify()
|
|
824
|
+
|
|
825
|
+
plugin[Symbol.for('skip-override')] = true
|
|
826
|
+
plugin[Symbol.for('plugin-meta')] = {
|
|
827
|
+
name: 'plugin',
|
|
828
|
+
fastify: '2.0.0'
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
fastify.register(plugin)
|
|
832
|
+
|
|
833
|
+
fastify.ready(() => {
|
|
834
|
+
t.pass('everything right')
|
|
835
|
+
})
|
|
836
|
+
|
|
837
|
+
function plugin (instance, opts, next) {
|
|
838
|
+
next()
|
|
839
|
+
}
|
|
840
|
+
})
|
|
841
|
+
|
|
842
|
+
test('plugin metadata - version range', t => {
|
|
843
|
+
t.plan(1)
|
|
844
|
+
const fastify = Fastify()
|
|
845
|
+
|
|
846
|
+
plugin[Symbol.for('skip-override')] = true
|
|
847
|
+
plugin[Symbol.for('plugin-meta')] = {
|
|
848
|
+
name: 'plugin',
|
|
849
|
+
fastify: '>=2.0.0'
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
fastify.register(plugin)
|
|
853
|
+
|
|
854
|
+
fastify.ready(() => {
|
|
855
|
+
t.pass('everything right')
|
|
856
|
+
})
|
|
857
|
+
|
|
858
|
+
function plugin (instance, opts, next) {
|
|
859
|
+
next()
|
|
860
|
+
}
|
|
861
|
+
})
|
|
862
|
+
|
|
863
|
+
test('plugin metadata - version not matching requirement', t => {
|
|
864
|
+
t.plan(2)
|
|
865
|
+
const fastify = Fastify()
|
|
866
|
+
|
|
867
|
+
plugin[Symbol.for('skip-override')] = true
|
|
868
|
+
plugin[Symbol.for('plugin-meta')] = {
|
|
869
|
+
name: 'plugin',
|
|
870
|
+
fastify: '99.0.0'
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
fastify.register(plugin)
|
|
874
|
+
|
|
875
|
+
fastify.ready((err) => {
|
|
876
|
+
t.ok(err)
|
|
877
|
+
t.equal(err.code, 'FST_ERR_PLUGIN_VERSION_MISMATCH')
|
|
878
|
+
})
|
|
879
|
+
|
|
880
|
+
function plugin (instance, opts, next) {
|
|
881
|
+
next()
|
|
882
|
+
}
|
|
883
|
+
})
|
|
884
|
+
|
|
885
|
+
test('plugin metadata - version not matching requirement 2', t => {
|
|
886
|
+
t.plan(2)
|
|
887
|
+
const fastify = Fastify()
|
|
888
|
+
|
|
889
|
+
plugin[Symbol.for('skip-override')] = true
|
|
890
|
+
plugin[Symbol.for('plugin-meta')] = {
|
|
891
|
+
name: 'plugin',
|
|
892
|
+
fastify: '<=3.0.0'
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
fastify.register(plugin)
|
|
896
|
+
|
|
897
|
+
fastify.ready((err) => {
|
|
898
|
+
t.ok(err)
|
|
899
|
+
t.equal(err.code, 'FST_ERR_PLUGIN_VERSION_MISMATCH')
|
|
900
|
+
})
|
|
901
|
+
|
|
902
|
+
function plugin (instance, opts, next) {
|
|
903
|
+
next()
|
|
904
|
+
}
|
|
905
|
+
})
|
|
906
|
+
|
|
907
|
+
test('plugin metadata - version not matching requirement 3', t => {
|
|
908
|
+
t.plan(2)
|
|
909
|
+
const fastify = Fastify()
|
|
910
|
+
|
|
911
|
+
plugin[Symbol.for('skip-override')] = true
|
|
912
|
+
plugin[Symbol.for('plugin-meta')] = {
|
|
913
|
+
name: 'plugin',
|
|
914
|
+
fastify: '>=99.0.0'
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
fastify.register(plugin)
|
|
918
|
+
|
|
919
|
+
fastify.ready((err) => {
|
|
920
|
+
t.ok(err)
|
|
921
|
+
t.equal(err.code, 'FST_ERR_PLUGIN_VERSION_MISMATCH')
|
|
922
|
+
})
|
|
923
|
+
|
|
924
|
+
function plugin (instance, opts, next) {
|
|
925
|
+
next()
|
|
926
|
+
}
|
|
927
|
+
})
|