Skip to content

Commit d68aec9

Browse files
authoredJul 2, 2024··
fix: use destination path for Content-Type header (#121)
1 parent 1898445 commit d68aec9

File tree

5 files changed

+101
-52
lines changed

5 files changed

+101
-52
lines changed
 

‎.changeset/swift-dingos-compare.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"vite-plugin-static-copy": patch
3+
---
4+
5+
The value of `Content-Type` header was inferred and set from the src file extension. It is now infered from the dest file extension.

‎src/middleware.ts

+11-28
Original file line numberDiff line numberDiff line change
@@ -108,40 +108,27 @@ function viaLocal(
108108
return undefined
109109
}
110110

111-
function getStaticHeaders(name: string, stats: Stats) {
112-
let ctype = lookup(name) || ''
113-
if (ctype === 'text/html') ctype += ';charset=utf-8'
114-
115-
const headers: OutgoingHttpHeaders = {
111+
function getStaticHeaders(stats: Stats): OutgoingHttpHeaders {
112+
return {
116113
'Content-Length': stats.size,
117-
'Content-Type': ctype,
118114
'Last-Modified': stats.mtime.toUTCString(),
119115
ETag: `W/"${stats.size}-${stats.mtime.getTime()}"`,
120116
'Cache-Control': 'no-cache'
121117
}
122-
123-
return headers
124118
}
125119

126120
function getTransformHeaders(
127-
name: string,
128121
encoding: BufferEncoding | 'buffer',
129122
content: string | Buffer
130-
) {
131-
let ctype = lookup(name) || ''
132-
if (ctype === 'text/html') ctype += ';charset=utf-8'
133-
134-
const headers: OutgoingHttpHeaders = {
123+
): OutgoingHttpHeaders {
124+
return {
135125
'Content-Length': Buffer.byteLength(
136126
content,
137127
encoding === 'buffer' ? undefined : encoding
138128
),
139-
'Content-Type': ctype,
140129
ETag: `W/"${calculateMd5Base64(content)}"`,
141130
'Cache-Control': 'no-cache'
142131
}
143-
144-
return headers
145132
}
146133

147134
function getMergeHeaders(headers: OutgoingHttpHeaders, res: ServerResponse) {
@@ -165,7 +152,7 @@ function sendStatic(
165152
file: string,
166153
stats: Stats
167154
) {
168-
const staticHeaders = getStaticHeaders(file, stats)
155+
const staticHeaders = getStaticHeaders(stats)
169156

170157
if (req.headers['if-none-match'] === staticHeaders['ETag']) {
171158
res.writeHead(304)
@@ -208,12 +195,10 @@ function sendStatic(
208195
function sendTransform(
209196
req: IncomingMessage,
210197
res: ServerResponse,
211-
file: string,
212198
transform: TransformOptionObject,
213199
transformedContent: string | Buffer
214200
): void {
215201
const transformHeaders = getTransformHeaders(
216-
file,
217202
transform.encoding,
218203
transformedContent
219204
)
@@ -243,7 +228,11 @@ function setHeaders(
243228
// these files to be TypeScript files, and for Vite to serve them with
244229
// this Content-Type.
245230
if (/\.[tj]sx?$/.test(pathname)) {
246-
res.setHeader('Content-Type', 'application/javascript')
231+
res.setHeader('Content-Type', 'text/javascript')
232+
} else {
233+
let ctype = lookup(pathname) || ''
234+
if (ctype === 'text/html') ctype += ';charset=utf-8'
235+
res.setHeader('Content-Type', ctype)
247236
}
248237

249238
if (headers) {
@@ -300,13 +289,7 @@ export function serveStaticCopyMiddleware(
300289
}
301290

302291
setHeaders(res, pathname, server.headers)
303-
sendTransform(
304-
req,
305-
res,
306-
data.filepath,
307-
transformOption,
308-
transformedContent
309-
)
292+
sendTransform(req, res, transformOption, transformedContent)
310293
return
311294
}
312295

‎test/fixtures/vite.config.ts

+24
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,30 @@ export default defineConfig({
111111
transform(content) {
112112
return content + '1'
113113
}
114+
},
115+
{
116+
src: 'foo.js',
117+
dest: 'fixture12',
118+
rename: filename => {
119+
return `${filename}.txt`
120+
}
121+
},
122+
{
123+
src: 'foo.txt',
124+
dest: 'fixture12',
125+
transform(content) {
126+
return JSON.stringify({ value: content.trim() })
127+
},
128+
rename: filename => {
129+
return `${filename}.json`
130+
}
131+
},
132+
{
133+
src: 'foo.txt',
134+
dest: 'fixture12',
135+
rename: filename => {
136+
return `${filename}.foo`
137+
}
114138
}
115139
]
116140
})

‎test/testcases.ts

+20
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ type Testcase = {
44
dest: string
55
transformedContent?: string
66
encoding?: BufferEncoding | 'buffer'
7+
contentType?: string
78
}
89

910
export const testcases: Record<string, Testcase[]> = {
@@ -115,6 +116,25 @@ export const testcases: Record<string, Testcase[]> = {
115116
name: 'overwrite=false with transform',
116117
src: './public/fixture11/notOverwriteDir/bar.txt',
117118
dest: '/fixture11/notOverwriteDir/bar.txt'
119+
},
120+
{
121+
name: 'modified extension, known content-type',
122+
src: 'foo.js',
123+
dest: '/fixture12/foo.txt',
124+
contentType: 'text/plain'
125+
},
126+
{
127+
name: 'modified extension, transformed, known content-type',
128+
src: null,
129+
dest: '/fixture12/foo.json',
130+
transformedContent: '{"value":"foo"}',
131+
contentType: 'application/json'
132+
},
133+
{
134+
name: 'modified extension, unknown content-type',
135+
src: 'foo.txt',
136+
dest: '/fixture12/foo.foo',
137+
contentType: ''
118138
}
119139
],
120140
'vite.absolute.config.ts': [

‎test/tests.test.ts

+41-24
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,23 @@ const fetchFromServer = async (
1616
return res
1717
}
1818

19-
const fetchTextContent = async (
19+
const fetchContent = async (
2020
server: ViteDevServer | PreviewServer,
21-
path: string
21+
path: string,
22+
encoding?: BufferEncoding | 'buffer'
2223
) => {
2324
const res = await fetchFromServer(server, path)
24-
const content = res.status === 200 ? await res.text() : null
25-
return content ? normalizeLineBreak(content) : null
26-
}
25+
let content: string | ArrayBuffer | null = null
2726

28-
const fetchBufferContent = async (
29-
server: ViteDevServer | PreviewServer,
30-
path: string
31-
) => {
32-
const res = await fetchFromServer(server, path)
33-
const content = res.status === 200 ? await res.arrayBuffer() : null
34-
return content
27+
if (res.status === 200) {
28+
content =
29+
encoding === 'buffer'
30+
? await res.arrayBuffer()
31+
: normalizeLineBreak(await res.text())
32+
}
33+
34+
const contentType = res.headers.get('content-type')
35+
return { content, contentType }
3536
}
3637

3738
describe('serve', () => {
@@ -47,16 +48,24 @@ describe('serve', () => {
4748
await server.close()
4849
})
4950

50-
for (const { name, src, dest, transformedContent, encoding } of tests) {
51+
for (const {
52+
name,
53+
src,
54+
dest,
55+
transformedContent,
56+
encoding,
57+
contentType
58+
} of tests) {
5159
// eslint-disable-next-line vitest/valid-title
5260
test.concurrent(name, async () => {
5361
const expected =
5462
src === null ? null : await loadFileContent(src, encoding)
55-
const actual =
56-
encoding === 'buffer'
57-
? await fetchBufferContent(server, dest)
58-
: await fetchTextContent(server, dest)
59-
expect(actual).toStrictEqual(transformedContent ?? expected)
63+
const actual = await fetchContent(server, dest, encoding)
64+
expect(actual.content).toStrictEqual(transformedContent ?? expected)
65+
66+
if (contentType !== undefined) {
67+
expect(actual.contentType).toStrictEqual(contentType)
68+
}
6069
})
6170
}
6271
})
@@ -106,16 +115,24 @@ describe('build', () => {
106115
})
107116
})
108117

109-
for (const { name, src, dest, transformedContent, encoding } of tests) {
118+
for (const {
119+
name,
120+
src,
121+
dest,
122+
transformedContent,
123+
encoding,
124+
contentType
125+
} of tests) {
110126
// eslint-disable-next-line vitest/valid-title
111127
test.concurrent(name, async () => {
112128
const expected =
113129
src === null ? null : await loadFileContent(src, encoding)
114-
const actual =
115-
encoding === 'buffer'
116-
? await fetchBufferContent(server, dest)
117-
: await fetchTextContent(server, dest)
118-
expect(actual).toStrictEqual(transformedContent ?? expected)
130+
const actual = await fetchContent(server, dest, encoding)
131+
expect(actual.content).toStrictEqual(transformedContent ?? expected)
132+
133+
if (contentType !== undefined) {
134+
expect(actual.contentType).toStrictEqual(contentType)
135+
}
119136
})
120137
}
121138
})

0 commit comments

Comments
 (0)
Please sign in to comment.