diff --git a/lib/middleware/testRunner.js b/lib/middleware/testRunner.js index dd9cae64..fa7071b0 100644 --- a/lib/middleware/testRunner.js +++ b/lib/middleware/testRunner.js @@ -5,20 +5,43 @@ const path = require("path"); const mime = require("mime-types"); const parseurl = require("parseurl"); const log = require("@ui5/logger").getLogger("server:middleware:testRunner"); +const etag = require("etag"); +const fresh = require("fresh"); const testRunnerResourceRegEx = /\/test-resources\/sap\/ui\/qunit\/(testrunner\.(html|css)|TestRunner.js)$/; const resourceCache = {}; -function serveResource(res, resourcePath, resourceContent) { +function isFresh(req, res) { + return fresh(req.headers, { + "etag": res.getHeader("ETag") + }); +} + +async function readResourceInfo(resourceName) { + const content = await readFile(path.join(__dirname, "testRunner", resourceName), {encoding: "utf8"}); + return { + content, + etag: etag(content) + }; +} + +function serveResource(req, res, resourcePath, resourceInfo) { const type = mime.lookup(resourcePath) || "application/octet-stream"; const charset = mime.charset(type); const contentType = type + (charset ? "; charset=" + charset : ""); + res.setHeader("Content-Type", contentType); - // resources served by this middleware do not change often - res.setHeader("Cache-Control", "public, max-age=1800"); + // Enable ETag caching + res.setHeader("ETag", resourceInfo.etag); - res.setHeader("Content-Type", contentType); - res.end(resourceContent); + if (isFresh(req, res)) { + // client has a fresh copy of the resource + res.statusCode = 304; + res.end(); + return; + } + + res.end(resourceInfo.content); } /** @@ -40,14 +63,14 @@ function createMiddleware({resources}) { log.verbose(`Serving ${pathname}`); let pResource; if (!resourceCache[pathname]) { - pResource = readFile(path.join(__dirname, "testRunner", resourceName), {encoding: "utf8"}); + pResource = readResourceInfo(resourceName); resourceCache[pathname] = pResource; } else { pResource = resourceCache[pathname]; } - const resourceContent = await pResource; - serveResource(res, pathname, resourceContent); + const resourceInfo = await pResource; + serveResource(req, res, pathname, resourceInfo); } else { next(); }