Skip to content

Commit 23d04fc

Browse files
sapphi-redCopilot
andauthored
fix: respond with correct headers and status code for HEAD requests (vitejs#20421)
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
1 parent ead2dec commit 23d04fc

File tree

4 files changed

+39
-4
lines changed

4 files changed

+39
-4
lines changed

packages/vite/src/node/server/middlewares/transform.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,10 @@ export function transformMiddleware(
120120
return async function viteTransformMiddleware(req, res, next) {
121121
const environment = server.environments.client
122122

123-
if (req.method !== 'GET' || knownIgnoreList.has(req.url!)) {
123+
if (
124+
(req.method !== 'GET' && req.method !== 'HEAD') ||
125+
knownIgnoreList.has(req.url!)
126+
) {
124127
return next()
125128
}
126129

packages/vite/src/node/server/send.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ export function send(
9292
}
9393

9494
res.statusCode = 200
95-
res.end(content)
95+
if (req.method === 'HEAD') {
96+
res.end()
97+
} else {
98+
res.end(content)
99+
}
96100
return
97101
}

playground/resolve/__tests__/resolve.spec.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import fs from 'node:fs'
22
import path from 'node:path'
33
import { fileURLToPath } from 'node:url'
4-
import { expect, test } from 'vitest'
5-
import { isBuild, isWindows, page, testDir, viteTestUrl } from '~utils'
4+
import { describe, expect, test } from 'vitest'
5+
import { isBuild, isServe, isWindows, page, testDir, viteTestUrl } from '~utils'
66

77
test('bom import', async () => {
88
expect(await page.textContent('.utf8-bom')).toMatch('[success]')
@@ -263,3 +263,26 @@ test.runIf(isBuild)('sideEffects field glob pattern is respected', async () => {
263263
)
264264
expect(sideEffectValues).toStrictEqual(['success'])
265265
})
266+
267+
describe.runIf(isServe)('HEAD request handling', () => {
268+
test('HEAD request to JS file returns correct Content-Type', async () => {
269+
const response = await fetch(new URL('/absolute.js', viteTestUrl), {
270+
method: 'HEAD',
271+
})
272+
expect(response.headers.get('content-type')).toBe('text/javascript')
273+
expect(response.status).toBe(200)
274+
const text = await response.text()
275+
expect(text).toBe('')
276+
})
277+
278+
test('HEAD request to CSS file returns correct Content-Type', async () => {
279+
const response = await fetch(new URL('/style.css', viteTestUrl), {
280+
method: 'HEAD',
281+
headers: {
282+
Accept: 'text/css',
283+
},
284+
})
285+
expect(response.headers.get('content-type')).toBe('text/css')
286+
expect(response.status).toBe(200)
287+
})
288+
})

playground/resolve/style.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/* Simple CSS for HEAD request testing */
2+
body {
3+
margin: 0;
4+
padding: 0;
5+
}

0 commit comments

Comments
 (0)