mirror of https://github.com/coder/code-server.git
Fix base path
Now it should work whether you have a trailing slash or not.
This commit is contained in:
parent
cc79edb312
commit
bf1be16d11
|
@ -1,3 +1,4 @@
|
|||
import { field, logger } from "@coder/logger"
|
||||
import { getBasepath, navigate, setBasepath } from "hookrouter"
|
||||
import * as React from "react"
|
||||
import { Application, isExecutableApplication } from "../common/api"
|
||||
|
@ -14,16 +15,25 @@ interface RedirectedApplication extends Application {
|
|||
redirected?: boolean
|
||||
}
|
||||
|
||||
const origin = typeof window !== "undefined" ? window.location.origin + window.location.pathname : undefined
|
||||
|
||||
let resolved = false
|
||||
const App: React.FunctionComponent<AppProps> = (props) => {
|
||||
const [authed, setAuthed] = React.useState<boolean>(props.options.authed)
|
||||
const [app, setApp] = React.useState<RedirectedApplication | undefined>(props.options.app)
|
||||
const [error, setError] = React.useState<HttpError | Error | string>()
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
const url = new URL(origin + props.options.basePath)
|
||||
if (!resolved && typeof document !== "undefined") {
|
||||
// Get the base path. We need the full URL for connecting the web socket.
|
||||
// Use the path name plus the provided base path. For example:
|
||||
// foo.com/base + ./ => foo.com/base
|
||||
// foo.com/base/ + ./ => foo.com/base
|
||||
// foo.com/base/bar + ./ => foo.com/base
|
||||
// foo.com/base/bar/ + ./../ => foo.com/base
|
||||
const parts = window.location.pathname.replace(/^\//g, "").split("/")
|
||||
parts[parts.length - 1] = props.options.basePath
|
||||
const url = new URL(window.location.origin + "/" + parts.join("/"))
|
||||
setBasepath(normalize(url.pathname))
|
||||
logger.debug("resolved base path", field("base", getBasepath()))
|
||||
resolved = true
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
;(window as any).setAuthed = (a: boolean): void => {
|
||||
|
|
|
@ -117,8 +117,9 @@ interface ProviderRoute extends Route {
|
|||
|
||||
export interface HttpProviderOptions {
|
||||
readonly auth: AuthType
|
||||
readonly password?: string
|
||||
readonly base: string
|
||||
readonly commit: string
|
||||
readonly password?: string
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,10 +151,16 @@ export abstract class HttpProvider {
|
|||
public abstract handleRequest(route: Route, request: http.IncomingMessage): Promise<HttpResponse | undefined>
|
||||
|
||||
/**
|
||||
* Get the base relative to the provided route.
|
||||
* Get the base relative to the provided route. For each slash we need to go
|
||||
* up a directory. For example:
|
||||
* / => ./
|
||||
* /foo => ./
|
||||
* /foo/ => ./../
|
||||
* /foo/bar => ./../
|
||||
* /foo/bar/ => ./../../
|
||||
*/
|
||||
public base(route: Route): string {
|
||||
const depth = ((route.fullPath + "/").match(/\//g) || []).length
|
||||
const depth = (route.originalPath.match(/\//g) || []).length
|
||||
return normalize("./" + (depth > 1 ? "../".repeat(depth - 1) : ""))
|
||||
}
|
||||
|
||||
|
@ -403,6 +410,7 @@ export class HttpServer {
|
|||
new provider(
|
||||
{
|
||||
auth: this.options.auth || AuthType.None,
|
||||
base: `/${endpoint}`,
|
||||
commit: this.options.commit,
|
||||
password: this.options.password,
|
||||
},
|
||||
|
@ -510,11 +518,6 @@ export class HttpServer {
|
|||
return { redirect: redirect(route.fullPath) }
|
||||
}
|
||||
|
||||
// Redirect our indexes to a trailing slash so relative paths in the served
|
||||
// HTML will operate against the base path properly.
|
||||
if (route.requestPath === "/index.html" && !route.originalPath.endsWith("/") && this.providers.has(route.base)) {
|
||||
return { redirect: redirect(route.fullPath + "/") }
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
|
@ -572,7 +575,7 @@ export class HttpServer {
|
|||
}
|
||||
|
||||
const parsedUrl = request.url ? url.parse(request.url, true) : { query: {}, pathname: "" }
|
||||
const originalPath = parsedUrl.pathname || ""
|
||||
const originalPath = parsedUrl.pathname || "/"
|
||||
const fullPath = normalize(originalPath)
|
||||
const { base, requestPath } = parse(fullPath)
|
||||
|
||||
|
|
|
@ -199,6 +199,8 @@ export class VscodeHttpProvider extends HttpProvider {
|
|||
...response,
|
||||
content: response.content
|
||||
.replace(/{{COMMIT}}/g, options.commit)
|
||||
.replace(/{{BASE}}/g, this.base(route))
|
||||
.replace(/{{VS_BASE}}/g, this.base(route) + this.options.base)
|
||||
.replace(`"{{REMOTE_USER_DATA_URI}}"`, `'${JSON.stringify(options.remoteUserDataUri)}'`)
|
||||
.replace(`"{{PRODUCT_CONFIGURATION}}"`, `'${JSON.stringify(options.productConfiguration)}'`)
|
||||
.replace(`"{{WORKBENCH_WEB_CONFIGURATION}}"`, `'${JSON.stringify(options.workbenchWebConfiguration)}'`)
|
||||
|
|
|
@ -19,28 +19,27 @@
|
|||
<meta id="vscode-remote-nls-configuration" data-settings="{{NLS_CONFIGURATION}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
<link rel="icon" href="../static-{{COMMIT}}/src/browser/media/favicon.ico" type="image/x-icon" />
|
||||
<link rel="manifest" href="../static-{{COMMIT}}/src/browser/media/manifest.json" crossorigin="use-credentials">
|
||||
<link data-name="vs/workbench/workbench.web.api" rel="stylesheet" href="./static-{{COMMIT}}/out/vs/workbench/workbench.web.api.css">
|
||||
<link rel="apple-touch-icon" href="../static-{{COMMIT}}/src/browser/media/code-server.png" />
|
||||
<link rel="icon" href="{{BASE}}/static-{{COMMIT}}/src/browser/media/favicon.ico" type="image/x-icon" />
|
||||
<link rel="manifest" href="{{BASE}}/static-{{COMMIT}}/src/browser/media/manifest.json" crossorigin="use-credentials">
|
||||
<link data-name="vs/workbench/workbench.web.api" rel="stylesheet" href="{{VS_BASE}}/static-{{COMMIT}}/out/vs/workbench/workbench.web.api.css">
|
||||
<link rel="apple-touch-icon" href="{{BASE}}/static-{{COMMIT}}/src/browser/media/code-server.png" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
|
||||
<!-- Prefetch to avoid waterfall -->
|
||||
<link rel="prefetch" href="./static-{{COMMIT}}/node_modules/semver-umd/lib/semver-umd.js">
|
||||
<link rel="prefetch" href="{{BASE}}/static-{{COMMIT}}/node_modules/semver-umd/lib/semver-umd.js">
|
||||
</head>
|
||||
|
||||
<body aria-label="">
|
||||
</body>
|
||||
|
||||
<!-- Startup (do not modify order of script tags!) -->
|
||||
<!-- NOTE:coder: Modified to work against the current path and use the commit for caching. -->
|
||||
<script>
|
||||
// NOTE: Changes to inline scripts require update of content security policy
|
||||
const basePath = window.location.pathname.replace(/\/+$/, '');
|
||||
const base = window.location.origin + basePath;
|
||||
const parts = window.location.pathname.replace(/^\//g, "").split("/")
|
||||
parts[parts.length - 1] = "{{VS_BASE}}"
|
||||
const url = new URL(window.location.origin + "/" + parts.join("/"))
|
||||
const el = document.getElementById('vscode-remote-commit');
|
||||
const commit = el ? el.getAttribute('data-settings') : "";
|
||||
const staticBase = base + '/static-' + commit;
|
||||
const staticBase = url.href + '/static-' + commit;
|
||||
let nlsConfig;
|
||||
try {
|
||||
nlsConfig = JSON.parse(document.getElementById('vscode-remote-nls-configuration').getAttribute('data-settings'));
|
||||
|
@ -54,7 +53,7 @@
|
|||
// FIXME: Only works if path separators are /.
|
||||
const path = nlsConfig._resolvedLanguagePackCoreLocation
|
||||
+ '/' + bundle.replace(/\//g, '!') + '.nls.json';
|
||||
fetch(`${base}/resource/?path=${encodeURIComponent(path)}`)
|
||||
fetch(`${url.href}/resource/?path=${encodeURIComponent(path)}`)
|
||||
.then((response) => response.json())
|
||||
.then((json) => {
|
||||
bundles[bundle] = json;
|
||||
|
@ -78,15 +77,14 @@
|
|||
'vs/nls': nlsConfig,
|
||||
};
|
||||
</script>
|
||||
<script src="./static-{{COMMIT}}/out/vs/loader.js"></script>
|
||||
<script src="./static-{{COMMIT}}/out/vs/workbench/workbench.web.api.nls.js"></script>
|
||||
<script src="./static-{{COMMIT}}/out/vs/workbench/workbench.web.api.js"></script>
|
||||
<script src="{{VS_BASE}}/static-{{COMMIT}}/out/vs/loader.js"></script>
|
||||
<script src="{{VS_BASE}}/static-{{COMMIT}}/out/vs/workbench/workbench.web.api.nls.js"></script>
|
||||
<script src="{{VS_BASE}}/static-{{COMMIT}}/out/vs/workbench/workbench.web.api.js"></script>
|
||||
<!-- TODO@coder: This errors with multiple anonymous define calls (one is
|
||||
workbench.js and one is semver-umd.js). For now use the same method found in
|
||||
workbench-dev.html. Appears related to the timing of the script load events. -->
|
||||
<!-- <script src="./static-{{COMMIT}}/out/vs/workbench/workbench.js"></script> -->
|
||||
<!-- <script src="{{VS_BASE}}/static-{{COMMIT}}/out/vs/workbench/workbench.js"></script> -->
|
||||
<script>
|
||||
// NOTE: Changes to inline scripts require update of content security policy
|
||||
require(['vs/code/browser/workbench/workbench'], function() {});
|
||||
</script>
|
||||
</html>
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
<meta id="vscode-remote-nls-configuration" data-settings="{{NLS_CONFIGURATION}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
<link rel="icon" href="../static/src/browser/media/favicon.ico" type="image/x-icon" />
|
||||
<link rel="manifest" href="../static/src/browser/media/manifest.json" crossorigin="use-credentials">
|
||||
<link rel="apple-touch-icon" href="../static/src/browser/media/code-server.png" />
|
||||
<link rel="icon" href="{{BASE}}/static/src/browser/media/favicon.ico" type="image/x-icon" />
|
||||
<link rel="manifest" href="{{BASE}}/static/src/browser/media/manifest.json" crossorigin="use-credentials">
|
||||
<link rel="apple-touch-icon" href="{{BASE}}/static/src/browser/media/code-server.png" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
</head>
|
||||
|
||||
|
@ -30,11 +30,12 @@
|
|||
|
||||
<!-- Startup (do not modify order of script tags!) -->
|
||||
<script>
|
||||
const basePath = window.location.pathname.replace(/\/+$/, '');
|
||||
const base = window.location.origin + basePath;
|
||||
const parts = window.location.pathname.replace(/^\//g, "").split("/")
|
||||
parts[parts.length - 1] = "{{VS_BASE}}"
|
||||
const url = new URL(window.location.origin + "/" + parts.join("/"))
|
||||
const el = document.getElementById('vscode-remote-commit');
|
||||
const commit = el ? el.getAttribute('data-settings') : "";
|
||||
const staticBase = base + '/static-' + commit;
|
||||
const staticBase = url.href + '/static-' + commit;
|
||||
self.require = {
|
||||
baseUrl: `${staticBase}/out`,
|
||||
paths: {
|
||||
|
@ -48,7 +49,7 @@
|
|||
},
|
||||
};
|
||||
</script>
|
||||
<script src="./static/out/vs/loader.js"></script>
|
||||
<script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
|
||||
<script>
|
||||
require(['vs/code/browser/workbench/workbench'], function() {});
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue