Skip to content

Commit b0e255a

Browse files
authored
fix: OPTIONS Content-Type handling (fastify#6263)
* fix: OPTIONS Content-Type handling * remove unnecessary comment * add more tests * add no content-type test * add more * typo * one test * remove unnecessary test
1 parent 0d71821 commit b0e255a

File tree

2 files changed

+42
-22
lines changed

2 files changed

+42
-22
lines changed

lib/handleRequest.js

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,38 +21,34 @@ function handleRequest (err, request, reply) {
2121
return
2222
}
2323

24-
const method = request.raw.method
25-
const headers = request.headers
26-
const context = request[kRouteContext]
24+
const method = request.method
2725

2826
if (this[kSupportedHTTPMethods].bodyless.has(method)) {
2927
handler(request, reply)
3028
return
3129
}
3230

3331
if (this[kSupportedHTTPMethods].bodywith.has(method)) {
32+
const headers = request.headers
3433
const contentType = headers['content-type']
35-
const contentLength = headers['content-length']
36-
const transferEncoding = headers['transfer-encoding']
3734

3835
if (contentType === undefined) {
39-
if (
40-
(contentLength === undefined || contentLength === '0') &&
41-
transferEncoding === undefined
42-
) {
36+
const contentLength = headers['content-length']
37+
const transferEncoding = headers['transfer-encoding']
38+
const isEmptyBody = transferEncoding === undefined &&
39+
(contentLength === undefined || contentLength === '0')
40+
41+
if (isEmptyBody) {
4342
// Request has no body to parse
4443
handler(request, reply)
45-
} else {
46-
context.contentTypeParser.run('', handler, request, reply)
47-
}
48-
} else {
49-
if (contentLength === undefined && transferEncoding === undefined && method === 'OPTIONS') {
50-
// OPTIONS can have a Content-Type header without a body
51-
handler(request, reply)
5244
return
5345
}
54-
context.contentTypeParser.run(contentType, handler, request, reply)
46+
47+
request[kRouteContext].contentTypeParser.run('', handler, request, reply)
48+
return
5549
}
50+
51+
request[kRouteContext].contentTypeParser.run(contentType, handler, request, reply)
5652
return
5753
}
5854

test/internals/handle-request.test.js

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ test('request should be defined in onSend Hook on post request with content type
191191
})
192192

193193
test('request should be defined in onSend Hook on options request with content type application/x-www-form-urlencoded', async t => {
194-
t.plan(5)
194+
t.plan(15)
195195
const fastify = require('../..')()
196196

197197
t.after(() => {
@@ -209,16 +209,40 @@ test('request should be defined in onSend Hook on options request with content t
209209
reply.send(200)
210210
})
211211

212-
const fastifyServer = await fastify.listen({ port: 0 })
213-
const result = await fetch(fastifyServer, {
212+
// Test 1: OPTIONS with body and content-type header
213+
const result1 = await fastify.inject({
214+
method: 'OPTIONS',
215+
url: '/',
216+
body: 'first-name=OPTIONS&last-name=METHOD',
217+
headers: {
218+
'content-type': 'application/x-www-form-urlencoded'
219+
}
220+
})
221+
222+
// Content-Type is not supported
223+
t.assert.strictEqual(result1.statusCode, 415)
224+
225+
// Test 2: OPTIONS with content-type header only (no body)
226+
const result2 = await fastify.inject({
214227
method: 'OPTIONS',
228+
url: '/',
215229
headers: {
216230
'content-type': 'application/x-www-form-urlencoded'
217231
}
218232
})
219233

220-
// Body parsing skipped, so no body sent
221-
t.assert.strictEqual(result.status, 200)
234+
// Content-Type is not supported
235+
t.assert.strictEqual(result2.statusCode, 415)
236+
237+
// Test 3: OPTIONS with body but no content-type header
238+
const result3 = await fastify.inject({
239+
method: 'OPTIONS',
240+
url: '/',
241+
body: 'first-name=OPTIONS&last-name=METHOD'
242+
})
243+
244+
// No content-type with payload
245+
t.assert.strictEqual(result3.statusCode, 415)
222246
})
223247

224248
test('request should respond with an error if an unserialized payload is sent inside an async handler', async t => {

0 commit comments

Comments
 (0)