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 +1 -1
- package/lib/validation.js +11 -1
- package/package.json +1 -1
- package/test/schema-validation.test.js +142 -0
package/fastify.js
CHANGED
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']
|
|
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
|
@@ -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
|
+
})
|