Skip to content

Commit 4723c1b

Browse files
climba03003Uzlopak
andauthored
fix: content-type mis-handling for invalid non-essence content-type (fastify#4509)
* fix: content-type mis-handling for invalid non-essence content-type * Update lib/contentTypeParser.js Co-authored-by: Uzlopak <aras.abbasi@googlemail.com> * fixup: empty string and semicolon edge case * test: add edge case * chore: update comment * test: remove duplicate test --------- Co-authored-by: Uzlopak <aras.abbasi@googlemail.com>
1 parent 6b5957d commit 4723c1b

File tree

2 files changed

+111
-2
lines changed

2 files changed

+111
-2
lines changed

lib/contentTypeParser.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,10 +396,18 @@ function ParserListItem (contentType) {
396396
// we pre-calculate all the needed information
397397
// before content-type comparsion
398398
const parsed = safeParseContentType(contentType)
399-
this.type = parsed.type
399+
this.isEssence = contentType.indexOf(';') === -1
400+
// we should not allow empty string for parser list item
401+
// because it would become a match-all handler
402+
if (this.isEssence === false && parsed.type === '') {
403+
// handle semicolon or empty string
404+
const tmp = contentType.split(';')[0]
405+
this.type = tmp === '' ? contentType : tmp
406+
} else {
407+
this.type = parsed.type
408+
}
400409
this.parameters = parsed.parameters
401410
this.parameterKeys = Object.keys(parsed.parameters)
402-
this.isEssence = contentType.indexOf(';') === -1
403411
}
404412

405413
// used in ContentTypeParser.remove

test/content-parser.test.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,3 +649,104 @@ test('content-type regexp list should be cloned when plugin override', async t =
649649
t.same(payload, 'png')
650650
}
651651
})
652+
653+
test('allow partial content-type - essence check', async t => {
654+
t.plan(1)
655+
656+
const fastify = Fastify()
657+
fastify.removeAllContentTypeParsers()
658+
fastify.addContentTypeParser('json', function (request, body, done) {
659+
t.pass('should be called')
660+
done(null, body)
661+
})
662+
663+
fastify.post('/', async () => {
664+
return 'ok'
665+
})
666+
667+
await fastify.inject({
668+
method: 'POST',
669+
path: '/',
670+
headers: {
671+
'content-type': 'application/json; foo=bar; charset=utf8'
672+
},
673+
body: ''
674+
})
675+
676+
await fastify.inject({
677+
method: 'POST',
678+
path: '/',
679+
headers: {
680+
'content-type': 'image/jpeg'
681+
},
682+
body: ''
683+
})
684+
})
685+
686+
test('allow partial content-type - not essence check', async t => {
687+
t.plan(1)
688+
689+
const fastify = Fastify()
690+
fastify.removeAllContentTypeParsers()
691+
fastify.addContentTypeParser('json;', function (request, body, done) {
692+
t.pass('should be called')
693+
done(null, body)
694+
})
695+
696+
fastify.post('/', async () => {
697+
return 'ok'
698+
})
699+
700+
await fastify.inject({
701+
method: 'POST',
702+
path: '/',
703+
headers: {
704+
'content-type': 'application/json; foo=bar; charset=utf8'
705+
},
706+
body: ''
707+
})
708+
709+
await fastify.inject({
710+
method: 'POST',
711+
path: '/',
712+
headers: {
713+
'content-type': 'image/jpeg'
714+
},
715+
body: ''
716+
})
717+
})
718+
719+
test('edge case content-type - ;', async t => {
720+
t.plan(1)
721+
722+
const fastify = Fastify()
723+
fastify.removeAllContentTypeParsers()
724+
fastify.addContentTypeParser(';', function (request, body, done) {
725+
t.fail('should not be called')
726+
done(null, body)
727+
})
728+
729+
fastify.post('/', async () => {
730+
return 'ok'
731+
})
732+
733+
await fastify.inject({
734+
method: 'POST',
735+
path: '/',
736+
headers: {
737+
'content-type': 'application/json; foo=bar; charset=utf8'
738+
},
739+
body: ''
740+
})
741+
742+
await fastify.inject({
743+
method: 'POST',
744+
path: '/',
745+
headers: {
746+
'content-type': 'image/jpeg'
747+
},
748+
body: ''
749+
})
750+
751+
t.pass('end')
752+
})

0 commit comments

Comments
 (0)