diff --git a/lib/middleware/MiddlewareManager.js b/lib/middleware/MiddlewareManager.js index e3c6b04d..a6ac2001 100644 --- a/lib/middleware/MiddlewareManager.js +++ b/lib/middleware/MiddlewareManager.js @@ -108,7 +108,16 @@ class MiddlewareManager { await this.addMiddleware("discovery", { mountPath: "/discovery" }); - await this.addMiddleware("serveResources"); + await this.addMiddleware("serveResources", { + wrapperCallback: (serveResourcesModule) => { + return ({resources}) => { + return serveResourcesModule({ + resources, + tree: this.tree + }); + }; + } + }); await this.addMiddleware("serveThemes"); await this.addMiddleware("versionInfo", { mountPath: "/resources/sap-ui-version.json", diff --git a/lib/middleware/serveIndex.js b/lib/middleware/serveIndex.js index 606e8888..3df8b077 100644 --- a/lib/middleware/serveIndex.js +++ b/lib/middleware/serveIndex.js @@ -2,8 +2,6 @@ const log = require("@ui5/logger").getLogger("server:middleware:serveIndex"); const mime = require("mime-types"); const parseurl = require("parseurl"); -const rProperties = /\.properties$/; - const KB = 1024; const MB = KB * KB; const GB = KB * KB * KB; @@ -15,11 +13,7 @@ const GB = KB * KB * KB; * @returns {string} mime type */ function getMimeType(resource) { - if (rProperties.test(resource.getPath())) { - return "text/plain;charset=ISO-8859-1"; - } else { - return mime.lookup(resource.getPath()) || "application/octet-stream"; - } + return mime.lookup(resource.getPath()) || "application/octet-stream"; } /** diff --git a/lib/middleware/serveResources.js b/lib/middleware/serveResources.js index e1ade546..62e88a15 100644 --- a/lib/middleware/serveResources.js +++ b/lib/middleware/serveResources.js @@ -23,10 +23,11 @@ function isFresh(req, res) { * @param {module:@ui5/fs.AbstractReader} resources.all Resource collection which contains the workspace and the project dependencies * @returns {Function} Returns a server middleware closure. */ -function createMiddleware({resources}) { - return function serveResources(req, res, next) { - const pathname = parseurl(req).pathname; - resources.all.byPath(pathname).then(function(resource) { +function createMiddleware({resources, tree: project}) { + return async function serveResources(req, res, next) { + try { + const pathname = parseurl(req).pathname; + const resource = await resources.all.byPath(pathname); if (!resource) { // Not found next(); return; @@ -36,22 +37,21 @@ function createMiddleware({resources}) { log.verbose("\n" + treeify.asTree(resource.getPathTree())); } - let type; - let charset; const resourcePath = resource.getPath(); + const type = mime.lookup(resourcePath) || "application/octet-stream"; + const charset = mime.charset(type); if (rProperties.test(resourcePath)) { - // Special handling for *.properties files which are encoded with charset ISO-8859-1. - type = "text/plain"; - charset = "ISO-8859-1"; - } else { - type = mime.lookup(resourcePath) || "application/octet-stream"; + // Special handling for *.properties files escape non ascii characters. + const nonAsciiEscaper = require("@ui5/builder").processors.nonAsciiEscaper; + const propertiesFileSourceEncoding = project && project.resources && project.resources.configuration && project.resources.configuration.propertiesFileSourceEncoding; + const encoding = nonAsciiEscaper.getEncodingFromAlias(propertiesFileSourceEncoding || "ISO-8859-1"); + await nonAsciiEscaper({ + resources: [resource], options: { + encoding + } + }); } - if (!res.getHeader("Content-Type")) { - if (!charset) { - charset = mime.charset(type); - } - res.setHeader("Content-Type", type + (charset ? "; charset=" + charset : "")); } @@ -71,7 +71,7 @@ function createMiddleware({resources}) { // UTF-8 anyways. // Also, only process .library, *.js and *.json files. Just like it's done in Application- // and LibraryBuilder - if (charset === "UTF-8" && rReplaceVersion.test(resourcePath)) { + if ((!charset || charset === "UTF-8") && rReplaceVersion.test(resourcePath)) { if (resource._project) { stream = stream.pipe(replaceStream("${version}", resource._project.version)); } else { @@ -80,9 +80,9 @@ function createMiddleware({resources}) { } stream.pipe(res); - }).catch((err) => { + } catch (err) { next(err); - }); + } }; } diff --git a/test/lib/server/main.js b/test/lib/server/main.js index 1baad208..67c6583e 100644 --- a/test/lib/server/main.js +++ b/test/lib/server/main.js @@ -67,18 +67,18 @@ test("Get resource from application.a with replaced version placeholder (/versio }); }); -test("Get resource from application.a (/i18n/i18n.properties) with correct charset 'ISO-8859-1'", (t) => { +test("Get resource from application.a (/i18n/i18n.properties) with correct content-type", (t) => { return request.get("/i18n/i18n.properties").then((res) => { if (res.error) { t.fail(res.error.text); } t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.deepEqual(res.headers["content-type"], "text/plain; charset=ISO-8859-1", "Correct content type and charset"); - t.deepEqual(Buffer.from(res.text, "latin1").toString(), "showHelloButtonText=Say Hello!", "Correct response"); + t.deepEqual(res.headers["content-type"], "application/octet-stream", "Correct content type"); + t.deepEqual(res.body.toString(), "showHelloButtonText=Say Hello!", "Correct response"); }); }); -test("Get resource from application.a (/i18n/i18n_de.properties) with correct encoding 'ISO-8859-1'", (t) => { +test("Get resource from application.a (/i18n/i18n_de.properties) with correct content-type'", (t) => { return request.get("/i18n/i18n_de.properties") .responseType("arraybuffer") .then((res) => { @@ -86,10 +86,10 @@ test("Get resource from application.a (/i18n/i18n_de.properties) with correct en t.fail(res.error.text); } t.deepEqual(res.statusCode, 200, "Correct HTTP status code"); - t.deepEqual(res.headers["content-type"], "text/plain; charset=ISO-8859-1", - "Correct content type and charset"); + t.deepEqual(res.headers["content-type"], "application/octet-stream", + "Correct content type"); - t.deepEqual(res.body.toString("latin1"), "showHelloButtonText=Say ä!", "Correct response"); + t.deepEqual(res.body.toString(), "showHelloButtonText=Say \\u00e4!", "Correct response"); // Because it took so long to figure this out I keep the below line. It is equivalent to the deepEqual above // t.deepEqual(res.body.toString("latin1"), Buffer.from("showHelloButtonText=Say \u00e4!", "latin1").toString("latin1"), // "Correct response"); diff --git a/test/lib/server/middleware/serveIndex.js b/test/lib/server/middleware/serveIndex.js index f2bba1d0..9b4dff53 100644 --- a/test/lib/server/middleware/serveIndex.js +++ b/test/lib/server/middleware/serveIndex.js @@ -41,7 +41,7 @@ test.serial("Check if index for files is created", (t) => { end: function(content) { t.regex(content, /