Skip to content

Commit bf1be16

Browse files
committed
Fix base path
Now it should work whether you have a trailing slash or not.
1 parent cc79edb commit bf1be16

File tree

5 files changed

+50
-36
lines changed

5 files changed

+50
-36
lines changed

src/browser/app.tsx

+14-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { field, logger } from "@coder/logger"
12
import { getBasepath, navigate, setBasepath } from "hookrouter"
23
import * as React from "react"
34
import { Application, isExecutableApplication } from "../common/api"
@@ -14,16 +15,25 @@ interface RedirectedApplication extends Application {
1415
redirected?: boolean
1516
}
1617

17-
const origin = typeof window !== "undefined" ? window.location.origin + window.location.pathname : undefined
18-
18+
let resolved = false
1919
const App: React.FunctionComponent<AppProps> = (props) => {
2020
const [authed, setAuthed] = React.useState<boolean>(props.options.authed)
2121
const [app, setApp] = React.useState<RedirectedApplication | undefined>(props.options.app)
2222
const [error, setError] = React.useState<HttpError | Error | string>()
2323

24-
if (typeof window !== "undefined") {
25-
const url = new URL(origin + props.options.basePath)
24+
if (!resolved && typeof document !== "undefined") {
25+
// Get the base path. We need the full URL for connecting the web socket.
26+
// Use the path name plus the provided base path. For example:
27+
// foo.com/base + ./ => foo.com/base
28+
// foo.com/base/ + ./ => foo.com/base
29+
// foo.com/base/bar + ./ => foo.com/base
30+
// foo.com/base/bar/ + ./../ => foo.com/base
31+
const parts = window.location.pathname.replace(/^\//g, "").split("/")
32+
parts[parts.length - 1] = props.options.basePath
33+
const url = new URL(window.location.origin + "/" + parts.join("/"))
2634
setBasepath(normalize(url.pathname))
35+
logger.debug("resolved base path", field("base", getBasepath()))
36+
resolved = true
2737

2838
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2939
;(window as any).setAuthed = (a: boolean): void => {

src/node/http.ts

+12-9
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,9 @@ interface ProviderRoute extends Route {
117117

118118
export interface HttpProviderOptions {
119119
readonly auth: AuthType
120-
readonly password?: string
120+
readonly base: string
121121
readonly commit: string
122+
readonly password?: string
122123
}
123124

124125
/**
@@ -150,10 +151,16 @@ export abstract class HttpProvider {
150151
public abstract handleRequest(route: Route, request: http.IncomingMessage): Promise<HttpResponse | undefined>
151152

152153
/**
153-
* Get the base relative to the provided route.
154+
* Get the base relative to the provided route. For each slash we need to go
155+
* up a directory. For example:
156+
* / => ./
157+
* /foo => ./
158+
* /foo/ => ./../
159+
* /foo/bar => ./../
160+
* /foo/bar/ => ./../../
154161
*/
155162
public base(route: Route): string {
156-
const depth = ((route.fullPath + "/").match(/\//g) || []).length
163+
const depth = (route.originalPath.match(/\//g) || []).length
157164
return normalize("./" + (depth > 1 ? "../".repeat(depth - 1) : ""))
158165
}
159166

@@ -403,6 +410,7 @@ export class HttpServer {
403410
new provider(
404411
{
405412
auth: this.options.auth || AuthType.None,
413+
base: `/${endpoint}`,
406414
commit: this.options.commit,
407415
password: this.options.password,
408416
},
@@ -510,11 +518,6 @@ export class HttpServer {
510518
return { redirect: redirect(route.fullPath) }
511519
}
512520

513-
// Redirect our indexes to a trailing slash so relative paths in the served
514-
// HTML will operate against the base path properly.
515-
if (route.requestPath === "/index.html" && !route.originalPath.endsWith("/") && this.providers.has(route.base)) {
516-
return { redirect: redirect(route.fullPath + "/") }
517-
}
518521
return undefined
519522
}
520523

@@ -572,7 +575,7 @@ export class HttpServer {
572575
}
573576

574577
const parsedUrl = request.url ? url.parse(request.url, true) : { query: {}, pathname: "" }
575-
const originalPath = parsedUrl.pathname || ""
578+
const originalPath = parsedUrl.pathname || "/"
576579
const fullPath = normalize(originalPath)
577580
const { base, requestPath } = parse(fullPath)
578581

src/node/vscode/server.ts

+2
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ export class VscodeHttpProvider extends HttpProvider {
199199
...response,
200200
content: response.content
201201
.replace(/{{COMMIT}}/g, options.commit)
202+
.replace(/{{BASE}}/g, this.base(route))
203+
.replace(/{{VS_BASE}}/g, this.base(route) + this.options.base)
202204
.replace(`"{{REMOTE_USER_DATA_URI}}"`, `'${JSON.stringify(options.remoteUserDataUri)}'`)
203205
.replace(`"{{PRODUCT_CONFIGURATION}}"`, `'${JSON.stringify(options.productConfiguration)}'`)
204206
.replace(`"{{WORKBENCH_WEB_CONFIGURATION}}"`, `'${JSON.stringify(options.workbenchWebConfiguration)}'`)

src/node/vscode/workbench-build.html

+14-16
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,27 @@
1919
<meta id="vscode-remote-nls-configuration" data-settings="{{NLS_CONFIGURATION}}">
2020

2121
<!-- Workbench Icon/Manifest/CSS -->
22-
<link rel="icon" href="../static-{{COMMIT}}/src/browser/media/favicon.ico" type="image/x-icon" />
23-
<link rel="manifest" href="../static-{{COMMIT}}/src/browser/media/manifest.json" crossorigin="use-credentials">
24-
<link data-name="vs/workbench/workbench.web.api" rel="stylesheet" href="./static-{{COMMIT}}/out/vs/workbench/workbench.web.api.css">
25-
<link rel="apple-touch-icon" href="../static-{{COMMIT}}/src/browser/media/code-server.png" />
22+
<link rel="icon" href="{{BASE}}/static-{{COMMIT}}/src/browser/media/favicon.ico" type="image/x-icon" />
23+
<link rel="manifest" href="{{BASE}}/static-{{COMMIT}}/src/browser/media/manifest.json" crossorigin="use-credentials">
24+
<link data-name="vs/workbench/workbench.web.api" rel="stylesheet" href="{{VS_BASE}}/static-{{COMMIT}}/out/vs/workbench/workbench.web.api.css">
25+
<link rel="apple-touch-icon" href="{{BASE}}/static-{{COMMIT}}/src/browser/media/code-server.png" />
2626
<meta name="apple-mobile-web-app-capable" content="yes">
2727

2828
<!-- Prefetch to avoid waterfall -->
29-
<link rel="prefetch" href="./static-{{COMMIT}}/node_modules/semver-umd/lib/semver-umd.js">
29+
<link rel="prefetch" href="{{BASE}}/static-{{COMMIT}}/node_modules/semver-umd/lib/semver-umd.js">
3030
</head>
3131

3232
<body aria-label="">
3333
</body>
3434

3535
<!-- Startup (do not modify order of script tags!) -->
36-
<!-- NOTE:coder: Modified to work against the current path and use the commit for caching. -->
3736
<script>
38-
// NOTE: Changes to inline scripts require update of content security policy
39-
const basePath = window.location.pathname.replace(/\/+$/, '');
40-
const base = window.location.origin + basePath;
37+
const parts = window.location.pathname.replace(/^\//g, "").split("/")
38+
parts[parts.length - 1] = "{{VS_BASE}}"
39+
const url = new URL(window.location.origin + "/" + parts.join("/"))
4140
const el = document.getElementById('vscode-remote-commit');
4241
const commit = el ? el.getAttribute('data-settings') : "";
43-
const staticBase = base + '/static-' + commit;
42+
const staticBase = url.href + '/static-' + commit;
4443
let nlsConfig;
4544
try {
4645
nlsConfig = JSON.parse(document.getElementById('vscode-remote-nls-configuration').getAttribute('data-settings'));
@@ -54,7 +53,7 @@
5453
// FIXME: Only works if path separators are /.
5554
const path = nlsConfig._resolvedLanguagePackCoreLocation
5655
+ '/' + bundle.replace(/\//g, '!') + '.nls.json';
57-
fetch(`${base}/resource/?path=${encodeURIComponent(path)}`)
56+
fetch(`${url.href}/resource/?path=${encodeURIComponent(path)}`)
5857
.then((response) => response.json())
5958
.then((json) => {
6059
bundles[bundle] = json;
@@ -78,15 +77,14 @@
7877
'vs/nls': nlsConfig,
7978
};
8079
</script>
81-
<script src="./static-{{COMMIT}}/out/vs/loader.js"></script>
82-
<script src="./static-{{COMMIT}}/out/vs/workbench/workbench.web.api.nls.js"></script>
83-
<script src="./static-{{COMMIT}}/out/vs/workbench/workbench.web.api.js"></script>
80+
<script src="{{VS_BASE}}/static-{{COMMIT}}/out/vs/loader.js"></script>
81+
<script src="{{VS_BASE}}/static-{{COMMIT}}/out/vs/workbench/workbench.web.api.nls.js"></script>
82+
<script src="{{VS_BASE}}/static-{{COMMIT}}/out/vs/workbench/workbench.web.api.js"></script>
8483
<!-- TODO@coder: This errors with multiple anonymous define calls (one is
8584
workbench.js and one is semver-umd.js). For now use the same method found in
8685
workbench-dev.html. Appears related to the timing of the script load events. -->
87-
<!-- <script src="./static-{{COMMIT}}/out/vs/workbench/workbench.js"></script> -->
86+
<!-- <script src="{{VS_BASE}}/static-{{COMMIT}}/out/vs/workbench/workbench.js"></script> -->
8887
<script>
89-
// NOTE: Changes to inline scripts require update of content security policy
9088
require(['vs/code/browser/workbench/workbench'], function() {});
9189
</script>
9290
</html>

src/node/vscode/workbench.html

+8-7
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
<meta id="vscode-remote-nls-configuration" data-settings="{{NLS_CONFIGURATION}}">
2020

2121
<!-- Workbench Icon/Manifest/CSS -->
22-
<link rel="icon" href="../static/src/browser/media/favicon.ico" type="image/x-icon" />
23-
<link rel="manifest" href="../static/src/browser/media/manifest.json" crossorigin="use-credentials">
24-
<link rel="apple-touch-icon" href="../static/src/browser/media/code-server.png" />
22+
<link rel="icon" href="{{BASE}}/static/src/browser/media/favicon.ico" type="image/x-icon" />
23+
<link rel="manifest" href="{{BASE}}/static/src/browser/media/manifest.json" crossorigin="use-credentials">
24+
<link rel="apple-touch-icon" href="{{BASE}}/static/src/browser/media/code-server.png" />
2525
<meta name="apple-mobile-web-app-capable" content="yes">
2626
</head>
2727

@@ -30,11 +30,12 @@
3030

3131
<!-- Startup (do not modify order of script tags!) -->
3232
<script>
33-
const basePath = window.location.pathname.replace(/\/+$/, '');
34-
const base = window.location.origin + basePath;
33+
const parts = window.location.pathname.replace(/^\//g, "").split("/")
34+
parts[parts.length - 1] = "{{VS_BASE}}"
35+
const url = new URL(window.location.origin + "/" + parts.join("/"))
3536
const el = document.getElementById('vscode-remote-commit');
3637
const commit = el ? el.getAttribute('data-settings') : "";
37-
const staticBase = base + '/static-' + commit;
38+
const staticBase = url.href + '/static-' + commit;
3839
self.require = {
3940
baseUrl: `${staticBase}/out`,
4041
paths: {
@@ -48,7 +49,7 @@
4849
},
4950
};
5051
</script>
51-
<script src="./static/out/vs/loader.js"></script>
52+
<script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
5253
<script>
5354
require(['vs/code/browser/workbench/workbench'], function() {});
5455
</script>

0 commit comments

Comments
 (0)