fastify 4.29.0 → 4.29.1

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/fastify.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const VERSION = '4.29.0'
3
+ const VERSION = '4.29.1'
4
4
 
5
5
  const Avvio = require('avvio')
6
6
  const http = require('node:http')
package/lib/validation.js CHANGED
@@ -155,7 +155,7 @@ function validate (context, request, execution) {
155
155
  validatorFunction = context[bodySchema]
156
156
  } else if (context[bodySchema]) {
157
157
  // TODO: add request.contentType and reuse it here
158
- const contentType = request.headers['content-type']?.split(';', 1)[0]
158
+ const contentType = getEssenceMediaType(request.headers['content-type'])
159
159
  const contentSchema = context[bodySchema][contentType]
160
160
  if (contentSchema) {
161
161
  validatorFunction = contentSchema
@@ -254,6 +254,16 @@ function wrapValidationError (result, dataVar, schemaErrorFormatter) {
254
254
  return error
255
255
  }
256
256
 
257
+ /**
258
+ * simple function to retrieve the essence media type
259
+ * @param {string} header
260
+ * @returns {string} Mimetype string.
261
+ */
262
+ function getEssenceMediaType (header) {
263
+ if (!header) return ''
264
+ return header.split(/[ ;]/, 1)[0].trim().toLowerCase()
265
+ }
266
+
257
267
  module.exports = {
258
268
  symbols: { bodySchema, querystringSchema, responseSchema, paramsSchema, headersSchema },
259
269
  compileSchemasForValidation,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastify",
3
- "version": "4.29.0",
3
+ "version": "4.29.1",
4
4
  "description": "Fast and low overhead web framework, for Node.js",
5
5
  "main": "fastify.js",
6
6
  "type": "commonjs",
@@ -2,6 +2,7 @@
2
2
 
3
3
  const { test } = require('tap')
4
4
  const Fastify = require('..')
5
+ const { request, Agent } = require('undici')
5
6
 
6
7
  const AJV = require('ajv')
7
8
  const Schema = require('fluent-json-schema')
@@ -1285,3 +1286,144 @@ test('Custom validator builder override by custom validator compiler in child in
1285
1286
  })
1286
1287
  t.equal(two.statusCode, 200)
1287
1288
  })
1289
+
1290
+ test('Schema validation when no content type is provided', async t => {
1291
+ // this case should not be happened in normal use-case,
1292
+ // it is added for the completeness of code branch
1293
+ const fastify = Fastify()
1294
+
1295
+ fastify.post('/', {
1296
+ schema: {
1297
+ body: {
1298
+ content: {
1299
+ 'application/json': {
1300
+ schema: {
1301
+ type: 'object',
1302
+ properties: {
1303
+ foo: { type: 'string' }
1304
+ },
1305
+ required: ['foo'],
1306
+ additionalProperties: false
1307
+ }
1308
+ }
1309
+ }
1310
+ }
1311
+ },
1312
+ preValidation: async (request) => {
1313
+ request.headers['content-type'] = undefined
1314
+ }
1315
+ }, async () => 'ok')
1316
+
1317
+ await fastify.ready()
1318
+
1319
+ const invalid = await fastify.inject({
1320
+ method: 'POST',
1321
+ url: '/',
1322
+ headers: {
1323
+ 'content-type': 'application/json'
1324
+ },
1325
+ body: { invalid: 'string' }
1326
+ })
1327
+ t.equal(invalid.statusCode, 200)
1328
+ })
1329
+
1330
+ test('Schema validation will not be bypass by different content type', async t => {
1331
+ t.plan(10)
1332
+
1333
+ const fastify = Fastify()
1334
+
1335
+ fastify.post('/', {
1336
+ schema: {
1337
+ body: {
1338
+ content: {
1339
+ 'application/json': {
1340
+ schema: {
1341
+ type: 'object',
1342
+ properties: {
1343
+ foo: { type: 'string' }
1344
+ },
1345
+ required: ['foo'],
1346
+ additionalProperties: false
1347
+ }
1348
+ }
1349
+ }
1350
+ }
1351
+ }
1352
+ }, async () => 'ok')
1353
+
1354
+ await fastify.listen({ port: 0 })
1355
+ t.teardown(() => fastify.close())
1356
+ const address = fastify.listeningOrigin
1357
+
1358
+ const correct1 = await request(address, {
1359
+ dispatcher: new Agent({ pipelining: 0 }),
1360
+ method: 'POST',
1361
+ url: '/',
1362
+ headers: {
1363
+ 'content-type': 'application/json'
1364
+ },
1365
+ body: JSON.stringify({ foo: 'string' })
1366
+ })
1367
+ t.equal(correct1.statusCode, 200)
1368
+ await correct1.body.dump()
1369
+
1370
+ const correct2 = await request(address, {
1371
+ dispatcher: new Agent({ pipelining: 0 }),
1372
+ method: 'POST',
1373
+ url: '/',
1374
+ headers: {
1375
+ 'content-type': 'application/json; charset=utf-8'
1376
+ },
1377
+ body: JSON.stringify({ foo: 'string' })
1378
+ })
1379
+ t.equal(correct2.statusCode, 200)
1380
+ await correct2.body.dump()
1381
+
1382
+ const invalid1 = await request(address, {
1383
+ dispatcher: new Agent({ pipelining: 0 }),
1384
+ method: 'POST',
1385
+ url: '/',
1386
+ headers: {
1387
+ 'content-type': 'application/json ;'
1388
+ },
1389
+ body: JSON.stringify({ invalid: 'string' })
1390
+ })
1391
+ t.equal(invalid1.statusCode, 415)
1392
+ t.equal((await invalid1.body.json()).code, 'FST_ERR_CTP_INVALID_MEDIA_TYPE')
1393
+
1394
+ const invalid2 = await request(address, {
1395
+ dispatcher: new Agent({ pipelining: 0 }),
1396
+ method: 'POST',
1397
+ url: '/',
1398
+ headers: {
1399
+ 'content-type': 'ApPlIcAtIoN/JsOn;'
1400
+ },
1401
+ body: JSON.stringify({ invalid: 'string' })
1402
+ })
1403
+ t.equal(invalid2.statusCode, 415)
1404
+ t.equal((await invalid2.body.json()).code, 'FST_ERR_CTP_INVALID_MEDIA_TYPE')
1405
+
1406
+ const invalid3 = await request(address, {
1407
+ dispatcher: new Agent({ pipelining: 0 }),
1408
+ method: 'POST',
1409
+ url: '/',
1410
+ headers: {
1411
+ 'content-type': 'ApPlIcAtIoN/JsOn ;'
1412
+ },
1413
+ body: JSON.stringify({ invalid: 'string' })
1414
+ })
1415
+ t.equal(invalid3.statusCode, 415)
1416
+ t.equal((await invalid3.body.json()).code, 'FST_ERR_CTP_INVALID_MEDIA_TYPE')
1417
+
1418
+ const invalid4 = await request(address, {
1419
+ dispatcher: new Agent({ pipelining: 0 }),
1420
+ method: 'POST',
1421
+ url: '/',
1422
+ headers: {
1423
+ 'content-type': 'ApPlIcAtIoN/JsOn foo;'
1424
+ },
1425
+ body: JSON.stringify({ invalid: 'string' })
1426
+ })
1427
+ t.equal(invalid4.statusCode, 415)
1428
+ t.equal((await invalid4.body.json()).code, 'FST_ERR_CTP_INVALID_MEDIA_TYPE')
1429
+ })