mirror of https://github.com/coder/code-server.git
feat: enable forwarded ports using built-in proxy (#5673)
* feat: enable ports panel in proxy-uri patch This makes the forwarded ports panel enabled by default. * feat: add tunnelProvider in proxy-uri patch This adds a `tunnelProvider` along with a `tunnelFactory` so that ports are forwarded and use code-server's built-in proxy. * fixup!: update import * fix: skip uri modification if authority host match This adds a check in our `resolveExternalUri` patch to skip modifying if the `authority` and the `location.host` match to prevent `localhost:<port>/proxy/<port>` from being modified. * fixup!: refresh patch * fixup!: move authority check up * fixup!: remove comment * fixup!: add trailing slash
This commit is contained in:
parent
430b567e69
commit
031e903979
|
@ -19,6 +19,13 @@ For the `asExternalUri` changes, you'll need to test manually by:
|
||||||
Do the same thing but set `VSCODE_PROXY_URI: "https://{{port}}-main-workspace-name-user-name.coder.com"`
|
Do the same thing but set `VSCODE_PROXY_URI: "https://{{port}}-main-workspace-name-user-name.coder.com"`
|
||||||
and the output should replace `{{port}}` with port used in input url.
|
and the output should replace `{{port}}` with port used in input url.
|
||||||
|
|
||||||
|
This also enables the forwared ports view panel by default.
|
||||||
|
|
||||||
|
Lastly, it adds a tunnelProvider so that ports are forwarded using code-server's
|
||||||
|
built-in proxy. You can test this by starting a server i.e. `python3 -m
|
||||||
|
http.server` and it should show a notification and show up in the ports panel
|
||||||
|
using the /proxy/port.
|
||||||
|
|
||||||
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
|
@ -77,7 +84,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
rootEndpoint: base,
|
rootEndpoint: base,
|
||||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
||||||
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}',
|
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
extensionsGallery: this._productService.extensionsGallery,
|
extensionsGallery: this._productService.extensionsGallery,
|
||||||
},
|
},
|
||||||
|
@ -115,11 +122,11 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||||
import type { IURLCallbackProvider } from 'vs/workbench/services/url/browser/urlService';
|
import type { IURLCallbackProvider } from 'vs/workbench/services/url/browser/urlService';
|
||||||
import type { IWorkbenchConstructionOptions } from 'vs/workbench/browser/web.api';
|
import type { IWorkbenchConstructionOptions } from 'vs/workbench/browser/web.api';
|
||||||
import type { IWorkspace, IWorkspaceProvider } from 'vs/workbench/services/host/browser/browserHostService';
|
import type { IWorkspace, IWorkspaceProvider } from 'vs/workbench/services/host/browser/browserHostService';
|
||||||
+import { extractLocalHostUriMetaDataForPortMapping } from 'vs/platform/tunnel/common/tunnel';
|
+import { extractLocalHostUriMetaDataForPortMapping, TunnelOptions, TunnelCreationOptions } from 'vs/platform/tunnel/common/tunnel';
|
||||||
|
|
||||||
interface ICredential {
|
interface ICredential {
|
||||||
service: string;
|
service: string;
|
||||||
@@ -511,6 +512,21 @@ function doCreateUri(path: string, query
|
@@ -511,6 +512,38 @@ function doCreateUri(path: string, query
|
||||||
} : undefined,
|
} : undefined,
|
||||||
workspaceProvider: WorkspaceProvider.create(config),
|
workspaceProvider: WorkspaceProvider.create(config),
|
||||||
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
|
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
|
||||||
|
@ -127,9 +134,9 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||||
+ credentialsProvider: config.remoteAuthority ? undefined : new LocalStorageCredentialsProvider(), // with a remote, we don't use a local credentials provider
|
+ credentialsProvider: config.remoteAuthority ? undefined : new LocalStorageCredentialsProvider(), // with a remote, we don't use a local credentials provider
|
||||||
+ resolveExternalUri: (uri: URI): Promise<URI> => {
|
+ resolveExternalUri: (uri: URI): Promise<URI> => {
|
||||||
+ let resolvedUri = uri
|
+ let resolvedUri = uri
|
||||||
+ const localhostMatch = extractLocalHostUriMetaDataForPortMapping(uri)
|
+ const localhostMatch = extractLocalHostUriMetaDataForPortMapping(resolvedUri)
|
||||||
+
|
+
|
||||||
+ if (localhostMatch) {
|
+ if (localhostMatch && resolvedUri.authority !== location.host) {
|
||||||
+ if (config.productConfiguration && config.productConfiguration.proxyEndpointTemplate) {
|
+ if (config.productConfiguration && config.productConfiguration.proxyEndpointTemplate) {
|
||||||
+ resolvedUri = URI.parse(new URL(config.productConfiguration.proxyEndpointTemplate.replace('{{port}}', localhostMatch.port.toString()), window.location.href).toString())
|
+ resolvedUri = URI.parse(new URL(config.productConfiguration.proxyEndpointTemplate.replace('{{port}}', localhostMatch.port.toString()), window.location.href).toString())
|
||||||
+ } else {
|
+ } else {
|
||||||
|
@ -139,6 +146,36 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||||
+
|
+
|
||||||
+ // If not localhost, return unmodified
|
+ // If not localhost, return unmodified
|
||||||
+ return Promise.resolve(resolvedUri)
|
+ return Promise.resolve(resolvedUri)
|
||||||
|
+ },
|
||||||
|
+ tunnelProvider: {
|
||||||
|
+ tunnelFactory: (tunnelOptions: TunnelOptions, tunnelCreationOptions: TunnelCreationOptions) => {
|
||||||
|
+ const onDidDispose: Emitter<void> = new Emitter();
|
||||||
|
+ let isDisposed = false;
|
||||||
|
+ return Promise.resolve({
|
||||||
|
+ remoteAddress: tunnelOptions.remoteAddress,
|
||||||
|
+ localAddress: `localhost:${tunnelOptions.remoteAddress.port}`,
|
||||||
|
+ onDidDispose: onDidDispose.event,
|
||||||
|
+ dispose: () => {
|
||||||
|
+ if (!isDisposed) {
|
||||||
|
+ isDisposed = true;
|
||||||
|
+ onDidDispose.fire();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ })
|
||||||
|
+ }
|
||||||
+ }
|
+ }
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
Index: code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||||
|
===================================================================
|
||||||
|
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||||
|
+++ code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||||
|
@@ -73,7 +73,7 @@ export class ForwardedPortsView extends
|
||||||
|
this.contextKeyListener = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
- const viewEnabled: boolean = !!forwardedPortsViewEnabled.getValue(this.contextKeyService);
|
||||||
|
+ const viewEnabled: boolean = true;
|
||||||
|
|
||||||
|
if (this.environmentService.remoteAuthority && viewEnabled) {
|
||||||
|
const viewContainer = await this.getViewContainer();
|
||||||
|
|
|
@ -57,7 +57,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -316,6 +316,10 @@ export class WebClientServer {
|
@@ -316,6 +316,10 @@ export class WebClientServer {
|
||||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
||||||
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}',
|
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
|
||||||
+ serviceWorker: {
|
+ serviceWorker: {
|
||||||
+ scope: vscodeBase + '/',
|
+ scope: vscodeBase + '/',
|
||||||
+ path: base + '/_static/out/browser/serviceWorker.js',
|
+ path: base + '/_static/out/browser/serviceWorker.js',
|
||||||
|
|
|
@ -15,7 +15,7 @@ function runTestExtensionTests() {
|
||||||
const text = await codeServerPage.page.locator("text=proxyUri").first().textContent()
|
const text = await codeServerPage.page.locator("text=proxyUri").first().textContent()
|
||||||
// Remove end slash in address
|
// Remove end slash in address
|
||||||
const normalizedAddress = address.replace(/\/+$/, "")
|
const normalizedAddress = address.replace(/\/+$/, "")
|
||||||
expect(text).toBe(`Info: proxyUri: ${normalizedAddress}/proxy/{{port}}`)
|
expect(text).toBe(`Info: proxyUri: ${normalizedAddress}/proxy/{{port}}/`)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue