Skip to content

Commit

Permalink
bring proxy stuff together
Browse files Browse the repository at this point in the history
add http.proxyStrictSSL option

fixes microsoft#155
  • Loading branch information
joaomoreno committed Dec 1, 2015
1 parent 9b6bff1 commit eaa5bcf
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 54 deletions.
11 changes: 11 additions & 0 deletions src/typings/https-proxy-agent.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,19 @@

declare module 'https-proxy-agent' {

import * as tls from 'tls';

interface IHttpsProxyAgentOptions extends tls.ConnectionOptions {
host: string;
port: number;
secureProxy?: boolean;
secureEndpoint?: boolean;
}

class HttpsProxyAgent {
constructor(proxy: string);
constructor(opts: IHttpsProxyAgentOptions);
}

export = HttpsProxyAgent;
}
34 changes: 0 additions & 34 deletions src/vs/base/node/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import http = require('http');
import { Url, parse as parseUrl } from 'url';
import { createWriteStream } from 'fs';
import { assign } from 'vs/base/common/objects';
import HttpProxyAgent = require('http-proxy-agent');
import HttpsProxyAgent = require('https-proxy-agent');

export interface IRequestOptions {
type?: string;
Expand Down Expand Up @@ -100,36 +98,4 @@ export function json<T>(opts: IRequestOptions): TPromise<T> {
pair.res.on('end', () => c(JSON.parse(buffer.join(''))));
pair.res.on('error', e);
}));
}

function getSystemProxyURI(requestURL: Url): string {
if (requestURL.protocol === 'http:') {
return process.env.HTTP_PROXY || process.env.http_proxy || null;
} else if (requestURL.protocol === 'https:') {
return process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy || null;
}

return null;
}

export function getProxyAgent(rawRequestURL: string, proxyURL: string): any {
let requestURL = parseUrl(rawRequestURL);
let proxyEndpoint = parseUrl(proxyURL);

if (!/^https?:$/.test(proxyEndpoint.protocol)) {
return null;
}

return requestURL.protocol === 'http:' ? new HttpProxyAgent(proxyURL) : new HttpsProxyAgent(proxyURL);
}

export function getSystemProxyAgent(rawRequestURL: string): any {
let requestURL = parseUrl(rawRequestURL);
let proxyURL = getSystemProxyURI(requestURL);

if (!proxyURL) {
return null;
}

return getProxyAgent(rawRequestURL, proxyURL);
}
16 changes: 9 additions & 7 deletions src/vs/workbench/electron-main/win32/auto-updater.win32.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import {ClientRequest} from 'http';
import {mkdirp} from 'vs/base/node/extfs';
import {isString} from 'vs/base/common/types';
import {Promise, TPromise} from 'vs/base/common/winjs.base';
import {IRequestOptions, download, json, getProxyAgent, getSystemProxyAgent} from 'vs/base/node/request';
import {IRequestOptions, download, json } from 'vs/base/node/request';
import { getProxyAgent } from 'vs/workbench/node/proxy';
import {manager as Settings} from 'vs/workbench/electron-main/settings';
import {manager as Lifecycle} from 'vs/workbench/electron-main/lifecycle';

Expand Down Expand Up @@ -53,11 +54,11 @@ export class Win32AutoUpdaterImpl extends events.EventEmitter implements IAutoUp

this.emit('checking-for-update');

const httpProxySettings = Settings.getValue('http.proxy');
const getAgent = url => httpProxySettings ? getProxyAgent(url, httpProxySettings) : getSystemProxyAgent(url);
const proxyUrl = Settings.getValue('http.proxy');
const strictSSL = Settings.getValue('http.proxy.strictSSL', true);
const agent = getProxyAgent(this.url, { proxyUrl, strictSSL });

this.currentRequest =
json<IUpdate>({ url: this.url, agent: getAgent(this.url) })
this.currentRequest = json<IUpdate>({ url: this.url, agent })
.then(update => {
if (!update || !update.url || !update.version) {
this.emit('update-not-available');
Expand All @@ -73,9 +74,10 @@ export class Win32AutoUpdaterImpl extends events.EventEmitter implements IAutoUp
return TPromise.as(updatePackagePath);
}

let downloadPath = `${updatePackagePath}.tmp`;
const downloadPath = `${updatePackagePath}.tmp`;
const agent = getProxyAgent(update.url, { proxyUrl, strictSSL });

return download(downloadPath, { url: update.url, agent: getAgent(update.url) })
return download(downloadPath, { url: update.url, agent })
.then(() => pfs.rename(downloadPath, updatePackagePath))
.then(() => updatePackagePath);
});
Expand Down
58 changes: 58 additions & 0 deletions src/vs/workbench/node/proxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Url, parse as parseUrl } from 'url';
import HttpProxyAgent = require('http-proxy-agent');
import HttpsProxyAgent = require('https-proxy-agent');

function getAgent(rawRequestURL: string, proxyURL: string, strictSSL: boolean = true): any {
let requestURL = parseUrl(rawRequestURL);
let proxyEndpoint = parseUrl(proxyURL);

if (!/^https?:$/.test(proxyEndpoint.protocol)) {
return null;
}

if (requestURL.protocol === 'http:') {
return new HttpProxyAgent(proxyURL);
}

return new HttpsProxyAgent({
host: proxyEndpoint.host,
port: Number(proxyEndpoint.port),
rejectUnauthorized: strictSSL
});
}

function getSystemProxyURI(requestURL: Url): string {
if (requestURL.protocol === 'http:') {
return process.env.HTTP_PROXY || process.env.http_proxy || null;
} else if (requestURL.protocol === 'https:') {
return process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy || null;
}

return null;
}

function getSystemProxyAgent(rawRequestURL: string): any {
let requestURL = parseUrl(rawRequestURL);
let proxyURL = getSystemProxyURI(requestURL);

if (!proxyURL) {
return null;
}

return getAgent(rawRequestURL, proxyURL);
}

export interface IOptions {
proxyUrl?: string;
strictSSL?: boolean;
}

export function getProxyAgent(rawRequestURL: string, options: IOptions = {}): any {
console.log(rawRequestURL, options);

if (!options.proxyUrl) {
return getSystemProxyAgent(rawRequestURL);
}

return getAgent(rawRequestURL, options.proxyUrl, options.strictSSL);
}
32 changes: 19 additions & 13 deletions src/vs/workbench/parts/extensions/node/extensionsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import { assign } from 'vs/base/common/objects';
import { extract, buffer } from 'vs/base/node/zip';
import { Promise, TPromise } from 'vs/base/common/winjs.base';
import { IExtensionsService, IExtension, IExtensionManifest, IGalleryInformation } from 'vs/workbench/parts/extensions/common/extensions';
import { download, getProxyAgent, getSystemProxyAgent } from 'vs/base/node/request';
import { download } from 'vs/base/node/request';
import { getProxyAgent } from 'vs/workbench/node/proxy';
import { IWorkspaceContextService } from 'vs/workbench/services/workspace/common/contextService';
import { Limiter } from 'vs/base/common/async';
import Event, { Emitter } from 'vs/base/common/event';
Expand Down Expand Up @@ -121,18 +122,23 @@ export class ExtensionsService implements IExtensionsService {
const extensionPath = path.join(this.extensionsPath, `${ extension.publisher }.${ extension.name }`);
const manifestPath = path.join(extensionPath, 'package.json');

return UserSettings.getValue(this.contextService, 'http.proxy').then((httpProxySettings) => {
const getAgent = url => httpProxySettings ? getProxyAgent(url, httpProxySettings) : getSystemProxyAgent(url);
return download(zipPath, { url: url, agent: getAgent(url) })
.then(() => validate(zipPath, extension))
.then(manifest => { this._onInstallExtension.fire(manifest); return manifest; })
.then(manifest => extract(zipPath, extensionPath, { sourcePath: 'extension', overwrite: true }).then(() => manifest))
.then(manifest => {
manifest = assign({ __metadata: galleryInformation }, manifest);
return pfs.writeFile(manifestPath, JSON.stringify(manifest, null, '\t'));
})
.then(() => { this._onDidInstallExtension.fire(extension); return extension; });
});
const settings = TPromise.join([
UserSettings.getValue(this.contextService, 'http.proxy'),
UserSettings.getValue(this.contextService, 'http.proxy.strictSSL')
]);

return settings
.then(settings => ({ proxyUrl: settings[0], strictSSL: settings[1] }))
.then(options => getProxyAgent(url, options))
.then(agent => download(zipPath, { url, agent }))
.then(() => validate(zipPath, extension))
.then(manifest => { this._onInstallExtension.fire(manifest); return manifest; })
.then(manifest => extract(zipPath, extensionPath, { sourcePath: 'extension', overwrite: true }).then(() => manifest))
.then(manifest => {
manifest = assign({ __metadata: galleryInformation }, manifest);
return pfs.writeFile(manifestPath, JSON.stringify(manifest, null, '\t'));
})
.then(() => { this._onDidInstallExtension.fire(extension); return extension; });
}

private installFromZip(zipPath: string): TPromise<IExtension> {
Expand Down
5 changes: 5 additions & 0 deletions src/vs/workbench/services/request/node/requestService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ confRegistry.registerConfiguration({
'http.proxy': {
'type': 'string',
'description': nls.localize('proxy', "The proxy setting to use. If not set will be taken from the http_proxy and https_proxy environment variables")
},
'http.proxyStrictSSL': {
'type': 'boolean',
'default': true,
'description': nls.localize('strictSSL', "Whether the proxy server certificate should be verified against the list of supplied CAs.")
}
}
});

0 comments on commit eaa5bcf

Please sign in to comment.