Skip to content

Commit 540d187

Browse files
committed
fix(http-request): prevent Content-Type header for empty string body
Fix critical bug where empty string body incorrectly triggered Content-Type header to be set. Bug Details: - Changed condition from `if (body !== undefined)` to `if (body)` - Empty string "" is !== undefined (true) but is falsy - Sending Content-Type with empty body is semantically incorrect - Could break APIs that treat empty bodies differently Affected Functions: - httpJson(): Line 1011 (now uses truthiness check) - httpText(): Line 1185 (now uses truthiness check) Test Coverage: - Added test: should not set Content-Type when body is empty string (httpJson) - Added test: should not set Content-Type when body is empty string (httpText) - Total tests: 69 (up from 67) Impact: High - Affects POST/PUT/PATCH requests with empty string bodies Closes critical issue identified in code review.
1 parent dc46e82 commit 540d187

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

src/http-request.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,7 +1008,7 @@ export async function httpJson<T = unknown>(
10081008
}
10091009

10101010
// Add Content-Type when body is present
1011-
if (body !== undefined) {
1011+
if (body) {
10121012
defaultHeaders['Content-Type'] = 'application/json'
10131013
}
10141014

@@ -1182,7 +1182,7 @@ export async function httpText(
11821182
}
11831183

11841184
// Add Content-Type when body is present
1185-
if (body !== undefined) {
1185+
if (body) {
11861186
defaultHeaders['Content-Type'] = 'text/plain'
11871187
}
11881188

test/unit/http-request.test.mts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,37 @@ describe('http-request', () => {
988988
}
989989
})
990990

991+
it('should not set Content-Type when body is empty string', async () => {
992+
const testServer = http.createServer((req, res) => {
993+
res.writeHead(200, { 'Content-Type': 'application/json' })
994+
res.end(
995+
JSON.stringify({ contentType: req.headers['content-type'] || null }),
996+
)
997+
})
998+
999+
await new Promise<void>(resolve => {
1000+
testServer.listen(0, () => resolve())
1001+
})
1002+
1003+
const address = testServer.address()
1004+
const testPort = address && typeof address === 'object' ? address.port : 0
1005+
1006+
try {
1007+
const data = await httpJson<{ contentType: string | null }>(
1008+
`http://localhost:${testPort}/`,
1009+
{
1010+
method: 'POST',
1011+
body: '',
1012+
},
1013+
)
1014+
expect(data.contentType).toBeNull()
1015+
} finally {
1016+
await new Promise<void>(resolve => {
1017+
testServer.close(() => resolve())
1018+
})
1019+
}
1020+
})
1021+
9911022
it('should allow overriding default headers', async () => {
9921023
const testServer = http.createServer((req, res) => {
9931024
res.writeHead(200, { 'Content-Type': 'application/json' })
@@ -1169,6 +1200,32 @@ describe('http-request', () => {
11691200
}
11701201
})
11711202

1203+
it('should not set Content-Type when body is empty string', async () => {
1204+
const testServer = http.createServer((req, res) => {
1205+
res.writeHead(200, { 'Content-Type': 'text/plain' })
1206+
res.end(req.headers['content-type'] || 'no-content-type')
1207+
})
1208+
1209+
await new Promise<void>(resolve => {
1210+
testServer.listen(0, () => resolve())
1211+
})
1212+
1213+
const address = testServer.address()
1214+
const testPort = address && typeof address === 'object' ? address.port : 0
1215+
1216+
try {
1217+
const text = await httpText(`http://localhost:${testPort}/`, {
1218+
method: 'POST',
1219+
body: '',
1220+
})
1221+
expect(text).toBe('no-content-type')
1222+
} finally {
1223+
await new Promise<void>(resolve => {
1224+
testServer.close(() => resolve())
1225+
})
1226+
}
1227+
})
1228+
11721229
it('should allow overriding default headers', async () => {
11731230
const testServer = http.createServer((req, res) => {
11741231
res.writeHead(200, { 'Content-Type': 'text/plain' })

0 commit comments

Comments
 (0)