Skip to content

Commit ccb599b

Browse files
committed
Add proxy template paths.
cc @code-asher
1 parent 42bfedf commit ccb599b

File tree

6 files changed

+72
-23
lines changed

6 files changed

+72
-23
lines changed

src/vs/base/common/product.ts

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export interface IProductConfiguration {
3636
readonly codeServerVersion?: string;
3737
readonly authed?: boolean;
3838
readonly logoutEndpointUrl: string;
39+
readonly proxyEndpointUrlTemplate?: string;
3940
readonly serviceWorker?: {
4041
readonly url: string;
4142
readonly scope: string;

src/vs/platform/remote/browser/remoteAuthorityResolverService.ts

+31-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { Emitter } from 'vs/base/common/event';
77
import { Disposable } from 'vs/base/common/lifecycle';
88
import { RemoteAuthorities } from 'vs/base/common/network';
99
import { URI } from 'vs/base/common/uri';
10-
import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
10+
import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolvedOptions, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
1111

1212
export class RemoteAuthorityResolverService extends Disposable implements IRemoteAuthorityResolverService {
1313

@@ -20,7 +20,11 @@ export class RemoteAuthorityResolverService extends Disposable implements IRemot
2020
private readonly _connectionToken: string | undefined;
2121
private readonly _connectionTokens: Map<string, string>;
2222

23-
constructor(connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined) {
23+
constructor(
24+
connectionToken: string | undefined,
25+
resourceUriProvider: ((uri: URI) => URI) | undefined,
26+
/** @coder */
27+
private readonly proxyEndpointUrlTemplate?: string,) {
2428
super();
2529
this._cache = new Map<string, ResolverResult>();
2630
this._connectionToken = connectionToken;
@@ -59,11 +63,34 @@ export class RemoteAuthorityResolverService extends Disposable implements IRemot
5963

6064
private _doResolveAuthority(authority: string): ResolverResult {
6165
const connectionToken = this._connectionTokens.get(authority) || this._connectionToken;
66+
let host = authority;
67+
let port = 80;
68+
let options: ResolvedOptions | undefined;
69+
6270
if (authority.indexOf(':') >= 0) {
6371
const pieces = authority.split(':');
64-
return { authority: { authority, host: pieces[0], port: parseInt(pieces[1], 10), connectionToken } };
72+
host = pieces[0];
73+
port = parseInt(pieces[1], 10);
74+
}
75+
76+
/** @coder */
77+
if (this.proxyEndpointUrlTemplate) {
78+
options = {
79+
extensionHostEnv: {
80+
VSCODE_PROXY_URI: this.proxyEndpointUrlTemplate,
81+
},
82+
};
6583
}
66-
return { authority: { authority, host: authority, port: 80, connectionToken } };
84+
85+
return {
86+
authority: {
87+
authority,
88+
host,
89+
port,
90+
connectionToken,
91+
},
92+
options,
93+
};
6794
}
6895

6996
_clearResolvedAuthority(authority: string): void {

src/vs/server/services/environmentService.ts

+4
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ export class EnvironmentServerService extends NativeEnvironmentService implement
109109
sizes: '512x512',
110110
},
111111
],
112+
113+
// Proxy
114+
/** The URL constructor should be decoded here to retain the port template variable. */
115+
proxyEndpointUrlTemplate: decodeURI(this.createRequestUrl(req, AssetPaths.ProxyUri).toString()),
112116
};
113117

114118
if (!this.configuration.disableUpdateCheck) {

src/vs/server/services/net/abstractIncomingRequestService.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55

66
import * as http from 'http';
77
import * as net from 'net';
8-
import * as path from 'path';
98
import { Disposable } from 'vs/base/common/lifecycle';
109
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
1110
import { ILogService } from 'vs/platform/log/common/log';
1211
import { IEnvironmentServerService } from 'vs/server/services/environmentService';
12+
import { getPathPrefix } from 'vs/server/services/net/common/http';
1313

1414
export interface ParsedRequest extends http.IncomingMessage {
1515
parsedUrl: URL;
@@ -40,7 +40,7 @@ export abstract class AbstractIncomingRequestService<E extends NetEventListener>
4040

4141
Object.assign(req, {
4242
parsedUrl,
43-
pathPrefix: path.join(path.dirname(parsedUrl.pathname), '/'),
43+
pathPrefix: getPathPrefix(parsedUrl.pathname),
4444
});
4545

4646
this.eventListener(req as ParsedRequest, ...args);

src/vs/server/services/net/common/http.ts

+22-6
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,23 @@
66
import { randomBytes } from 'crypto';
77
import { readFileSync } from 'fs';
88
import { ServerResponse } from 'http';
9-
import { join } from 'path';
9+
import * as path from 'path';
1010
import { MatchResult } from 'path-to-regexp';
1111
import { UriComponents } from 'vs/base/common/uri';
1212
import { ParsedRequest } from 'vs/server/services/net/abstractIncomingRequestService';
1313
import * as Handlebars from 'handlebars';
1414
import { IWorkbenchConfigurationSerialized } from 'vs/platform/workspaces/common/workbench';
1515

16-
export const APP_ROOT = join(__dirname, '..', '..', '..', '..', '..', '..');
17-
export const WORKBENCH_PATH = join(APP_ROOT, 'out', 'vs', 'code', 'browser', 'workbench');
16+
export const APP_ROOT = path.join(__dirname, '..', '..', '..', '..', '..', '..');
17+
export const WORKBENCH_PATH = path.join(APP_ROOT, 'out', 'vs', 'code', 'browser', 'workbench');
1818
export const SERVICE_WORKER_FILE_NAME = 'service-worker.js';
1919

2020
export const AssetPaths = {
2121
StaticBase: '/static',
22-
Webview: join(APP_ROOT, 'out', 'vs', 'workbench', 'contrib', 'webview', 'browser', 'pre'),
23-
Favicon: join(APP_ROOT, 'resources', 'web', 'favicon.ico'),
24-
ServiceWorker: join(APP_ROOT, 'out', 'vs', 'code', 'browser', 'workbench', SERVICE_WORKER_FILE_NAME),
22+
ProxyUri: '/proxy/{port}',
23+
Webview: path.join(APP_ROOT, 'out', 'vs', 'workbench', 'contrib', 'webview', 'browser', 'pre'),
24+
Favicon: path.join(APP_ROOT, 'resources', 'web', 'favicon.ico'),
25+
ServiceWorker: path.join(APP_ROOT, 'out', 'vs', 'code', 'browser', 'workbench', SERVICE_WORKER_FILE_NAME),
2526
};
2627

2728
/** Matching the given keys in `PollingURLCallbackProvider.QUERY_KEYS` */
@@ -142,3 +143,18 @@ export interface ClientTheme {
142143
backgroundColor: string;
143144
foregroundColor: string;
144145
}
146+
147+
/**
148+
* Returns the relative path prefix for a given URL path.
149+
* @remark This is especially useful when creating URLs which have to remain
150+
* relative to an initial request.
151+
*
152+
* @example
153+
* ```ts
154+
* const url = new URL('https://www.example.com/foo/bar/baz.js')
155+
* getPathPrefix(url.pathname) // '/foo/bar/'
156+
* ```
157+
*/
158+
export function getPathPrefix(pathname: string) {
159+
return path.join(path.dirname(pathname), '/');
160+
}

src/vs/workbench/browser/web.main.ts

+12-11
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ import { HTMLFileSystemProvider } from 'vs/platform/files/browser/htmlFileSystem
6666
import { IOpenerService } from 'vs/platform/opener/common/opener';
6767
import { safeStringify } from 'vs/base/common/objects';
6868
import { CodeServerClientAdditions } from './client';
69-
import { isWeb } from 'vs/base/common/platform';
7069

7170
class BrowserMain extends Disposable {
7271

@@ -100,17 +99,14 @@ class BrowserMain extends Disposable {
10099
const instantiationService = workbench.startup();
101100

102101

103-
if (isWeb) {
104-
/** @coder Initialize our own client-side additions. */
105-
if (!this.configuration.productConfiguration) {
106-
throw new Error('`productConfiguration` not present in workbench config');
107-
}
108-
109-
const codeServerClientAdditions = this._register(instantiationService.createInstance(CodeServerClientAdditions, this.configuration.productConfiguration));
110-
111-
await codeServerClientAdditions.startup();
102+
/** @coder Initialize our own client-side additions. */
103+
if (!this.configuration.productConfiguration) {
104+
throw new Error('`productConfiguration` not present in workbench config');
112105
}
113106

107+
const codeServerClientAdditions = this._register(instantiationService.createInstance(CodeServerClientAdditions, this.configuration.productConfiguration));
108+
109+
await codeServerClientAdditions.startup();
114110

115111
// Window
116112
this._register(instantiationService.createInstance(BrowserWindow));
@@ -183,7 +179,12 @@ class BrowserMain extends Disposable {
183179

184180
// Remote
185181
const connectionToken = environmentService.options.connectionToken || getCookieValue('vscode-tkn');
186-
const remoteAuthorityResolverService = new RemoteAuthorityResolverService(connectionToken, this.configuration.resourceUriProvider);
182+
const remoteAuthorityResolverService = new RemoteAuthorityResolverService(
183+
connectionToken,
184+
this.configuration.resourceUriProvider,
185+
/** @coder */
186+
this.configuration.productConfiguration?.proxyEndpointUrlTemplate,
187+
);
187188
serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService);
188189

189190
// Signing

0 commit comments

Comments
 (0)