Skip to content

Commit 031e903

Browse files
authored
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
1 parent 430b567 commit 031e903

File tree

3 files changed

+44
-7
lines changed

3 files changed

+44
-7
lines changed

patches/proxy-uri.diff

+42-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ For the `asExternalUri` changes, you'll need to test manually by:
1919
Do the same thing but set `VSCODE_PROXY_URI: "https://{{port}}-main-workspace-name-user-name.coder.com"`
2020
and the output should replace `{{port}}` with port used in input url.
2121

22+
This also enables the forwared ports view panel by default.
23+
24+
Lastly, it adds a tunnelProvider so that ports are forwarded using code-server's
25+
built-in proxy. You can test this by starting a server i.e. `python3 -m
26+
http.server` and it should show a notification and show up in the ports panel
27+
using the /proxy/port.
28+
2229
Index: code-server/lib/vscode/src/vs/base/common/product.ts
2330
===================================================================
2431
--- 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
7784
rootEndpoint: base,
7885
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
7986
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
80-
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}',
87+
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
8188
embedderIdentifier: 'server-distro',
8289
extensionsGallery: this._productService.extensionsGallery,
8390
},
@@ -115,21 +122,21 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
115122
import type { IURLCallbackProvider } from 'vs/workbench/services/url/browser/urlService';
116123
import type { IWorkbenchConstructionOptions } from 'vs/workbench/browser/web.api';
117124
import type { IWorkspace, IWorkspaceProvider } from 'vs/workbench/services/host/browser/browserHostService';
118-
+import { extractLocalHostUriMetaDataForPortMapping } from 'vs/platform/tunnel/common/tunnel';
125+
+import { extractLocalHostUriMetaDataForPortMapping, TunnelOptions, TunnelCreationOptions } from 'vs/platform/tunnel/common/tunnel';
119126

120127
interface ICredential {
121128
service: string;
122-
@@ -511,6 +512,21 @@ function doCreateUri(path: string, query
129+
@@ -511,6 +512,38 @@ function doCreateUri(path: string, query
123130
} : undefined,
124131
workspaceProvider: WorkspaceProvider.create(config),
125132
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
126133
- credentialsProvider: config.remoteAuthority ? undefined : new LocalStorageCredentialsProvider() // with a remote, we don't use a local credentials provider
127134
+ credentialsProvider: config.remoteAuthority ? undefined : new LocalStorageCredentialsProvider(), // with a remote, we don't use a local credentials provider
128135
+ resolveExternalUri: (uri: URI): Promise<URI> => {
129136
+ let resolvedUri = uri
130-
+ const localhostMatch = extractLocalHostUriMetaDataForPortMapping(uri)
137+
+ const localhostMatch = extractLocalHostUriMetaDataForPortMapping(resolvedUri)
131138
+
132-
+ if (localhostMatch) {
139+
+ if (localhostMatch && resolvedUri.authority !== location.host) {
133140
+ if (config.productConfiguration && config.productConfiguration.proxyEndpointTemplate) {
134141
+ resolvedUri = URI.parse(new URL(config.productConfiguration.proxyEndpointTemplate.replace('{{port}}', localhostMatch.port.toString()), window.location.href).toString())
135142
+ } else {
@@ -139,6 +146,36 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
139146
+
140147
+ // If not localhost, return unmodified
141148
+ return Promise.resolve(resolvedUri)
149+
+ },
150+
+ tunnelProvider: {
151+
+ tunnelFactory: (tunnelOptions: TunnelOptions, tunnelCreationOptions: TunnelCreationOptions) => {
152+
+ const onDidDispose: Emitter<void> = new Emitter();
153+
+ let isDisposed = false;
154+
+ return Promise.resolve({
155+
+ remoteAddress: tunnelOptions.remoteAddress,
156+
+ localAddress: `localhost:${tunnelOptions.remoteAddress.port}`,
157+
+ onDidDispose: onDidDispose.event,
158+
+ dispose: () => {
159+
+ if (!isDisposed) {
160+
+ isDisposed = true;
161+
+ onDidDispose.fire();
162+
+ }
163+
+ }
164+
+ })
165+
+ }
142166
+ }
143167
});
144168
})();
169+
Index: code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
170+
===================================================================
171+
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
172+
+++ code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
173+
@@ -73,7 +73,7 @@ export class ForwardedPortsView extends
174+
this.contextKeyListener = undefined;
175+
}
176+
177+
- const viewEnabled: boolean = !!forwardedPortsViewEnabled.getValue(this.contextKeyService);
178+
+ const viewEnabled: boolean = true;
179+
180+
if (this.environmentService.remoteAuthority && viewEnabled) {
181+
const viewContainer = await this.getViewContainer();

patches/service-worker.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
5757
@@ -316,6 +316,10 @@ export class WebClientServer {
5858
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
5959
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
60-
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}',
60+
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
6161
+ serviceWorker: {
6262
+ scope: vscodeBase + '/',
6363
+ path: base + '/_static/out/browser/serviceWorker.js',

test/e2e/extensions.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function runTestExtensionTests() {
1515
const text = await codeServerPage.page.locator("text=proxyUri").first().textContent()
1616
// Remove end slash in address
1717
const normalizedAddress = address.replace(/\/+$/, "")
18-
expect(text).toBe(`Info: proxyUri: ${normalizedAddress}/proxy/{{port}}`)
18+
expect(text).toBe(`Info: proxyUri: ${normalizedAddress}/proxy/{{port}}/`)
1919
})
2020
}
2121

0 commit comments

Comments
 (0)