diff --git a/cli.js b/cli.js index fc1f9d9..35621eb 100644 --- a/cli.js +++ b/cli.js @@ -89,4 +89,4 @@ Arguments: module.exports = { Logger, Cli -} \ No newline at end of file +} diff --git a/server.js b/server.js index 089b7a5..09d340d 100644 --- a/server.js +++ b/server.js @@ -373,21 +373,44 @@ class EleventyDevServer { return (content || "") + script; } + getFileContentType(filepath, res) { + let contentType = res.getHeader("Content-Type"); + + // Content-Type might be already set via middleware + if (contentType) { + return contentType; + } + + let mimeType = mime.getType(filepath); + if (!mimeType) { + return; + } + + contentType = mimeType; + + // We only want to append charset if the header is not already set + if (contentType === "text/html") { + contentType = `text/html; charset=${this.options.encoding}`; + } + + return contentType; + } + renderFile(filepath, res) { let contents = fs.readFileSync(filepath); - let mimeType = mime.getType(filepath); + let contentType = this.getFileContentType(filepath, res); - if (mimeType === "text/html") { - res.setHeader("Content-Type", `text/html; charset=${this.options.encoding}`); + if (!contentType) { + return res.end(contents); + } + + res.setHeader("Content-Type", contentType); + if (contentType.startsWith("text/html")) { // the string is important here, wrapResponse expects strings internally for HTML content (for now) return res.end(contents.toString()); } - if (mimeType) { - res.setHeader("Content-Type", mimeType); - } - return res.end(contents); } diff --git a/test/stubs/index.php b/test/stubs/index.php new file mode 100644 index 0000000..5ae6e4b --- /dev/null +++ b/test/stubs/index.php @@ -0,0 +1 @@ +SAMPLE PHP diff --git a/test/testServerRequests.js b/test/testServerRequests.js index 1fa5d29..4ef283c 100644 --- a/test/testServerRequests.js +++ b/test/testServerRequests.js @@ -42,6 +42,32 @@ async function makeRequestTo(t, server, path) { }) } +async function fetchHeadersForRequest(t, server, path) { + let port = await server.getPort(); + + return new Promise(resolve => { + const options = { + hostname: 'localhost', + port, + path, + method: 'GET', + }; + + http.get(options, (res) => { + const { statusCode } = res; + if(statusCode !== 200) { + throw new Error("Invalid status code" + statusCode); + } + + let headers = res.headers; + resolve(headers); + + }).on('error', (e) => { + console.error(`Got error: ${e.message}`); + }); + }) +} + test("Standard request", async t => { let server = new EleventyDevServer("test-server", "./test/stubs/", getOptions()); server.serve(8080); @@ -255,4 +281,24 @@ test("Fun unicode paths", async t => { t.true(data.startsWith("This is a test")); server.close(); -}); \ No newline at end of file +}); + +test("Content-Type header via middleware", async t => { + let server = new EleventyDevServer("test-server", "./test/stubs/", getOptions({ + middleware: [ + function (req, res, next) { + if (/.*\.php$/.test(req.url)) { + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + } + + next(); + } + ] + })); + server.serve(8080); + + let data = await fetchHeadersForRequest(t, server, encodeURI(`/index.php`)); + t.true(data['content-type'] === 'text/html; charset=utf-8'); + + server.close(); +});