Skip to content

Commit

Permalink
fix(sirv): append charset=utf-8 to HTML content-type (#122)
Browse files Browse the repository at this point in the history
* fix: append charset=utf-8 to text/html

Closes #106

I considered fixing this upstream in "mime" or "mime-db" packages,
but then I came across these issues, which indicated that it was
not a viable path.

broofa/mime#174
jshttp/mime-db#94

* test: check for charset=utf-8 in .html requests

* fix(test): prevent undefined `full` access

* chore: add `charset=utf-8` to test expectants

* chore: light code style/spacing

Co-authored-by: Luke Edwards <luke.edwards05@gmail.com>
  • Loading branch information
aleclarson and lukeed authored Oct 15, 2021
1 parent 881c4c7 commit d1b8ba6
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 12 deletions.
20 changes: 13 additions & 7 deletions packages/sirv/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
6 changes: 5 additions & 1 deletion tests/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
};
}
Expand Down
8 changes: 4 additions & 4 deletions tests/sirv.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit d1b8ba6

Please sign in to comment.