diff --git a/scripts/vscode.patch b/scripts/vscode.patch index e20308e4..e513589e 100644 --- a/scripts/vscode.patch +++ b/scripts/vscode.patch @@ -151,15 +151,17 @@ index 1d9a0b8308..d8204187c6 100644 diff --git a/src/vs/code/browser/workbench/workbench.js b/src/vs/code/browser/workbench/workbench.js -index 2f09f53e43..ca969f19f6 100644 +index 2f09f53e43..0f5eef1c9e 100644 --- a/src/vs/code/browser/workbench/workbench.js +++ b/src/vs/code/browser/workbench/workbench.js -@@ -8,24 +8,52 @@ +@@ -8,24 +8,53 @@ (function () { + const basePath = window.location.pathname.replace(/\/+$/, ''); + const base = window.location.origin + basePath; ++ const options = JSON.parse(document.getElementById('vscode-workbench-web-configuration').getAttribute('data-settings')); ++ options.webviewEndpoint = `${base}/webview/`; + let nlsConfig; + try { + nlsConfig = JSON.parse(document.getElementById('vscode-remote-nls-configuration').getAttribute('data-settings')); @@ -187,9 +189,10 @@ index 2f09f53e43..ca969f19f6 100644 /** @type any */ const amdLoader = require; ++ const staticBase = base + `/static${options.productConfiguration && options.productConfiguration.commit ? `-${options.productConfiguration.commit}` : ''}`; amdLoader.config({ - baseUrl: `${window.location.origin}/static/out`, -+ baseUrl: `${base}/static/out`, ++ baseUrl: `${staticBase}/out`, paths: { - 'vscode-textmate': `${window.location.origin}/static/node_modules/vscode-textmate/release/main`, - 'onigasm-umd': `${window.location.origin}/static/node_modules/onigasm-umd/release/main`, @@ -199,20 +202,19 @@ index 2f09f53e43..ca969f19f6 100644 - 'semver-umd': `${window.location.origin}/static/node_modules/semver-umd/lib/semver-umd.js`, - '@microsoft/applicationinsights-web': `${window.location.origin}/static/node_modules/@microsoft/applicationinsights-web/dist/applicationinsights-web.js`, - } -+ 'vscode-textmate': `${base}/static/node_modules/vscode-textmate/release/main`, -+ 'onigasm-umd': `${base}/static/node_modules/onigasm-umd/release/main`, -+ 'xterm': `${base}/static/node_modules/xterm/lib/xterm.js`, -+ 'xterm-addon-search': `${base}/static/node_modules/xterm-addon-search/lib/xterm-addon-search.js`, -+ 'xterm-addon-web-links': `${base}/static/node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js`, -+ 'semver-umd': `${base}/static/node_modules/semver-umd/lib/semver-umd.js`, -+ '@microsoft/applicationinsights-web': `${base}/static/node_modules/@microsoft/applicationinsights-web/dist/applicationinsights-web.js`, ++ 'vscode-textmate': `${staticBase}/node_modules/vscode-textmate/release/main`, ++ 'onigasm-umd': `${staticBase}/node_modules/onigasm-umd/release/main`, ++ 'xterm': `${staticBase}/node_modules/xterm/lib/xterm.js`, ++ 'xterm-addon-search': `${staticBase}/node_modules/xterm-addon-search/lib/xterm-addon-search.js`, ++ 'xterm-addon-web-links': `${staticBase}/node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js`, ++ 'semver-umd': `${staticBase}/node_modules/semver-umd/lib/semver-umd.js`, ++ '@microsoft/applicationinsights-web': `${staticBase}/node_modules/@microsoft/applicationinsights-web/dist/applicationinsights-web.js`, + }, + 'vs/nls': nlsConfig }); amdLoader(['vs/workbench/workbench.web.api'], function (api) { - const options = JSON.parse(document.getElementById('vscode-workbench-web-configuration').getAttribute('data-settings')); -+ options.webviewEndpoint = `${base}/webview/`; +- const options = JSON.parse(document.getElementById('vscode-workbench-web-configuration').getAttribute('data-settings')); api.create(document.body, options); }); })(); diff --git a/src/server.ts b/src/server.ts index ca93b2eb..b778141c 100644 --- a/src/server.ts +++ b/src/server.ts @@ -84,6 +84,7 @@ export interface Options { } export interface Response { + cache?: boolean; code?: number; content?: string | Buffer; filePath?: string; @@ -207,12 +208,13 @@ export abstract class Server { private onRequest = async (request: http.IncomingMessage, response: http.ServerResponse): Promise => { try { - const payload = await this.preHandleRequest(request); + const parsedUrl = request.url ? url.parse(request.url, true) : { query: {}}; + const payload = await this.preHandleRequest(request, parsedUrl); response.writeHead(payload.redirect ? HttpCode.Redirect : payload.code || HttpCode.Ok, { - // "Cache-Control": "public, max-age=31536000", "Content-Type": getMediaMime(payload.filePath), ...(payload.redirect ? { Location: this.withBase(request, payload.redirect) } : {}), ...(request.headers["service-worker"] ? { "Service-Worker-Allowed": this.options.basePath || "/" } : {}), + ...(payload.cache ? { "Cache-Control": "public, max-age=31536000" } : {}), ...payload.headers, }); response.end(payload.content); @@ -225,13 +227,12 @@ export abstract class Server { } } - private async preHandleRequest(request: http.IncomingMessage): Promise { + private async preHandleRequest(request: http.IncomingMessage, parsedUrl: url.UrlWithParsedQuery): Promise { const secure = (request.connection as tls.TLSSocket).encrypted; if (this.options.cert && !secure) { return { redirect: request.url }; } - const parsedUrl = request.url ? url.parse(request.url, true) : { query: {}}; const fullPath = decodeURIComponent(parsedUrl.pathname || "/"); const match = fullPath.match(/^(\/?[^/]*)(.*)$/); let [/* ignore */, base, requestPath] = match @@ -250,19 +251,32 @@ export abstract class Server { this.ensureGet(request); } + // Allow for a versioned static endpoint. This lets us cache every static + // resource underneath the path based on the version without any work and + // without adding query parameters which have their own issues. + // REVIEW: Discuss whether this is the best option; this is sort of a quick + // hack almost to get caching in the meantime but it does work pretty well. + if (/static-.+/.test(base)) { + base = "/static"; + } + switch (base) { case "/": switch (requestPath) { case "/favicon.ico": case "/manifest.json": - return this.getResource(this.serverRoot, "media", requestPath); + const response = await this.getResource(this.serverRoot, "media", requestPath); + response.cache = true; + return response; } if (!this.authenticate(request)) { return { redirect: "/login" }; } break; case "/static": - return this.getResource(this.rootPath, requestPath); + const response = await this.getResource(this.rootPath, requestPath); + response.cache = true; + return response; case "/login": if (!this.options.auth || requestPath !== "/index.html") { throw new HttpError("Not found", HttpCode.NotFound); @@ -514,10 +528,10 @@ export class MainServer extends Server { NLS_CONFIGURATION: await getNlsConfiguration(locale, environment.userDataPath), }; + content = content.replace(/\/static\//g, `/static${product.commit ? `-${product.commit}` : ""}/`).replace("{{WEBVIEW_ENDPOINT}}", ""); for (const key in options) { content = content.replace(`"{{${key}}}"`, `'${JSON.stringify(options[key as keyof Options])}'`); } - content = content.replace("{{WEBVIEW_ENDPOINT}}", ""); return { content, filePath }; }