Skip to content

Commit cc8c7e2

Browse files
code-asherkylecarbs
authored andcommitted
Make assets unique (#518)
* Make all assets unique All CSS and JavaScript files have unique names now. I also moved the login to the /login path in order to ensure the HTML for each page is also unique. * Explicitly include assets to cache
1 parent e0f1787 commit cc8c7e2

12 files changed

+167
-150
lines changed

build/tasks.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -67,21 +67,21 @@ const buildServerBinaryCopy = register("build:server:binary:copy", async (runner
6767
}
6868
fse.copySync(defaultExtensionsPath, path.join(cliBuildPath, "extensions"));
6969
fs.writeFileSync(path.join(cliBuildPath, "bootstrap-fork.js.gz"), zlib.gzipSync(fs.readFileSync(bootstrapForkPath)));
70-
const cpDir = (dir: string, subdir: "auth" | "unauth", rootPath: string): void => {
70+
const cpDir = (dir: string, rootPath: string, subdir?: "login"): void => {
7171
const stat = fs.statSync(dir);
7272
if (stat.isDirectory()) {
7373
const paths = fs.readdirSync(dir);
74-
paths.forEach((p) => cpDir(path.join(dir, p), subdir, rootPath));
74+
paths.forEach((p) => cpDir(path.join(dir, p), rootPath, subdir));
7575
} else if (stat.isFile()) {
76-
const newPath = path.join(cliBuildPath, "web", subdir, path.relative(rootPath, dir));
76+
const newPath = path.join(cliBuildPath, "web", subdir || "", path.relative(rootPath, dir));
7777
fse.mkdirpSync(path.dirname(newPath));
7878
fs.writeFileSync(newPath + ".gz", zlib.gzipSync(fs.readFileSync(dir)));
7979
} else {
8080
// Nothing
8181
}
8282
};
83-
cpDir(webOutputPath, "auth", webOutputPath);
84-
cpDir(browserAppOutputPath, "unauth", browserAppOutputPath);
83+
cpDir(webOutputPath, webOutputPath);
84+
cpDir(browserAppOutputPath, browserAppOutputPath, "login");
8585
fse.mkdirpSync(path.join(cliBuildPath, "dependencies"));
8686
fse.copySync(ripgrepPath, path.join(cliBuildPath, "dependencies", "rg"));
8787
});

packages/app/browser/src/app.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ if (!form) {
2828

2929
form.addEventListener("submit", (e) => {
3030
e.preventDefault();
31-
document.cookie = `password=${password.value}`;
31+
document.cookie = `password=${password.value}; `
32+
+ `path=${location.pathname.replace(/\/login\/?$/, "/")}; `
33+
+ `domain=${location.hostname}`;
3234
location.reload();
3335
});
3436

packages/app/browser/webpack.config.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ const root = path.resolve(__dirname, "../../..");
77

88
module.exports = merge(
99
require(path.join(root, "scripts/webpack.client.config.js"))({
10-
entry: path.join(root, "packages/app/browser/src/app.ts"),
11-
template: path.join(root, "packages/app/browser/src/app.html"),
10+
dirname: __dirname,
11+
entry: path.join(__dirname, "src/app.ts"),
12+
name: "login",
13+
template: path.join(__dirname, "src/app.html"),
1214
}), {
13-
output: {
14-
path: path.join(__dirname, "out"),
15-
},
1615
},
1716
);

packages/dns/webpack.config.js

+2-5
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,12 @@ const root = path.resolve(__dirname, "../..");
55

66
module.exports = merge(
77
require(path.join(root, "scripts/webpack.node.config.js"))({
8-
// Options.
8+
dirname: __dirname,
9+
name: "dns",
910
}), {
1011
externals: {
1112
"node-named": "commonjs node-named",
1213
},
13-
output: {
14-
path: path.join(__dirname, "out"),
15-
filename: "main.js",
16-
},
1714
entry: [
1815
"./packages/dns/src/dns.ts"
1916
],

packages/server/src/cli.ts

-7
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,6 @@ const bold = (text: string | number): string | number => {
216216
allowHttp: options.allowHttp,
217217
bypassAuth: options.noAuth,
218218
registerMiddleware: (app): void => {
219-
app.use((req, res, next) => {
220-
res.on("finish", () => {
221-
logger.trace(`\u001B[1m${req.method} ${res.statusCode} \u001B[0m${req.url}`, field("host", req.hostname), field("ip", req.ip));
222-
});
223-
224-
next();
225-
});
226219
// If we're not running from the binary and we aren't serving the static
227220
// pre-built version, use webpack to serve the web files.
228221
if (!isCli && !serveStatic) {

packages/server/src/server.ts

+59-14
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import * as os from "os";
1818
import * as path from "path";
1919
import * as pem from "pem";
2020
import * as util from "util";
21+
import * as url from "url";
2122
import * as ws from "ws";
2223
import { buildDir } from "./constants";
2324
import { createPortScanner } from "./portScanner";
@@ -140,13 +141,13 @@ export const createApp = async (options: CreateAppOptions): Promise<{
140141
};
141142

142143
const portScanner = createPortScanner();
143-
wss.on("connection", (ws, req) => {
144+
wss.on("connection", async (ws, req) => {
144145
if (req.url && req.url.startsWith("/tunnel")) {
145146
try {
146147
const rawPort = req.url.split("/").pop();
147148
const port = Number.parseInt(rawPort!, 10);
148149

149-
handleTunnel(ws, port);
150+
await handleTunnel(ws, port);
150151
} catch (ex) {
151152
ws.close(TunnelCloseCode.Error, ex.toString());
152153
}
@@ -189,31 +190,70 @@ export const createApp = async (options: CreateAppOptions): Promise<{
189190
new Server(connection, options.serverOptions);
190191
});
191192

193+
const redirect = (
194+
req: express.Request, res: express.Response,
195+
to: string = "", from: string = "",
196+
code: number = 302, protocol: string = req.protocol,
197+
): void => {
198+
const currentUrl = `${protocol}://${req.headers.host}${req.originalUrl}`;
199+
const newUrl = url.parse(currentUrl);
200+
if (from && newUrl.pathname) {
201+
newUrl.pathname = newUrl.pathname.replace(new RegExp(`\/${from}\/?$`), "/");
202+
}
203+
if (to) {
204+
newUrl.pathname = (newUrl.pathname || "").replace(/\/$/, "") + `/${to}`;
205+
}
206+
newUrl.path = undefined; // Path is not necessary for format().
207+
const newUrlString = url.format(newUrl);
208+
logger.trace(`Redirecting from ${currentUrl} to ${newUrlString}`);
209+
210+
return res.redirect(code, newUrlString);
211+
};
212+
192213
const baseDir = buildDir || path.join(__dirname, "..");
193-
const authStaticFunc = expressStaticGzip(path.join(baseDir, "build/web/auth"));
194-
const unauthStaticFunc = expressStaticGzip(path.join(baseDir, "build/web/unauth"));
214+
const staticGzip = expressStaticGzip(path.join(baseDir, "build/web"));
215+
195216
app.use((req, res, next) => {
217+
logger.trace(`\u001B[1m${req.method} ${res.statusCode} \u001B[0m${req.originalUrl}`, field("host", req.hostname), field("ip", req.ip));
218+
219+
// Force HTTPS unless allowing HTTP.
196220
if (!isEncrypted(req.socket) && !options.allowHttp) {
197-
return res.redirect(301, `https://${req.headers.host!}${req.path}`);
221+
return redirect(req, res, "", "", 301, "https");
198222
}
199223

200-
if (isAuthed(req)) {
201-
// We can serve the actual VSCode bin
202-
authStaticFunc(req, res, next);
203-
} else {
204-
// Serve only the unauthed version
205-
unauthStaticFunc(req, res, next);
206-
}
224+
next();
207225
});
226+
208227
// @ts-ignore
209-
app.use((err, req, res, next) => {
228+
app.use((err, _req, _res, next) => {
229+
logger.error(err.message);
210230
next();
211231
});
212-
app.get("/ping", (req, res) => {
232+
233+
// If not authenticated, redirect to the login page.
234+
app.get("/", (req, res, next) => {
235+
if (!isAuthed(req)) {
236+
return redirect(req, res, "login");
237+
}
238+
next();
239+
});
240+
241+
// If already authenticated, redirect back to the root.
242+
app.get("/login", (req, res, next) => {
243+
if (isAuthed(req)) {
244+
return redirect(req, res, "", "login");
245+
}
246+
next();
247+
});
248+
249+
// For getting general server data.
250+
app.get("/ping", (_req, res) => {
213251
res.json({
214252
hostname: os.hostname(),
215253
});
216254
});
255+
256+
// For getting a resource on disk.
217257
app.get("/resource/:url(*)", async (req, res) => {
218258
if (!ensureAuthed(req, res)) {
219259
return;
@@ -254,6 +294,8 @@ export const createApp = async (options: CreateAppOptions): Promise<{
254294
res.end();
255295
}
256296
});
297+
298+
// For writing a resource to disk.
257299
app.post("/resource/:url(*)", async (req, res) => {
258300
if (!ensureAuthed(req, res)) {
259301
return;
@@ -282,6 +324,9 @@ export const createApp = async (options: CreateAppOptions): Promise<{
282324
}
283325
});
284326

327+
// Everything else just pulls from the static build directory.
328+
app.use(staticGzip);
329+
285330
return {
286331
express: app,
287332
server,

packages/server/webpack.config.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ const root = path.resolve(__dirname, "../..");
66

77
module.exports = merge(
88
require(path.join(root, "scripts/webpack.node.config.js"))({
9-
// Config options.
9+
dirname: __dirname,
1010
}), {
1111
output: {
1212
filename: "cli.js",
13-
path: path.join(__dirname, "out"),
1413
libraryTarget: "commonjs",
1514
},
1615
node: {

packages/vscode/webpack.bootstrap.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const vsFills = path.join(root, "packages/vscode/src/fill");
77

88
module.exports = merge(
99
require(path.join(root, "scripts/webpack.node.config.js"))({
10+
dirname: __dirname,
1011
typescriptCompilerOptions: {
1112
target: "es6",
1213
},
@@ -15,7 +16,6 @@ module.exports = merge(
1516
mode: "development",
1617
output: {
1718
chunkFilename: "[name].bundle.js",
18-
path: path.resolve(__dirname, "out"),
1919
publicPath: "/",
2020
filename: "bootstrap-fork.js",
2121
libraryTarget: "commonjs",

packages/web/src/index.html

+10-10
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@
2323
return;
2424
}
2525
document.body.style.background = bg;
26-
})();
27-
28-
// Check that service workers are registered
29-
if ("serviceWorker" in navigator) {
30-
// Use the window load event to keep the page load performant
31-
window.addEventListener("load", () => {
32-
navigator.serviceWorker.register("/service-worker.js");
33-
});
34-
}
26+
})();
27+
28+
// Check that service workers are registered
29+
if ("serviceWorker" in navigator) {
30+
// Use the window load event to keep the page load performant
31+
window.addEventListener("load", () => {
32+
navigator.serviceWorker.register("/service-worker.js");
33+
});
34+
}
3535
</script>
3636
</body>
37-
</html>
37+
</html>

packages/web/webpack.config.js

+2-5
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,16 @@ const vsFills = path.join(root, "packages/vscode/src/fill");
77

88
module.exports = merge(
99
require(path.join(root, "scripts/webpack.client.config.js"))({
10+
dirname: __dirname,
1011
entry: path.join(root, "packages/web/src/index.ts"),
12+
name: "ide",
1113
template: path.join(root, "packages/web/src/index.html"),
1214
typescriptCompilerOptions: {
1315
"target": "es5",
1416
"lib": ["dom", "esnext"],
1517
},
1618
},
1719
), {
18-
output: {
19-
chunkFilename: "[name]-[hash:6].bundle.js",
20-
path: path.join(__dirname, "out"),
21-
filename: "[hash:6].bundle.js",
22-
},
2320
node: {
2421
module: "empty",
2522
crypto: "empty",

0 commit comments

Comments
 (0)