From 2ef570412037f16a1b165a5abcaf088554711b46 Mon Sep 17 00:00:00 2001 From: Mathias Bynens Date: Mon, 19 Feb 2018 13:12:08 -0800 Subject: [PATCH 01/10] Update mime to v2.2.0 --- README.md | 4 +--- lib/ecstatic.js | 10 ++++------ package-lock.json | 8 ++++---- package.json | 2 +- test/mime.js | 18 +++++++++--------- 5 files changed, 19 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index c3217c2..95a679a 100644 --- a/README.md +++ b/README.md @@ -236,9 +236,7 @@ Defaults to **application/octet-stream**. ### `--mime-types {filename}` Add new or override one or more mime-types. This affects the HTTP Content-Type -header. Can either be a path to a -[`.types`](http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types) -file or an object hash of type(s). +header. Must be an object hash of type(s). ecstatic({ mimeTypes: { 'mime-type': ['file_extension', 'file_extension'] } }) diff --git a/lib/ecstatic.js b/lib/ecstatic.js index 7827408..534b1b6 100644 --- a/lib/ecstatic.js +++ b/lib/ecstatic.js @@ -118,9 +118,7 @@ module.exports = function createMiddleware(_dir, _options) { } catch (e) { // swallow parse errors, treat this as a string mimetype input } - if (typeof opts.mimeTypes === 'string') { - mime.load(opts.mimeTypes); - } else if (typeof opts.mimeTypes === 'object') { + if (typeof opts.mimeTypes === 'object') { mime.define(opts.mimeTypes); } } @@ -244,7 +242,7 @@ module.exports = function createMiddleware(_dir, _options) { // Do a MIME lookup, fall back to octet-stream and handle gzip // and brotli special case. const defaultType = opts.contentType || 'application/octet-stream'; - let contentType = mime.lookup(file, defaultType); + let contentType = mime.getType(file, defaultType); let charSet; const range = (req.headers && req.headers.range); const lastModified = (new Date(stat.mtime)).toUTCString(); @@ -261,11 +259,11 @@ module.exports = function createMiddleware(_dir, _options) { if (file === gzippedFile) { // is .gz picked up res.setHeader('Content-Encoding', 'gzip'); // strip gz ending and lookup mime type - contentType = mime.lookup(path.basename(file, '.gz'), defaultType); + contentType = mime.getType(path.basename(file, '.gz'), defaultType); } else if (file === brotliFile) { // is .br picked up res.setHeader('Content-Encoding', 'br'); // strip br ending and lookup mime type - contentType = mime.lookup(path.basename(file, '.br'), defaultType); + contentType = mime.getType(path.basename(file, '.br'), defaultType); } if (typeof cacheControl === 'function') { diff --git a/package-lock.json b/package-lock.json index 3e3fe84..ec820d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ecstatic", - "version": "3.3.0", + "version": "3.3.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1543,9 +1543,9 @@ "dev": true }, "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.2.0.tgz", + "integrity": "sha512-0Qz9uF1ATtl8RKJG4VRfOymh7PyEor6NbrI/61lRfuRe4vx9SNATrvAeTj2EWVRKjEQGskrzWkJBBY5NbaVHIA==" }, "mime-db": { "version": "1.33.0", diff --git a/package.json b/package.json index 6007f9f..fbd7801 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ ], "dependencies": { "he": "^1.1.1", - "mime": "^1.6.0", + "mime": "^2.2.0", "minimist": "^1.1.0", "url-join": "^2.0.5" }, diff --git a/test/mime.js b/test/mime.js index 466a8a2..b55b5e8 100644 --- a/test/mime.js +++ b/test/mime.js @@ -6,13 +6,13 @@ const mime = require('mime'); test('mime package lookup', (t) => { t.plan(7); - t.equal(mime.lookup('/path/to/file.css'), 'text/css'); - t.equal(mime.lookup('/path/to/file.js'), 'application/javascript'); - t.equal(mime.lookup('/path/to/file.mjs'), 'application/javascript'); - t.equal(mime.lookup('/path/to/file.txt'), 'text/plain'); - t.equal(mime.lookup('file.txt'), 'text/plain'); - t.equal(mime.lookup('.TXT'), 'text/plain'); - t.equal(mime.lookup('htm'), 'text/html'); + t.equal(mime.getType('/path/to/file.css'), 'text/css'); + t.equal(mime.getType('/path/to/file.js'), 'application/javascript'); + t.equal(mime.getType('/path/to/file.mjs'), 'application/javascript'); + t.equal(mime.getType('/path/to/file.txt'), 'text/plain'); + t.equal(mime.getType('file.txt'), 'text/plain'); + t.equal(mime.getType('.TXT'), 'text/plain'); + t.equal(mime.getType('htm'), 'text/html'); t.end(); }); @@ -23,7 +23,7 @@ test('custom definition of mime-type with the mime package', (t) => { mime.define({ 'application/xml': ['opml'], }); - t.equal(mime.lookup('.opml'), 'application/xml'); + t.equal(mime.getType('.opml'), 'application/xml'); t.end(); }); @@ -38,7 +38,7 @@ test('custom definition of mime-type with a .types file', (t) => { t.end(); } - t.equal(mime.lookup('.opml'), 'application/foo'); // see public/custom_mime_type.types + t.equal(mime.getType('.opml'), 'application/foo'); // see public/custom_mime_type.types t.throws(mime.load.bind(mime, 'public/this_file_does_not_exist.types')); From 635d881df324058eb915152e61ac9a179f17a702 Mon Sep 17 00:00:00 2001 From: Joshua Holbrook Date: Fri, 5 Apr 2019 13:25:18 -0400 Subject: [PATCH 02/10] Tests pass! --- lib/ecstatic.js | 8 ++--- lib/ecstatic/mime.js | 11 ++++++ package-lock.json | 5 +++ package.json | 1 + test/cli.js | 22 ++---------- test/content-type.js | 2 +- test/custom-content-type-file-secret.js | 31 ---------------- test/custom-content-type-file.js | 47 ------------------------- test/custom-content-type.js | 2 +- test/fixtures/custom_mime_type.types | 3 -- test/mime.js | 21 ++--------- test/public/custom_mime_type.types | 3 -- 12 files changed, 28 insertions(+), 128 deletions(-) create mode 100644 lib/ecstatic/mime.js delete mode 100644 test/custom-content-type-file-secret.js delete mode 100644 test/custom-content-type-file.js delete mode 100644 test/fixtures/custom_mime_type.types delete mode 100644 test/public/custom_mime_type.types diff --git a/lib/ecstatic.js b/lib/ecstatic.js index 534b1b6..fa363a1 100644 --- a/lib/ecstatic.js +++ b/lib/ecstatic.js @@ -5,7 +5,7 @@ const path = require('path'); const fs = require('fs'); const url = require('url'); -const mime = require('mime'); +const mime = require('./ecstatic/mime'); const urlJoin = require('url-join'); const showDir = require('./ecstatic/show-dir'); const version = require('../package.json').version; @@ -54,7 +54,7 @@ function shouldCompressBrotli(req) { function hasGzipId12(gzipped, cb) { const stream = fs.createReadStream(gzipped, { start: 0, end: 1 }); - let buffer = Buffer(''); + let buffer = Buffer.from(''); let hasBeenCalled = false; stream.on('data', (chunk) => { @@ -110,7 +110,6 @@ module.exports = function createMiddleware(_dir, _options) { defaultExt = defaultExt.replace(/^\./, ''); } - // Support hashes and .types files in mimeTypes @since 0.8 if (opts.mimeTypes) { try { // You can pass a JSON blob here---useful for CLI use @@ -242,6 +241,7 @@ module.exports = function createMiddleware(_dir, _options) { // Do a MIME lookup, fall back to octet-stream and handle gzip // and brotli special case. const defaultType = opts.contentType || 'application/octet-stream'; + let contentType = mime.getType(file, defaultType); let charSet; const range = (req.headers && req.headers.range); @@ -250,7 +250,7 @@ module.exports = function createMiddleware(_dir, _options) { let cacheControl = cache; let stream = null; if (contentType) { - charSet = mime.charsets.lookup(contentType, 'utf-8'); + charSet = mime.lookupCharset(contentType); if (charSet) { contentType += `; charset=${charSet}`; } diff --git a/lib/ecstatic/mime.js b/lib/ecstatic/mime.js new file mode 100644 index 0000000..2556a1f --- /dev/null +++ b/lib/ecstatic/mime.js @@ -0,0 +1,11 @@ +'use strict'; + +const mime = require('mime'); +const charset = require('charset'); + + +exports.define = mappings => mime.define(mappings, true); + +exports.getType = (file, defaultValue) => mime.getType(file) || defaultValue; + +exports.lookupCharset = contentType => charset(contentType) || 'utf8'; diff --git a/package-lock.json b/package-lock.json index ec820d8..27ee363 100644 --- a/package-lock.json +++ b/package-lock.json @@ -278,6 +278,11 @@ } } }, + "charset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", + "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==" + }, "circular-json": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz", diff --git a/package.json b/package.json index fbd7801..d234d6b 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "middleware" ], "dependencies": { + "charset": "^1.0.1", "he": "^1.1.1", "mime": "^2.2.0", "minimist": "^1.1.0", diff --git a/test/cli.js b/test/cli.js index b58a25e..9f08b68 100644 --- a/test/cli.js +++ b/test/cli.js @@ -82,30 +82,14 @@ test('setting port via cli - custom port', (t) => { }); }); -test('setting mimeTypes via cli - .types file', (t) => { - t.plan(2); - - const port = getRandomPort(); - const root = path.resolve(__dirname, 'public/'); - const pathMimetypeFile = path.resolve(__dirname, 'fixtures/custom_mime_type.types'); - const options = [root, '--port', port, '--mimetypes', pathMimetypeFile]; - const ecstatic = startEcstatic(options); - - tearDown(ecstatic, t); - - ecstatic.stdout.on('data', () => { - t.pass('ecstatic should be started'); - checkServerIsRunning(`${defaultUrl}:${port}/custom_mime_type.opml`, t); - }); -}); - test('setting mimeTypes via cli - directly', (t) => { t.plan(4); const port = getRandomPort(); const root = path.resolve(__dirname, 'public/'); const mimeType = ['--mimeTypes', '{ "application/x-my-type": ["opml"] }']; - const options = [root, '--port', port, '--mimetypes'].concat(mimeType); + const options = [root, '--port', port].concat(mimeType); + const ecstatic = startEcstatic(options); // TODO: remove error handler @@ -115,7 +99,7 @@ test('setting mimeTypes via cli - directly', (t) => { t.pass('ecstatic should be started'); checkServerIsRunning(`${defaultUrl}:${port}/custom_mime_type.opml`, t, (err, res) => { t.error(err); - t.equal(res.headers['content-type'], 'application/x-my-type; charset=utf-8'); + t.equal(res.headers['content-type'], 'application/x-my-type; charset=utf8'); }); }); }); diff --git a/test/content-type.js b/test/content-type.js index d6bffa1..26c5b20 100644 --- a/test/content-type.js +++ b/test/content-type.js @@ -24,7 +24,7 @@ test('default default contentType', (t) => { request.get(`http://localhost:${port}/f_f`, (err, res) => { t.ifError(err); t.equal(res.statusCode, 200); - t.equal(res.headers['content-type'], 'text/plain; charset=UTF-8'); + t.equal(res.headers['content-type'], 'text/plain; charset=utf8'); server.close(() => { t.end(); }); }); }); diff --git a/test/custom-content-type-file-secret.js b/test/custom-content-type-file-secret.js deleted file mode 100644 index a04b912..0000000 --- a/test/custom-content-type-file-secret.js +++ /dev/null @@ -1,31 +0,0 @@ -'use strict'; - -const test = require('tap').test; -const http = require('http'); -const request = require('request'); -const ecstatic = require('../'); - -test('custom contentType via .types file', (t) => { - let server = null; - try { - server = http.createServer(ecstatic({ - root: `${__dirname}/public/`, - mimetypes: `${__dirname}/fixtures/custom_mime_type.types`, - })); - } catch (e) { - t.fail(e.message); - t.end(); - } - - t.plan(3); - - server.listen(0, () => { - const port = server.address().port; - request.get(`http://localhost:${port}/custom_mime_type.opml`, (err, res) => { - t.ifError(err); - t.equal(res.statusCode, 200, 'custom_mime_type.opml should be found'); - t.equal(res.headers['content-type'], 'application/secret; charset=utf-8'); - server.close(() => { t.end(); }); - }); - }); -}); diff --git a/test/custom-content-type-file.js b/test/custom-content-type-file.js deleted file mode 100644 index 95b9392..0000000 --- a/test/custom-content-type-file.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -const test = require('tap').test; -const http = require('http'); -const request = require('request'); -const ecstatic = require('../'); - -function setup(opts) { - return http.createServer(ecstatic(opts)); -} - -test('throws when custom contentType .types file does not exist', (t) => { - t.plan(1); - - t.throws( - setup.bind(null, { - root: `${__dirname}/public/`, - mimeTypes: 'this_file_does_not_exist.types', - }) - ); -}); - -test('custom contentType via .types file', (t) => { - let server = null; - try { - server = setup({ - root: `${__dirname}/public`, - 'mime-types': `${__dirname}/public/custom_mime_type.types`, - }); - } catch (e) { - t.fail(e.message); - t.end(); - } - - t.plan(3); - - server.listen(0, () => { - const port = server.address().port; - - request.get(`http://localhost:${port}/custom_mime_type.opml`, (err, res) => { - t.ifError(err); - t.equal(res.statusCode, 200, 'custom_mime_type.opml should be found'); - t.equal(res.headers['content-type'], 'application/foo; charset=utf-8'); - server.close(() => { t.end(); }); - }); - }); -}); diff --git a/test/custom-content-type.js b/test/custom-content-type.js index 66f2b05..ef12604 100644 --- a/test/custom-content-type.js +++ b/test/custom-content-type.js @@ -26,7 +26,7 @@ test('custom contentType', (t) => { request.get(`http://localhost:${port}/custom_mime_type.opml`, (err, res) => { t.ifError(err); t.equal(res.statusCode, 200, 'custom_mime_type.opml should be found'); - t.equal(res.headers['content-type'], 'application/jon; charset=utf-8'); + t.equal(res.headers['content-type'], 'application/jon; charset=utf8'); server.close(() => { t.end(); }); }); }); diff --git a/test/fixtures/custom_mime_type.types b/test/fixtures/custom_mime_type.types deleted file mode 100644 index 8f68da3..0000000 --- a/test/fixtures/custom_mime_type.types +++ /dev/null @@ -1,3 +0,0 @@ -# This file is an example of the Apache .types file format for describing mime-types. -# Other example: http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types -application/secret opml diff --git a/test/mime.js b/test/mime.js index b55b5e8..31008ef 100644 --- a/test/mime.js +++ b/test/mime.js @@ -1,7 +1,7 @@ 'use strict'; const test = require('tap').test; -const mime = require('mime'); +const mime = require('../lib/ecstatic/mime'); test('mime package lookup', (t) => { t.plan(7); @@ -17,7 +17,7 @@ test('mime package lookup', (t) => { t.end(); }); -test('custom definition of mime-type with the mime package', (t) => { +test('custom definition of mime-type', (t) => { t.plan(1); mime.define({ @@ -27,20 +27,3 @@ test('custom definition of mime-type with the mime package', (t) => { t.end(); }); - -test('custom definition of mime-type with a .types file', (t) => { - t.plan(2); - - try { - mime.load('test/public/custom_mime_type.types'); - } catch (e) { - t.fail(e.message); - t.end(); - } - - t.equal(mime.getType('.opml'), 'application/foo'); // see public/custom_mime_type.types - - t.throws(mime.load.bind(mime, 'public/this_file_does_not_exist.types')); - - t.end(); -}); diff --git a/test/public/custom_mime_type.types b/test/public/custom_mime_type.types deleted file mode 100644 index 1af14d2..0000000 --- a/test/public/custom_mime_type.types +++ /dev/null @@ -1,3 +0,0 @@ -# This file is an example of the Apache .types file format for describing mime-types. -# Other example: http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types -application/foo opml From 60453575e5258e10b31afc1ed92c7711ccc7e727 Mon Sep 17 00:00:00 2001 From: Joshua Holbrook Date: Fri, 5 Apr 2019 13:32:07 -0400 Subject: [PATCH 03/10] Totally custom mime function --- README.md | 6 ++++-- lib/ecstatic.js | 3 +++ lib/ecstatic/mime.js | 10 +++++++++- test/mime.js | 8 ++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 95a679a..5e90977 100644 --- a/README.md +++ b/README.md @@ -236,9 +236,11 @@ Defaults to **application/octet-stream**. ### `--mime-types {filename}` Add new or override one or more mime-types. This affects the HTTP Content-Type -header. Must be an object hash of type(s). +header. May be either an object hash of type(s), *or* a function +`(file, defaultValue) => 'some/mimetype'`. Naturally, only the object hash +works on the command line. - ecstatic({ mimeTypes: { 'mime-type': ['file_extension', 'file_extension'] } }) + ecstatic({ mimeTypes: { 'some/mimetype': ['file_extension', 'file_extension'] } }) ### `opts.handleError` diff --git a/lib/ecstatic.js b/lib/ecstatic.js index fa363a1..d285952 100644 --- a/lib/ecstatic.js +++ b/lib/ecstatic.js @@ -120,6 +120,9 @@ module.exports = function createMiddleware(_dir, _options) { if (typeof opts.mimeTypes === 'object') { mime.define(opts.mimeTypes); } + if (typeof opts.mimeTypes === 'function') { + mime.setCustomGetType(opts.mimeTypes); + } } function shouldReturn304(req, serverLastModified, serverEtag) { diff --git a/lib/ecstatic/mime.js b/lib/ecstatic/mime.js index 2556a1f..c815f54 100644 --- a/lib/ecstatic/mime.js +++ b/lib/ecstatic/mime.js @@ -6,6 +6,14 @@ const charset = require('charset'); exports.define = mappings => mime.define(mappings, true); -exports.getType = (file, defaultValue) => mime.getType(file) || defaultValue; +let customGetType = (file, defaultValue) => null; // eslint-disable-line no-unused-vars + +exports.setCustomGetType = (fn) => { customGetType = fn; }; + +exports.getType = (file, defaultValue) => ( + customGetType(file, defaultValue) || + mime.getType(file) || + defaultValue +); exports.lookupCharset = contentType => charset(contentType) || 'utf8'; diff --git a/test/mime.js b/test/mime.js index 31008ef..f337e9e 100644 --- a/test/mime.js +++ b/test/mime.js @@ -27,3 +27,11 @@ test('custom definition of mime-type', (t) => { t.end(); }); + +test('custom mime-type lookup function', (t) => { + t.plan(1); + + mime.setCustomGetType(() => 'application/pony'); + + t.equal(mime.getType('whatever'), 'application/pony'); +}); From 708460e66e3d1da3b86bfc7f8b13ea2b9828f62e Mon Sep 17 00:00:00 2001 From: Joshua Holbrook Date: Fri, 5 Apr 2019 13:35:59 -0400 Subject: [PATCH 04/10] Mime 2.4 --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 27ee363..9362cc4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1548,9 +1548,9 @@ "dev": true }, "mime": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.2.0.tgz", - "integrity": "sha512-0Qz9uF1ATtl8RKJG4VRfOymh7PyEor6NbrI/61lRfuRe4vx9SNATrvAeTj2EWVRKjEQGskrzWkJBBY5NbaVHIA==" + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.1.tgz", + "integrity": "sha512-VRUfmQO0rCd3hKwBymAn3kxYzBHr3I/wdVMywgG3HhXOwrCQgN84ZagpdTm2tZ4TNtwsSmyJWYO88mb5XvzGqQ==" }, "mime-db": { "version": "1.33.0", diff --git a/package.json b/package.json index d234d6b..31442de 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "dependencies": { "charset": "^1.0.1", "he": "^1.1.1", - "mime": "^2.2.0", + "mime": "^2.4.1", "minimist": "^1.1.0", "url-join": "^2.0.5" }, From 9af64283f35f612f292221fec09305ceff738723 Mon Sep 17 00:00:00 2001 From: Joshua Holbrook Date: Fri, 5 Apr 2019 13:59:01 -0400 Subject: [PATCH 05/10] Expose and document internal mime module; add custom charset lookup function --- README.md | 45 ++++++++++++++++++++++++++++++++++++++++++++ lib/ecstatic.js | 1 + lib/ecstatic/mime.js | 10 +++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5e90977..4aa99cb 100644 --- a/README.md +++ b/README.md @@ -242,6 +242,13 @@ works on the command line. ecstatic({ mimeTypes: { 'some/mimetype': ['file_extension', 'file_extension'] } }) +It's important to note that any changes to mime handling are **global**, since +the `mime` module appears to be poorly behaved outside of a global singleton +context. For clarity you may prefer to call `require('ecstatic').mime.define` +or `require('ecstatic').setCustomGetType` directly and skip using this option, +particularly in cases where you're using multiple instances of ecstatic's +middleware. **You've been warned!** + ### `opts.handleError` Turn **off** handleErrors to allow fall-through with @@ -280,6 +287,44 @@ This works more or less as you'd expect. This returns another middleware which will attempt to show a directory view. Turning on auto-indexing is roughly equivalent to adding this middleware after an ecstatic middleware with autoindexing disabled. +### ecstatic.mime.define(mappings); + +This defines new mappings for the mime singleton, as specified in the main +docs for the ecstatic middleware. Calling this directly should make global +mutation more clear than setting the options when instantiating the middleware, +and is recommended if you're using more than one middlware instance. + +### ecstatic.mime.setCustomGetType(fn); + +This sets a global custom function for getting the mime type for a filename. +If this function returns a falsey value, getType will fall back to the mime +module's handling. Calling this directly should make global mutation more clear +than setting the options when instantiating the middleware, and is recommended +if you're using more than one middleware instance. + +### ecstatic.mime.getType(filename, defaultValue); + +This will return the mimetype for a filename, first using any function supplied +with `ecstatic.mime.setCustomGetType`, then trying `require('mime').getType`, +then falling back to defaultValue. Generally you don't want to use this +directly. + +### ecstatic.mime.setCustomLookupCharset(fn); + +This sets a global custom function for getting the charset for a mime type. +If this function returns a falsey value, lookupCharset will fall back on the +charset module's handling. Calling this directly should make global mutation +more clear than setting the options when instantiating the middleware, and is +recommended if you're using more than one middleware instance. + +### ecstatic.mime.lookupCharset(mimeType); + +This will look up the charset for the supplied mime type, first using any +function supplied with `ecstatic.mime.setCustomLookupCharset`, then trying +`require('charset')(mimeType)`, then falling back to "utf8". Generally you +don't want to use this directly. + + # Tests: Ecstatic has a fairly extensive test suite. You can run it with: diff --git a/lib/ecstatic.js b/lib/ecstatic.js index d285952..f42b53b 100644 --- a/lib/ecstatic.js +++ b/lib/ecstatic.js @@ -466,6 +466,7 @@ module.exports = function createMiddleware(_dir, _options) { ecstatic = module.exports; ecstatic.version = version; ecstatic.showDir = showDir; +ecstatic.mime = mime; if (!module.parent) { diff --git a/lib/ecstatic/mime.js b/lib/ecstatic/mime.js index c815f54..72612d5 100644 --- a/lib/ecstatic/mime.js +++ b/lib/ecstatic/mime.js @@ -16,4 +16,12 @@ exports.getType = (file, defaultValue) => ( defaultValue ); -exports.lookupCharset = contentType => charset(contentType) || 'utf8'; +let customLookupCharset = mimeType => null; // eslint-disable-line no-unused-vars + +exports.setCustomLookupCharset = (fn) => { customLookupCharset = fn; }; + +exports.lookupCharset = mimeType => ( + customLookupCharset(mimeType) || + charset(mimeType) || + 'utf8' +); From 46949db6fd0b26ccc40bc8c8b9680036bd7b8371 Mon Sep 17 00:00:00 2001 From: Joshua Holbrook Date: Fri, 5 Apr 2019 14:01:24 -0400 Subject: [PATCH 06/10] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9c9d52..1346b49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ - Drop testing/support for nodes 4 and 5 - Fix parsing of CORS options +- Upgrade mime module to v2, use charset module for charset detection +- Remove ability to set mime types with a .types file +- Add ability to override mime type and charset lookup with globally-set + functions 2019/02/10 Version 3.3.1 - Publish via linux to hopefully fix #238 From 64549ca63d97d78b48b5b4f429d8c5a4a1eadabf Mon Sep 17 00:00:00 2001 From: Joshua Holbrook Date: Fri, 5 Apr 2019 14:20:21 -0400 Subject: [PATCH 07/10] Remove default charset --- README.md | 2 +- lib/ecstatic/mime.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4aa99cb..cd420be 100644 --- a/README.md +++ b/README.md @@ -321,7 +321,7 @@ recommended if you're using more than one middleware instance. This will look up the charset for the supplied mime type, first using any function supplied with `ecstatic.mime.setCustomLookupCharset`, then trying -`require('charset')(mimeType)`, then falling back to "utf8". Generally you +`require('charset')(mimeType)`. Generally you don't want to use this directly. diff --git a/lib/ecstatic/mime.js b/lib/ecstatic/mime.js index 72612d5..40ef44c 100644 --- a/lib/ecstatic/mime.js +++ b/lib/ecstatic/mime.js @@ -22,6 +22,5 @@ exports.setCustomLookupCharset = (fn) => { customLookupCharset = fn; }; exports.lookupCharset = mimeType => ( customLookupCharset(mimeType) || - charset(mimeType) || - 'utf8' + charset(mimeType) ); From e3a108edc07d882697b8ddc9d12bad92ff56723f Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Tue, 19 Jun 2018 09:41:56 -0400 Subject: [PATCH 08/10] Remove charset=utf-8 default Fixes #220 --- test/cli.js | 6 ++---- test/content-type.js | 2 +- test/custom-content-type.js | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/test/cli.js b/test/cli.js index 9f08b68..b4ef4fa 100644 --- a/test/cli.js +++ b/test/cli.js @@ -83,8 +83,7 @@ test('setting port via cli - custom port', (t) => { }); test('setting mimeTypes via cli - directly', (t) => { - t.plan(4); - + t.plan(3); const port = getRandomPort(); const root = path.resolve(__dirname, 'public/'); const mimeType = ['--mimeTypes', '{ "application/x-my-type": ["opml"] }']; @@ -98,8 +97,7 @@ test('setting mimeTypes via cli - directly', (t) => { ecstatic.stdout.on('data', () => { t.pass('ecstatic should be started'); checkServerIsRunning(`${defaultUrl}:${port}/custom_mime_type.opml`, t, (err, res) => { - t.error(err); - t.equal(res.headers['content-type'], 'application/x-my-type; charset=utf8'); + t.equal(res.headers['content-type'], 'application/x-my-type'); }); }); }); diff --git a/test/content-type.js b/test/content-type.js index 26c5b20..e42ed07 100644 --- a/test/content-type.js +++ b/test/content-type.js @@ -24,7 +24,7 @@ test('default default contentType', (t) => { request.get(`http://localhost:${port}/f_f`, (err, res) => { t.ifError(err); t.equal(res.statusCode, 200); - t.equal(res.headers['content-type'], 'text/plain; charset=utf8'); + t.equal(res.headers['content-type'], 'text/plain'); server.close(() => { t.end(); }); }); }); diff --git a/test/custom-content-type.js b/test/custom-content-type.js index ef12604..c22bd49 100644 --- a/test/custom-content-type.js +++ b/test/custom-content-type.js @@ -26,7 +26,7 @@ test('custom contentType', (t) => { request.get(`http://localhost:${port}/custom_mime_type.opml`, (err, res) => { t.ifError(err); t.equal(res.statusCode, 200, 'custom_mime_type.opml should be found'); - t.equal(res.headers['content-type'], 'application/jon; charset=utf8'); + t.equal(res.headers['content-type'], 'application/jon'); server.close(() => { t.end(); }); }); }); From 0fbabb79c0a1c69e37b23c803e6ff5209655af16 Mon Sep 17 00:00:00 2001 From: Joshua Holbrook Date: Fri, 5 Apr 2019 14:33:34 -0400 Subject: [PATCH 09/10] Update contributors --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 9a351f0..8cf60ce 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -67,3 +67,4 @@ Listed in no particular order: * Victor Didenko @victordidenko * Zong Jhe Wu @s25g5d4 * Jade Michael Thornton @thornjad +* @BigBlueHat From 2351c5615da08bfcb0b785b77cea7b59ecf90df8 Mon Sep 17 00:00:00 2001 From: Joshua Holbrook Date: Fri, 5 Apr 2019 14:43:26 -0400 Subject: [PATCH 10/10] Update to note that charset no longer defaults to utf8 --- CHANGELOG.md | 2 ++ test/mime.js | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1346b49..de3fa0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - Remove ability to set mime types with a .types file - Add ability to override mime type and charset lookup with globally-set functions +- Removes default charset of utf8 - if you need this, try using a custom + charset lookup function 2019/02/10 Version 3.3.1 - Publish via linux to hopefully fix #238 diff --git a/test/mime.js b/test/mime.js index f337e9e..ec2fa7c 100644 --- a/test/mime.js +++ b/test/mime.js @@ -17,6 +17,11 @@ test('mime package lookup', (t) => { t.end(); }); +test('charset lookup', (t) => { + t.plan(1); + t.equal(mime.lookupCharset('application/wasm'), null); +}); + test('custom definition of mime-type', (t) => { t.plan(1);