From 6dedcbddb03ec4eae3ef6357a3a4c1bb10fe0ffa Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Tue, 15 Dec 2020 19:28:50 +0100 Subject: [PATCH] Set correct MIME Type for all types of files served from techdocs-backend --- packages/techdocs-common/package.json | 2 + .../src/stages/publish/googleStorage.ts | 3 +- .../src/stages/publish/helpers.test.ts | 40 +++++++++---------- .../src/stages/publish/helpers.ts | 29 ++++---------- yarn.lock | 7 +++- 5 files changed, 35 insertions(+), 46 deletions(-) diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index adb138bdd9..fd767b4a64 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -48,6 +48,7 @@ "fs-extra": "^9.0.1", "git-url-parse": "^11.4.3", "js-yaml": "^3.14.0", + "mime-types": "^2.1.27", "mock-fs": "^4.13.0", "nodegit": "^0.27.0", "recursive-readdir": "^2.2.2", @@ -58,6 +59,7 @@ "@types/fs-extra": "^9.0.5", "@types/git-url-parse": "^9.0.0", "@types/js-yaml": "^3.12.5", + "@types/mime-types": "^2.1.0", "@types/mock-fs": "^4.13.0", "@types/nodegit": "^0.26.12", "@types/recursive-readdir": "^2.2.0" diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.ts b/packages/techdocs-common/src/stages/publish/googleStorage.ts index 5f8dc6a3fc..b33e2bfbe0 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import path from 'path'; import express from 'express'; import { Storage, @@ -167,7 +168,7 @@ export class GoogleGCSPublish implements PublisherBase { const filePath = req.path.replace(/^\//, ''); // Files with different extensions (CSS, HTML) need to be served with different headers - const fileExtension = filePath.split('.')[filePath.split('.').length - 1]; + const fileExtension = path.extname(filePath); const responseHeaders = getHeadersForFileExtension(fileExtension); const fileStreamChunks: Array = []; diff --git a/packages/techdocs-common/src/stages/publish/helpers.test.ts b/packages/techdocs-common/src/stages/publish/helpers.test.ts index e4f0c12b79..3b01f5ac43 100644 --- a/packages/techdocs-common/src/stages/publish/helpers.test.ts +++ b/packages/techdocs-common/src/stages/publish/helpers.test.ts @@ -17,29 +17,25 @@ import mockFs from 'mock-fs'; import { getFileTreeRecursively, getHeadersForFileExtension } from './helpers'; describe('getHeadersForFileExtension', () => { - it('returns correct header for default extensions', () => { - const headers = getHeadersForFileExtension('xyz'); - const expectedHeaders = { - 'Content-Type': 'text/plain', - }; - expect(headers).toEqual(expectedHeaders); - }); + const correctMapOfExtensions = [ + ['.html', 'text/html; charset=utf-8'], + ['.css', 'text/css; charset=utf-8'], + ['.png', 'image/png'], + ['.jpg', 'image/jpeg'], + ['.jpeg', 'image/jpeg'], + ['.svg', 'image/svg+xml'], + ['.json', 'application/json; charset=utf-8'], + ['.this-in-not-an-extension', 'text/plain; charset=utf-8'], + ]; - it('returns correct header for html', () => { - const headers = getHeadersForFileExtension('html'); - const expectedHeaders = { - 'Content-Type': 'text/html; charset=UTF-8', - }; - expect(headers).toEqual(expectedHeaders); - }); - - it('returns correct header for css', () => { - const headers = getHeadersForFileExtension('css'); - const expectedHeaders = { - 'Content-Type': 'text/css; charset=UTF-8', - }; - expect(headers).toEqual(expectedHeaders); - }); + test.each(correctMapOfExtensions)( + 'check content-type for %s extension', + (extension, expectedContentType) => { + const headers = getHeadersForFileExtension(extension); + expect(headers).toHaveProperty('Content-Type'); + expect(headers['Content-Type'].toLowerCase()).toBe(expectedContentType); + }, + ); }); describe('getFileTreeRecursively', () => { diff --git a/packages/techdocs-common/src/stages/publish/helpers.ts b/packages/techdocs-common/src/stages/publish/helpers.ts index 38ff27e0a0..4d9e2d327e 100644 --- a/packages/techdocs-common/src/stages/publish/helpers.ts +++ b/packages/techdocs-common/src/stages/publish/helpers.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import mime from 'mime-types'; import recursiveReadDir from 'recursive-readdir'; export type responseHeadersType = { @@ -22,32 +23,16 @@ export type responseHeadersType = { /** * Some files need special headers to be used correctly by the frontend. This function * generates headers in the response to those file requests. - * @param {string} fileExtension html, css, js etc. + * @param {string} fileExtension .html, .css, .js, .png etc. */ export const getHeadersForFileExtension = ( fileExtension: string, ): responseHeadersType => { - const headersCommon = { - 'Content-Type': 'text/plain', - }; - const headersHTML = { - ...headersCommon, - 'Content-Type': 'text/html; charset=UTF-8', - }; - - const headersCSS = { - ...headersCommon, - 'Content-Type': 'text/css; charset=UTF-8', - }; - - switch (fileExtension) { - case 'html': - return headersHTML; - case 'css': - return headersCSS; - default: - return headersCommon; - } + return { + 'Content-Type': mime.contentType(fileExtension) + ? mime.contentType(fileExtension) + : 'text/plain; charset=utf-8', + } as responseHeadersType; }; /** diff --git a/yarn.lock b/yarn.lock index 3bbeea245d..c01ad2c05b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5887,6 +5887,11 @@ dependencies: "@types/braces" "*" +"@types/mime-types@^2.1.0": + version "2.1.0" + resolved "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz#9ca52cda363f699c69466c2a6ccdaad913ea7a73" + integrity sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM= + "@types/mime@*": version "2.0.1" resolved "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" @@ -17416,7 +17421,7 @@ mime-db@1.44.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== -mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.26, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: +mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.26, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.27" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==