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:
Joe Previte 2022-10-24 11:11:44 -07:00 committed by GitHub
parent 430b567e69
commit 031e903979
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 7 deletions

View File

@ -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();

View File

@ -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',

View File

@ -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}}/`)
}) })
} }