From 29f6436c9896d42aaa5c57a579327687f79157e0 Mon Sep 17 00:00:00 2001 From: develar Date: Sun, 11 Sep 2016 15:11:05 +0200 Subject: [PATCH] fix: proxy config from npm #585 --- .idea/dictionaries/develar.xml | 1 + nsis-auto-updater/package.json | 4 +- package.json | 3 +- src/publish/restApiRequest.ts | 2 +- src/util/filter.ts | 2 +- src/util/httpRequest.ts | 77 +++++++++++++++++++++++++--------- 6 files changed, 66 insertions(+), 23 deletions(-) diff --git a/.idea/dictionaries/develar.xml b/.idea/dictionaries/develar.xml index 34f3cf876a2..5450db6c8fe 100644 --- a/.idea/dictionaries/develar.xml +++ b/.idea/dictionaries/develar.xml @@ -77,6 +77,7 @@ nokeys nomacver noninteractive + npmrc nsis nuget nupkg diff --git a/nsis-auto-updater/package.json b/nsis-auto-updater/package.json index 113431dcb3a..d0e9ccda121 100644 --- a/nsis-auto-updater/package.json +++ b/nsis-auto-updater/package.json @@ -14,7 +14,9 @@ "dependencies": { "bluebird": "^3.4.6", "fs-extra-p": "^1.1.8", - "semver": "^5.3.0" + "semver": "^5.3.0", + "ini": "^1.3.4", + "tunnel-agent": "^0.4.3" }, "bundledDependencies": [ "fs-extra-p", diff --git a/package.json b/package.json index 68985383587..5ac7e077a8d 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "fs-extra-p": "^1.1.8", "hosted-git-info": "^2.1.5", "image-size": "^0.5.0", + "ini": "^1.3.4", "isbinaryfile": "^3.0.1", "lodash.template": "^4.4.0", "mime": "^1.3.4", @@ -122,7 +123,7 @@ "json8": "^0.9.2", "path-sort": "^0.1.0", "pre-git": "^3.10.0", - "ts-babel": "^1.0.7", + "ts-babel": "^1.0.10", "tslint": "^3.15.1", "typescript": "^2.0.2", "whitespace": "^2.1.0" diff --git a/src/publish/restApiRequest.ts b/src/publish/restApiRequest.ts index 690ed9618eb..eaaefde71ea 100644 --- a/src/publish/restApiRequest.ts +++ b/src/publish/restApiRequest.ts @@ -50,7 +50,7 @@ export function doApiRequest(options: RequestOptions, token: string | null, r // error is clear, we don't need to read detailed error description reject(new HttpError(response, `method: ${options.method} url: https://${options.hostname}${options.path} -Please double check that your GitHub Token is correct. Due to security reasons GitHub doesn't report actual status, but 404. +Please double check that your authentication token is correct. Due to security reasons actual status maybe not reported, but 404. `)) } else if (response.statusCode === 204) { diff --git a/src/util/filter.ts b/src/util/filter.ts index bc5cd3637fb..f2cbd7f0e33 100644 --- a/src/util/filter.ts +++ b/src/util/filter.ts @@ -2,10 +2,10 @@ import { copy, Stats } from "fs-extra-p" import { Minimatch } from "minimatch" import * as path from "path" import { Promise as BluebirdPromise } from "bluebird" +const readInstalled = require("read-installed") //noinspection JSUnusedLocalSymbols const __awaiter = require("./awaiter") -const readInstalled = require("read-installed") // we use relative path to avoid canonical path issue - e.g. /tmp vs /private/tmp export function copyFiltered(src: string, destination: string, filter: Filter, dereference: boolean): Promise { diff --git a/src/util/httpRequest.ts b/src/util/httpRequest.ts index 45155b6f49c..983003fd5db 100644 --- a/src/util/httpRequest.ts +++ b/src/util/httpRequest.ts @@ -1,12 +1,16 @@ import { Socket } from "net" -import { IncomingMessage, ClientRequest } from "http" +import { IncomingMessage, ClientRequest, Agent } from "http" import * as https from "https" -import { createWriteStream, ensureDir } from "fs-extra-p" +import { createWriteStream, ensureDir, readFile } from "fs-extra-p" import { parse as parseUrl } from "url" import { Promise as BluebirdPromise } from "bluebird" import * as path from "path" import { createHash } from "crypto" import { Transform } from "stream" +import { homedir } from "os" + +//noinspection JSUnusedLocalSymbols +const __awaiter = require("./awaiter") const maxRedirects = 10 @@ -15,14 +19,20 @@ export interface DownloadOptions { sha2?: string } -export const download = <(url: string, destination: string, options?: DownloadOptions) => BluebirdPromise>(BluebirdPromise.promisify(_download)) +let httpsAgent: Promise | null = null -function _download(url: string, destination: string, options: DownloadOptions | null | undefined, callback: (error: Error) => void): void { - if (callback == null) { - callback = options - options = null - } - doDownload(url, destination, 0, options || {}, callback) +export function download(url: string, destination: string, options?: DownloadOptions | null): BluebirdPromise { + return >(httpsAgent || (httpsAgent = createAgent())) + .then(it => new BluebirdPromise(function (resolve, reject) { + doDownload(url, destination, 0, options || {}, it, error => { + if (error == null) { + resolve() + } + else { + reject(error) + } + }) + })) } export function addTimeOutHandler(request: ClientRequest, callback: (error: Error) => void) { @@ -34,7 +44,7 @@ export function addTimeOutHandler(request: ClientRequest, callback: (error: Erro }) } -function doDownload(url: string, destination: string, redirectCount: number, options: DownloadOptions, callback: (error: Error | null) => void) { +function doDownload(url: string, destination: string, redirectCount: number, options: DownloadOptions, agent: Agent, callback: (error: Error | null) => void) { const ensureDirPromise = options.skipDirCreation ? BluebirdPromise.resolve() : ensureDir(path.dirname(destination)) const parsedUrl = parseUrl(url) @@ -45,7 +55,7 @@ function doDownload(url: string, destination: string, redirectCount: number, opt headers: { "User-Agent": "electron-builder" }, - agent: createAgent("https"), + agent: agent, }, (response: IncomingMessage) => { if (response.statusCode >= 400) { callback(new Error(`Cannot download "${url}", status ${response.statusCode}: ${response.statusMessage}`)) @@ -55,7 +65,7 @@ function doDownload(url: string, destination: string, redirectCount: number, opt const redirectUrl = response.headers.location if (redirectUrl != null) { if (redirectCount < maxRedirects) { - doDownload(redirectUrl, destination, redirectCount++, options, callback) + doDownload(redirectUrl, destination, redirectCount++, options, agent, callback) } else { callback(new Error("Too many redirects (> " + maxRedirects + ")")) @@ -124,20 +134,49 @@ class DigestTransform extends Transform { } } -function createAgent(uriProtocol: string) { - const proxyString: string = process.env.HTTPS_PROXY || - process.env.https_proxy || - process.env.HTTP_PROXY || - process.env.http_proxy +// only https proxy +async function proxyFromNpm() { + let data = "" + try { + data = await readFile(path.join(homedir(), ".npmrc"), "utf-8") + } + catch (ignored) { + return null + } - if (!proxyString) { + if (!data) { return null } + try { + const config = require("ini").parse(data) + return config["https-proxy"] || config.proxy + } + catch (e) { + // used in nsis auto-updater, do not use .util.warn here + console.warn(e) + return null + } +} + +// only https url +async function createAgent() { + let proxyString: string = + process.env.npm_config_https_proxy || + process.env.HTTPS_PROXY || process.env.https_proxy || + process.env.npm_config_proxy + + if (!proxyString) { + proxyString = await proxyFromNpm() + if (!proxyString) { + return null + } + } + const proxy = parseUrl(proxyString) const proxyProtocol = proxy.protocol === "https:" ? "Https" : "Http" - return require("tunnel-agent")[`${uriProtocol}Over${proxyProtocol}`]({ + return require("tunnel-agent")[`httpsOver${proxyProtocol}`]({ proxy: { port: proxy.port || (proxyProtocol === "Https" ? 443 : 80), host: proxy.hostname,