From 7fa2c151cfc84001a0116e07532c464aefe9f56c Mon Sep 17 00:00:00 2001 From: Loonride Date: Mon, 29 Jun 2020 08:40:02 -0500 Subject: [PATCH] fix(middleware): prefer mime type option over built-in (#670) --- src/index.js | 4 +- src/middleware.js | 22 ++++++---- test/middleware.test.js | 97 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 109 insertions(+), 14 deletions(-) diff --git a/src/index.js b/src/index.js index f16e4635f..de45f0374 100644 --- a/src/index.js +++ b/src/index.js @@ -21,7 +21,9 @@ export default function wdm(compiler, options = {}) { if (mimeTypes) { const { types } = mime; - mime.types = { ...mimeTypes, ...types }; + // mimeTypes from user provided options should take priority + // over existing, known types + mime.types = { ...types, ...mimeTypes }; } const context = { diff --git a/src/middleware.js b/src/middleware.js index c9f09e7eb..c207efa9a 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -49,15 +49,9 @@ export default function wrapper(context) { return; } - try { - content = context.outputFileSystem.readFileSync(filename); - } catch (_ignoreError) { - await goNext(); - return; - } - - // Buffer - content = handleRangeHeaders(content, req, res); + // Content-Type and headers need to be set before checking if + // the file is in the outputFileSystem, as these things should be + // applied to all files that are being served if (!res.get('Content-Type')) { // content-type name(like application/javascript; charset=utf-8) or false @@ -74,6 +68,16 @@ export default function wrapper(context) { } } + try { + content = context.outputFileSystem.readFileSync(filename); + } catch (_ignoreError) { + await goNext(); + return; + } + + // Buffer + content = handleRangeHeaders(content, req, res); + // send Buffer res.send(content); } diff --git a/test/middleware.test.js b/test/middleware.test.js index b01c0a9b2..caa55261f 100644 --- a/test/middleware.test.js +++ b/test/middleware.test.js @@ -1990,7 +1990,7 @@ describe('middleware', () => { afterAll(close); - it('should return the "200" code for the "GET" request to "file.html"', (done) => { + it('should return the "200" code for the "GET" request to "file.phtml"', (done) => { request(app) .get('/file.phtml') .expect('Content-Type', 'application/octet-stream') @@ -2031,13 +2031,91 @@ describe('middleware', () => { afterAll(close); - it('should return the "200" code for the "GET" request "file.html"', (done) => { + it('should return the "200" code for the "GET" request "file.phtml"', (done) => { request(app) .get('/file.phtml') .expect('Content-Type', 'text/html; charset=utf-8') .expect(200, 'welcome', done); }); }); + + describe('should override value for "Content-Type" header for known MIME type', () => { + beforeAll((done) => { + const outputPath = path.resolve(__dirname, './outputs/basic'); + const compiler = getCompiler({ + ...webpackConfig, + output: { + filename: 'bundle.js', + path: outputPath, + }, + }); + + instance = middleware(compiler, { + mimeTypes: { + jpg: 'application/octet-stream', + }, + }); + + app = express(); + app.use(instance); + + listen = listenShorthand(done); + + instance.context.outputFileSystem.mkdirSync(outputPath, { + recursive: true, + }); + instance.context.outputFileSystem.writeFileSync( + path.resolve(outputPath, 'file.jpg'), + 'welcome' + ); + }); + + afterAll(close); + + it('should return the "200" code for the "GET" request "file.jpg"', (done) => { + request(app) + .get('/file.jpg') + .expect('Content-Type', /application\/octet-stream/) + .expect(200, done); + }); + }); + + describe('should set "Content-Type" header for route not from outputFileSystem', () => { + beforeAll((done) => { + const outputPath = path.resolve(__dirname, './outputs/basic'); + const compiler = getCompiler({ + ...webpackConfig, + output: { + filename: 'bundle.js', + path: outputPath, + }, + }); + + instance = middleware(compiler, { + mimeTypes: { + jpg: 'application/octet-stream', + }, + }); + + app = express(); + app.use(instance); + + app.get('/file.jpg', (req, res) => { + res.send('welcome'); + }); + + listen = listenShorthand(done); + }); + + afterAll(close); + + it('should return the "200" code for the "GET" request "file.jpg"', (done) => { + request(app) + .get('/file.jpg') + .expect('Content-Type', /application\/octet-stream/) + .expect(200, done); + }); + }); }); describe('watchOptions option', () => { @@ -2640,7 +2718,7 @@ describe('middleware', () => { }); describe('headers option', () => { - beforeAll((done) => { + beforeEach((done) => { const compiler = getCompiler(webpackConfig); instance = middleware(compiler, { @@ -2653,7 +2731,7 @@ describe('middleware', () => { listen = listenShorthand(done); }); - afterAll(close); + afterEach(close); it('should return the "200" code for the "GET" request to the bundle file and return headers', (done) => { request(app) @@ -2662,6 +2740,17 @@ describe('middleware', () => { .expect('X-nonsense-2', 'no') .expect(200, done); }); + + it('should return the "200" code for the "GET" request to path not in outputFileSystem and return headers', (done) => { + app.get('/file.jpg', (req, res) => { + res.send('welcome'); + }); + request(app) + .get('/file.jpg') + .expect('X-nonsense-1', 'yes') + .expect('X-nonsense-2', 'no') + .expect(200, done); + }); }); describe('publicPath option', () => {