diff --git a/packages/sirv/index.js b/packages/sirv/index.js index 07ecd6d..67bd7b0 100644 --- a/packages/sirv/index.js +++ b/packages/sirv/index.js @@ -88,20 +88,26 @@ function send(req, res, file, stats, headers) { fs.createReadStream(file, opts).pipe(res); } -function isEncoding(name, type, headers) { - headers['Content-Encoding'] = type; - headers['Content-Type'] = mime.getType(name.replace(/\.([^.]*)$/, '')) || ''; -} +const ENCODING = { + '.br': 'br', + '.gz': 'gzip', +}; function toHeaders(name, stats, isEtag) { + let enc = ENCODING[name.slice(-3)]; + + let ctype = mime.getType(name.slice(0, enc && -3)) || ''; + if (ctype === 'text/html') ctype += ';charset=utf-8'; + let headers = { 'Content-Length': stats.size, - 'Content-Type': mime.getType(name) || '', + 'Content-Type': ctype, 'Last-Modified': stats.mtime.toUTCString(), }; + + if (enc) headers['Content-Encoding'] = enc; if (isEtag) headers['ETag'] = `W/"${stats.size}-${stats.mtime.getTime()}"`; - if (/\.br$/.test(name)) isEncoding(name, 'br', headers); - if (/\.gz$/.test(name)) isEncoding(name, 'gzip', headers); + return headers; } diff --git a/tests/helpers.js b/tests/helpers.js index 2c10b31..0dea485 100644 --- a/tests/helpers.js +++ b/tests/helpers.js @@ -76,10 +76,14 @@ export async function lookup(filepath, enc) { let full = join(www, filepath); let stats = await statfile(full); filedata = await readfile(full, enc); + + let ctype = mime.getType(full) || ''; + if (ctype === 'text/html') ctype += ';charset=utf-8'; + return CACHE[filepath] = { data: filedata, size: stats.size, - type: mime.getType(full) || '', + type: ctype, mtime: stats.mtime.getTime(), }; } diff --git a/tests/sirv.js b/tests/sirv.js index 20fa567..9aa4597 100644 --- a/tests/sirv.js +++ b/tests/sirv.js @@ -733,7 +733,7 @@ brotli('should serve prepared `.br` file of any asset, if found', async () => { try { let res1 = await server.send('GET', '/', { headers }); - assert.is(res1.headers['content-type'], 'text/html'); + assert.is(res1.headers['content-type'], 'text/html;charset=utf-8'); assert.is(res1.headers['content-encoding'], 'br'); assert.is(res1.data, 'brotli html\n'); assert.is(res1.statusCode, 200); @@ -751,7 +751,7 @@ brotli('should be preferred when "Accept-Encoding" allows both', async () => { try { let res1 = await server.send('GET', '/', { headers }); - assert.is(res1.headers['content-type'], 'text/html'); + assert.is(res1.headers['content-type'], 'text/html;charset=utf-8'); assert.is(res1.headers['content-encoding'], 'br'); assert.is(res1.data, 'brotli html\n'); assert.is(res1.statusCode, 200); @@ -798,7 +798,7 @@ gzip('should serve prepared `.gz` file of any asset, if found', async () => { try { let res1 = await server.send('GET', '/', { headers }); - assert.is(res1.headers['content-type'], 'text/html'); + assert.is(res1.headers['content-type'], 'text/html;charset=utf-8'); assert.is(res1.headers['content-encoding'], 'gzip'); assert.is(res1.data, 'gzip html\n'); assert.is(res1.statusCode, 200); @@ -816,7 +816,7 @@ gzip('should defer to brotli when "Accept-Encoding" allows both', async () => { try { let res1 = await server.send('GET', '/', { headers }); - assert.is(res1.headers['content-type'], 'text/html'); + assert.is(res1.headers['content-type'], 'text/html;charset=utf-8'); assert.is(res1.headers['content-encoding'], 'br'); assert.is(res1.data, 'brotli html\n'); assert.is(res1.statusCode, 200);