From 900286b1fb76437d8274cff60b45baaac598db05 Mon Sep 17 00:00:00 2001 From: decaffeinate Date: Thu, 20 Feb 2020 12:04:58 -0500 Subject: [PATCH] decaffeinate: Run post-processing cleanups on ca.coffee and 11 other files --- packages/https-proxy/lib/ca.js | 298 +++++----- packages/https-proxy/lib/proxy.js | 24 +- packages/https-proxy/lib/server.js | 435 ++++++++------- packages/https-proxy/lib/util/parse.js | 60 +- packages/https-proxy/test/helpers/certs.js | 18 +- .../https-proxy/test/helpers/http_server.js | 47 +- .../https-proxy/test/helpers/https_server.js | 71 ++- packages/https-proxy/test/helpers/proxy.js | 123 ++-- .../test/integration/proxy_spec.js | 528 ++++++++++-------- packages/https-proxy/test/spec_helper.js | 37 +- packages/https-proxy/test/unit/ca_spec.js | 158 +++--- packages/https-proxy/test/unit/server_spec.js | 194 ++++--- 12 files changed, 1074 insertions(+), 919 deletions(-) diff --git a/packages/https-proxy/lib/ca.js b/packages/https-proxy/lib/ca.js index 61d3a6cd6d..6f02d465d7 100644 --- a/packages/https-proxy/lib/ca.js +++ b/packages/https-proxy/lib/ca.js @@ -1,262 +1,268 @@ +// TODO: This file was created by bulk-decaffeinate. +// Sanity-check the conversion and remove this comment. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const _ = require("lodash"); -let fs = require("fs-extra"); -const os = require("os"); -const path = require("path"); -const Forge = require("node-forge"); -const Promise = require("bluebird"); +const _ = require('lodash') +let fs = require('fs-extra') +const os = require('os') +const path = require('path') +const Forge = require('node-forge') +const Promise = require('bluebird') -fs = Promise.promisifyAll(fs); +fs = Promise.promisifyAll(fs) const { - pki -} = Forge; + pki, +} = Forge -const generateKeyPairAsync = Promise.promisify(pki.rsa.generateKeyPair); +const generateKeyPairAsync = Promise.promisify(pki.rsa.generateKeyPair) -const ipAddressRe = /^[\d\.]+$/; -const asterisksRe = /\*/g; +const ipAddressRe = /^[\d\.]+$/ +const asterisksRe = /\*/g const CAattrs = [{ - name: "commonName", - value: "CypressProxyCA" + name: 'commonName', + value: 'CypressProxyCA', }, { - name: "countryName", - value: "Internet" + name: 'countryName', + value: 'Internet', }, { - shortName: "ST", - value: "Internet" + shortName: 'ST', + value: 'Internet', }, { - name: "localityName", - value: "Internet" + name: 'localityName', + value: 'Internet', }, { - name: "organizationName", - value: "Cypress.io" + name: 'organizationName', + value: 'Cypress.io', }, { - shortName: "OU", - value: "CA" -}]; + shortName: 'OU', + value: 'CA', +}] const CAextensions = [{ - name: "basicConstraints", - cA: true + name: 'basicConstraints', + cA: true, }, { - name: "keyUsage", + name: 'keyUsage', keyCertSign: true, digitalSignature: true, nonRepudiation: true, keyEncipherment: true, - dataEncipherment: true + dataEncipherment: true, }, { - name: "extKeyUsage", + name: 'extKeyUsage', serverAuth: true, clientAuth: true, codeSigning: true, emailProtection: true, - timeStamping: true + timeStamping: true, }, { - name: "nsCertType", + name: 'nsCertType', client: true, server: true, email: true, objsign: true, sslCA: true, emailCA: true, - objCA: true + objCA: true, }, { - name: "subjectKeyIdentifier" -}]; + name: 'subjectKeyIdentifier', +}] const ServerAttrs = [{ - name: "countryName", - value: "Internet" + name: 'countryName', + value: 'Internet', }, { - shortName: "ST", - value: "Internet" + shortName: 'ST', + value: 'Internet', }, { - name: "localityName", - value: "Internet" + name: 'localityName', + value: 'Internet', }, { - name: "organizationName", - value: "Cypress Proxy CA" + name: 'organizationName', + value: 'Cypress Proxy CA', }, { - shortName: "OU", - value: "Cypress Proxy Server Certificate" -}]; + shortName: 'OU', + value: 'Cypress Proxy Server Certificate', +}] const ServerExtensions = [{ - name: "basicConstraints", - cA: false + name: 'basicConstraints', + cA: false, }, { - name: "keyUsage", + name: 'keyUsage', keyCertSign: false, digitalSignature: true, nonRepudiation: false, keyEncipherment: true, - dataEncipherment: true + dataEncipherment: true, }, { - name: "extKeyUsage", + name: 'extKeyUsage', serverAuth: true, clientAuth: true, codeSigning: false, emailProtection: false, - timeStamping: false + timeStamping: false, }, { - name: "nsCertType", + name: 'nsCertType', client: true, server: true, email: false, objsign: false, sslCA: false, emailCA: false, - objCA: false + objCA: false, }, { - name: "subjectKeyIdentifier" -}]; + name: 'subjectKeyIdentifier', +}] class CA { - constructor(caFolder) { + constructor (caFolder) { if (!caFolder) { - caFolder = path.join(os.tmpdir(), 'cy-ca'); + caFolder = path.join(os.tmpdir(), 'cy-ca') } - this.baseCAFolder = caFolder; - this.certsFolder = path.join(this.baseCAFolder, "certs"); - this.keysFolder = path.join(this.baseCAFolder, "keys"); + this.baseCAFolder = caFolder + this.certsFolder = path.join(this.baseCAFolder, 'certs') + this.keysFolder = path.join(this.baseCAFolder, 'keys') } - removeAll() { + removeAll () { return fs .removeAsync(this.baseCAFolder) - .catchReturn({ code: "ENOENT" }); + .catchReturn({ code: 'ENOENT' }) } - randomSerialNumber() { - //# generate random 16 bytes hex string - let sn = ""; + randomSerialNumber () { + // generate random 16 bytes hex string + let sn = '' for (let i = 1; i <= 4; i++) { - sn += ("00000000" + Math.floor(Math.random()*Math.pow(256, 4)).toString(16)).slice(-8); + sn += (`00000000${Math.floor(Math.random() * Math.pow(256, 4)).toString(16)}`).slice(-8) } - return sn; + return sn } - generateCA() { - return generateKeyPairAsync({bits: 512}) - .then(keys => { - const cert = pki.createCertificate(); - cert.publicKey = keys.publicKey; - cert.serialNumber = this.randomSerialNumber(); + generateCA () { + return generateKeyPairAsync({ bits: 512 }) + .then((keys) => { + const cert = pki.createCertificate() - cert.validity.notBefore = new Date(); - cert.validity.notAfter = new Date(); - cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 10); - cert.setSubject(CAattrs); - cert.setIssuer(CAattrs); - cert.setExtensions(CAextensions); - cert.sign(keys.privateKey, Forge.md.sha256.create()); + cert.publicKey = keys.publicKey + cert.serialNumber = this.randomSerialNumber() - this.CAcert = cert; - this.CAkeys = keys; + cert.validity.notBefore = new Date() + cert.validity.notAfter = new Date() + cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 10) + cert.setSubject(CAattrs) + cert.setIssuer(CAattrs) + cert.setExtensions(CAextensions) + cert.sign(keys.privateKey, Forge.md.sha256.create()) + + this.CAcert = cert + this.CAkeys = keys return Promise.all([ - fs.outputFileAsync(path.join(this.certsFolder, "ca.pem"), pki.certificateToPem(cert)), - fs.outputFileAsync(path.join(this.keysFolder, "ca.private.key"), pki.privateKeyToPem(keys.privateKey)), - fs.outputFileAsync(path.join(this.keysFolder, "ca.public.key"), pki.publicKeyToPem(keys.publicKey)) - ]); - }); - } - - loadCA() { - return Promise.props({ - certPEM: fs.readFileAsync(path.join(this.certsFolder, "ca.pem"), "utf-8"), - keyPrivatePEM: fs.readFileAsync(path.join(this.keysFolder, "ca.private.key"), "utf-8"), - keyPublicPEM: fs.readFileAsync(path.join(this.keysFolder, "ca.public.key"), "utf-8") + fs.outputFileAsync(path.join(this.certsFolder, 'ca.pem'), pki.certificateToPem(cert)), + fs.outputFileAsync(path.join(this.keysFolder, 'ca.private.key'), pki.privateKeyToPem(keys.privateKey)), + fs.outputFileAsync(path.join(this.keysFolder, 'ca.public.key'), pki.publicKeyToPem(keys.publicKey)), + ]) }) - .then(results => { - this.CAcert = pki.certificateFromPem(results.certPEM); - return this.CAkeys = { + } + + loadCA () { + return Promise.props({ + certPEM: fs.readFileAsync(path.join(this.certsFolder, 'ca.pem'), 'utf-8'), + keyPrivatePEM: fs.readFileAsync(path.join(this.keysFolder, 'ca.private.key'), 'utf-8'), + keyPublicPEM: fs.readFileAsync(path.join(this.keysFolder, 'ca.public.key'), 'utf-8'), + }) + .then((results) => { + this.CAcert = pki.certificateFromPem(results.certPEM) + + this.CAkeys = { privateKey: pki.privateKeyFromPem(results.keyPrivatePEM), - publicKey: pki.publicKeyFromPem(results.keyPublicPEM) - }; - }) - .return(undefined); + publicKey: pki.publicKeyFromPem(results.keyPublicPEM), + } + }) + .return(undefined) } - generateServerCertificateKeys(hosts) { - hosts = [].concat(hosts); + generateServerCertificateKeys (hosts) { + hosts = [].concat(hosts) - const mainHost = hosts[0]; - const keysServer = pki.rsa.generateKeyPair(1024); - const certServer = pki.createCertificate(); + const mainHost = hosts[0] + const keysServer = pki.rsa.generateKeyPair(1024) + const certServer = pki.createCertificate() - certServer.publicKey = keysServer.publicKey; - certServer.serialNumber = this.randomSerialNumber(); - certServer.validity.notBefore = new Date; - certServer.validity.notAfter = new Date; - certServer.validity.notAfter.setFullYear(certServer.validity.notBefore.getFullYear() + 2); + certServer.publicKey = keysServer.publicKey + certServer.serialNumber = this.randomSerialNumber() + certServer.validity.notBefore = new Date + certServer.validity.notAfter = new Date + certServer.validity.notAfter.setFullYear(certServer.validity.notBefore.getFullYear() + 2) + + const attrsServer = _.clone(ServerAttrs) - const attrsServer = _.clone(ServerAttrs); attrsServer.unshift({ - name: "commonName", - value: mainHost - }); + name: 'commonName', + value: mainHost, + }) - certServer.setSubject(attrsServer); - certServer.setIssuer(this.CAcert.issuer.attributes); + certServer.setSubject(attrsServer) + certServer.setIssuer(this.CAcert.issuer.attributes) certServer.setExtensions(ServerExtensions.concat([{ - name: "subjectAltName", - altNames: hosts.map(function(host) { + name: 'subjectAltName', + altNames: hosts.map((host) => { if (host.match(ipAddressRe)) { - return {type: 7, ip: host}; - } else { - return {type: 2, value: host}; - }}) - }])); + return { type: 7, ip: host } + } - certServer.sign(this.CAkeys.privateKey, Forge.md.sha256.create()); + return { type: 2, value: host } + }), + }])) - const certPem = pki.certificateToPem(certServer); - const keyPrivatePem = pki.privateKeyToPem(keysServer.privateKey); - const keyPublicPem = pki.publicKeyToPem(keysServer.publicKey); + certServer.sign(this.CAkeys.privateKey, Forge.md.sha256.create()) - const dest = mainHost.replace(asterisksRe, "_"); + const certPem = pki.certificateToPem(certServer) + const keyPrivatePem = pki.privateKeyToPem(keysServer.privateKey) + const keyPublicPem = pki.publicKeyToPem(keysServer.publicKey) + + const dest = mainHost.replace(asterisksRe, '_') return Promise.all([ - fs.outputFileAsync(path.join(this.certsFolder, dest + ".pem"), certPem), - fs.outputFileAsync(path.join(this.keysFolder, dest + ".key"), keyPrivatePem), - fs.outputFileAsync(path.join(this.keysFolder, dest + ".public.key"), keyPublicPem) + fs.outputFileAsync(path.join(this.certsFolder, `${dest}.pem`), certPem), + fs.outputFileAsync(path.join(this.keysFolder, `${dest}.key`), keyPrivatePem), + fs.outputFileAsync(path.join(this.keysFolder, `${dest}.public.key`), keyPublicPem), ]) - .return([certPem, keyPrivatePem]); + .return([certPem, keyPrivatePem]) } - getCertificateKeysForHostname(hostname) { - const dest = hostname.replace(asterisksRe, "_"); + getCertificateKeysForHostname (hostname) { + const dest = hostname.replace(asterisksRe, '_') return Promise.all([ - fs.readFileAsync(path.join(this.certsFolder, dest + ".pem")), - fs.readFileAsync(path.join(this.keysFolder, dest + ".key")) - ]); + fs.readFileAsync(path.join(this.certsFolder, `${dest}.pem`)), + fs.readFileAsync(path.join(this.keysFolder, `${dest}.key`)), + ]) } - getCACertPath() { - return path.join(this.certsFolder, "ca.pem"); + getCACertPath () { + return path.join(this.certsFolder, 'ca.pem') } - static create(caFolder) { - const ca = new CA(caFolder); + static create (caFolder) { + const ca = new CA(caFolder) - return fs.statAsync(path.join(ca.certsFolder, "ca.pem")) + return fs.statAsync(path.join(ca.certsFolder, 'ca.pem')) .bind(ca) .then(ca.loadCA) .catch(ca.generateCA) - .return(ca); + .return(ca) } } -module.exports = CA; +module.exports = CA diff --git a/packages/https-proxy/lib/proxy.js b/packages/https-proxy/lib/proxy.js index f9aa31d703..a6d5b2d039 100644 --- a/packages/https-proxy/lib/proxy.js +++ b/packages/https-proxy/lib/proxy.js @@ -1,23 +1,27 @@ +// TODO: This file was created by bulk-decaffeinate. +// Sanity-check the conversion and remove this comment. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const CA = require("./ca"); -const Server = require("./server"); +const CA = require('./ca') +const Server = require('./server') module.exports = { - create(dir, port, options) { + create (dir, port, options) { return CA.create(dir) - .then(ca => Server.create(ca, port, options)); + .then((ca) => { + return Server.create(ca, port, options) + }) }, - reset() { - return Server.reset(); + reset () { + return Server.reset() }, - httpsServer(onRequest) { - return require("../test/helpers/https_server").create(onRequest); - } + httpsServer (onRequest) { + return require('../test/helpers/https_server').create(onRequest) + }, -}; +} diff --git a/packages/https-proxy/lib/server.js b/packages/https-proxy/lib/server.js index 6ddb7e760b..36d467bf4f 100644 --- a/packages/https-proxy/lib/server.js +++ b/packages/https-proxy/lib/server.js @@ -1,360 +1,387 @@ +/* eslint-disable + brace-style, + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const _ = require("lodash"); -const { agent, allowDestroy, connect } = require("@packages/network"); -const debug = require("debug")("cypress:https-proxy"); -let fs = require("fs-extra"); +const _ = require('lodash') +const { agent, allowDestroy, connect } = require('@packages/network') +const debug = require('debug')('cypress:https-proxy') +let fs = require('fs-extra') const { - getProxyForUrl -} = require("proxy-from-env"); -const https = require("https"); -const net = require("net"); -const parse = require("./util/parse"); -const Promise = require("bluebird"); -const semaphore = require("semaphore"); -const url = require("url"); + getProxyForUrl, +} = require('proxy-from-env') +const https = require('https') +const net = require('net') +const parse = require('./util/parse') +const Promise = require('bluebird') +const semaphore = require('semaphore') +const url = require('url') -fs = Promise.promisifyAll(fs); +fs = Promise.promisifyAll(fs) -let sslServers = {}; -let sslIpServers = {}; -const sslSemaphores = {}; +let sslServers = {} +let sslIpServers = {} +const sslSemaphores = {} -//# https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_record +// https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_record const SSL_RECORD_TYPES = [ - 22, //# Handshake - 128, 0 //# TODO: what do these unknown types mean? -]; + 22, // Handshake + 128, 0, // TODO: what do these unknown types mean? +] -let onError = err => //# these need to be caught to avoid crashing but do not affect anything -debug('server error %o', { err }); +let onError = (err) => // these need to be caught to avoid crashing but do not affect anything +{ + return debug('server error %o', { err }) +} class Server { - constructor(_ca, _port, _options) { - this._getServerPortForIp = this._getServerPortForIp.bind(this); - this._ca = _ca; - this._port = _port; - this._options = _options; - this._onError = null; - this._ipServers = sslIpServers; + constructor (_ca, _port, _options) { + this._getServerPortForIp = this._getServerPortForIp.bind(this) + this._ca = _ca + this._port = _port + this._options = _options + this._onError = null + this._ipServers = sslIpServers } - connect(req, browserSocket, head, options = {}) { - //# don't buffer writes - thanks a lot, Nagle - //# https://github.com/cypress-io/cypress/issues/3192 - browserSocket.setNoDelay(true); + connect (req, browserSocket, head, options = {}) { + // don't buffer writes - thanks a lot, Nagle + // https://github.com/cypress-io/cypress/issues/3192 + browserSocket.setNoDelay(true) - debug("Writing browserSocket connection headers %o", { url: req.url, headLength: _.get(head, 'length'), headers: req.headers }); + debug('Writing browserSocket connection headers %o', { url: req.url, headLength: _.get(head, 'length'), headers: req.headers }) - browserSocket.on("error", err => { - //# TODO: shouldn't we destroy the upstream socket here? - //# and also vise versa if the upstream socket throws? - //# we may get this "for free" though because piping will - //# automatically forward the TCP errors...? + browserSocket.on('error', (err) => { + // TODO: shouldn't we destroy the upstream socket here? + // and also vise versa if the upstream socket throws? + // we may get this "for free" though because piping will + // automatically forward the TCP errors...? - //# nothing to do except catch here, the browser has d/c'd - return debug("received error on client browserSocket %o", { - err, url: req.url - }); - }); + // nothing to do except catch here, the browser has d/c'd + return debug('received error on client browserSocket %o', { + err, url: req.url, + }) + }) - browserSocket.write("HTTP/1.1 200 OK\r\n"); + browserSocket.write('HTTP/1.1 200 OK\r\n') - if (req.headers["proxy-connection"] === "keep-alive") { - browserSocket.write("Proxy-Connection: keep-alive\r\n"); - browserSocket.write("Connection: keep-alive\r\n"); + if (req.headers['proxy-connection'] === 'keep-alive') { + browserSocket.write('Proxy-Connection: keep-alive\r\n') + browserSocket.write('Connection: keep-alive\r\n') } - browserSocket.write("\r\n"); + browserSocket.write('\r\n') - //# if we somehow already have the head here - if (_.get(head, "length")) { - //# then immediately make up the connection - return this._onFirstHeadBytes(req, browserSocket, head, options); + // if we somehow already have the head here + if (_.get(head, 'length')) { + // then immediately make up the connection + return this._onFirstHeadBytes(req, browserSocket, head, options) } - //# else once we get it make the connection later - return browserSocket.once("data", data => { - return this._onFirstHeadBytes(req, browserSocket, data, options); - }); + // else once we get it make the connection later + return browserSocket.once('data', (data) => { + return this._onFirstHeadBytes(req, browserSocket, data, options) + }) } - _onFirstHeadBytes(req, browserSocket, head, options) { - let odc; - debug("Got first head bytes %o", { url: req.url, head: _.chain(head).invoke('toString').slice(0, 64).join('').value() }); + _onFirstHeadBytes (req, browserSocket, head, options) { + let odc - browserSocket.pause(); + debug('Got first head bytes %o', { url: req.url, head: _.chain(head).invoke('toString').slice(0, 64).join('').value() }) - if (odc = options.onDirectConnection) { - //# if onDirectConnection return true - //# then dont proxy, just pass this through + browserSocket.pause() + + odc = options.onDirectConnection + + if (odc) { + // if onDirectConnection return true + // then dont proxy, just pass this through if (odc.call(this, req, browserSocket, head) === true) { - return this._makeDirectConnection(req, browserSocket, head); - } else { - debug("Not making direct connection %o", { url: req.url }); + return this._makeDirectConnection(req, browserSocket, head) } + + debug('Not making direct connection %o', { url: req.url }) } - return this._onServerConnectData(req, browserSocket, head); + return this._onServerConnectData(req, browserSocket, head) } - _onUpgrade(fn, req, browserSocket, head) { + _onUpgrade (fn, req, browserSocket, head) { if (fn) { - return fn.call(this, req, browserSocket, head); + return fn.call(this, req, browserSocket, head) } } - _onRequest(fn, req, res) { - const hostPort = parse.hostAndPort(req.url, req.headers, 443); + _onRequest (fn, req, res) { + const hostPort = parse.hostAndPort(req.url, req.headers, 443) req.url = url.format({ - protocol: "https:", + protocol: 'https:', hostname: hostPort.host, - port: hostPort.port - }) + req.url; + port: hostPort.port, + }) + req.url if (fn) { - return fn.call(this, req, res); + return fn.call(this, req, res) } } + _getProxyForUrl (urlStr) { + const port = Number(_.get(url.parse(urlStr), 'port')) - _getProxyForUrl(urlStr) { - const port = Number(_.get(url.parse(urlStr), 'port')); - - debug('getting proxy URL %o', { port, serverPort: this._port, sniPort: this._sniPort, url: urlStr }); + debug('getting proxy URL %o', { port, serverPort: this._port, sniPort: this._sniPort, url: urlStr }) if ([this._sniPort, this._port].includes(port)) { - //# https://github.com/cypress-io/cypress/issues/4257 - //# this is a tunnel to the SNI server or to the main server, - //# it should never go through a proxy - return undefined; + // https://github.com/cypress-io/cypress/issues/4257 + // this is a tunnel to the SNI server or to the main server, + // it should never go through a proxy + return undefined } - return getProxyForUrl(urlStr); + return getProxyForUrl(urlStr) } - _makeDirectConnection(req, browserSocket, head) { - const { port, hostname } = url.parse(`https://${req.url}`); + _makeDirectConnection (req, browserSocket, head) { + const { port, hostname } = url.parse(`https://${req.url}`) - debug(`Making connection to ${hostname}:${port}`); - return this._makeConnection(browserSocket, head, port, hostname); + debug(`Making connection to ${hostname}:${port}`) + + return this._makeConnection(browserSocket, head, port, hostname) } - _makeConnection(browserSocket, head, port, hostname) { - let upstreamProxy; + _makeConnection (browserSocket, head, port, hostname) { + let upstreamProxy const onSocket = (err, upstreamSocket) => { - debug('received upstreamSocket callback for request %o', { port, hostname, err }); + debug('received upstreamSocket callback for request %o', { port, hostname, err }) - onError = err => { - browserSocket.destroy(err); + onError = (err) => { + browserSocket.destroy(err) if (this._onError) { - return this._onError(err, browserSocket, head, port); + return this._onError(err, browserSocket, head, port) } - }; - - if (err) { - return onError(err); } - upstreamSocket.setNoDelay(true); - upstreamSocket.on("error", onError); + if (err) { + return onError(err) + } - browserSocket.emit('upstream-connected', upstreamSocket); + upstreamSocket.setNoDelay(true) + upstreamSocket.on('error', onError) - browserSocket.pipe(upstreamSocket); - upstreamSocket.pipe(browserSocket); - upstreamSocket.write(head); + browserSocket.emit('upstream-connected', upstreamSocket) - return browserSocket.resume(); - }; + browserSocket.pipe(upstreamSocket) + upstreamSocket.pipe(browserSocket) + upstreamSocket.write(head) - if (!port) { port = "443"; } + return browserSocket.resume() + } - if (upstreamProxy = this._getProxyForUrl(`https://${hostname}:${port}`)) { + if (!port) { + port = '443' + } + + upstreamProxy = this._getProxyForUrl(`https://${hostname}:${port}`) + + if (upstreamProxy) { // todo: as soon as all requests are intercepted, this can go away since this is just for pass-through - debug("making proxied connection %o", { + debug('making proxied connection %o', { host: `${hostname}:${port}`, proxy: upstreamProxy, - }); + }) return agent.httpsAgent.createUpstreamProxyConnection({ proxy: upstreamProxy, href: `https://${hostname}:${port}`, uri: { port, - hostname + hostname, }, - shouldRetry: true - }, onSocket); + shouldRetry: true, + }, onSocket) } - return connect.createRetryingSocket({ port, host: hostname }, onSocket); + return connect.createRetryingSocket({ port, host: hostname }, onSocket) } - _onServerConnectData(req, browserSocket, head) { - let sem, sslServer; - const firstBytes = head[0]; + _onServerConnectData (req, browserSocket, head) { + let sem; let sslServer + const firstBytes = head[0] - const makeConnection = port => { - debug("Making intercepted connection to %s", port); + const makeConnection = (port) => { + debug('Making intercepted connection to %s', port) - return this._makeConnection(browserSocket, head, port, "localhost"); - }; + return this._makeConnection(browserSocket, head, port, 'localhost') + } if (!SSL_RECORD_TYPES.includes(firstBytes)) { - //# if this isn't an SSL request then go - //# ahead and make the connection now - return makeConnection(this._port); + // if this isn't an SSL request then go + // ahead and make the connection now + return makeConnection(this._port) } - //# else spin up the SNI server - const { hostname } = url.parse(`https://${req.url}`); + // else spin up the SNI server + const { hostname } = url.parse(`https://${req.url}`) - if (sslServer = sslServers[hostname]) { - return makeConnection(sslServer.port); + sslServer = sslServers[hostname] + + if (sslServer) { + return makeConnection(sslServer.port) } - //# only be creating one SSL server per hostname at once + // only be creating one SSL server per hostname at once if (!(sem = sslSemaphores[hostname])) { - sem = (sslSemaphores[hostname] = semaphore(1)); + sem = (sslSemaphores[hostname] = semaphore(1)) } return sem.take(() => { - const leave = () => process.nextTick(() => sem.leave()); + const leave = () => { + return process.nextTick(() => { + return sem.leave() + }) + } - if (sslServer = sslServers[hostname]) { - leave(); + sslServer = sslServers[hostname] - return makeConnection(sslServer.port); + if (sslServer) { + leave() + + return makeConnection(sslServer.port) } return this._getPortFor(hostname) - .then(function(port) { - sslServers[hostname] = { port }; + .then((port) => { + sslServers[hostname] = { port } - leave(); + leave() - return makeConnection(port); - }); - }); + return makeConnection(port) + }) + }) } - _normalizeKeyAndCert(certPem, privateKeyPem) { + _normalizeKeyAndCert (certPem, privateKeyPem) { return { - key: privateKeyPem, - cert: certPem - }; + key: privateKeyPem, + cert: certPem, + } } - _getCertificatePathsFor(hostname) { + _getCertificatePathsFor (hostname) { return this._ca.getCertificateKeysForHostname(hostname) - .spread(this._normalizeKeyAndCert); + .spread(this._normalizeKeyAndCert) } - _generateMissingCertificates(hostname) { + _generateMissingCertificates (hostname) { return this._ca.generateServerCertificateKeys(hostname) - .spread(this._normalizeKeyAndCert); + .spread(this._normalizeKeyAndCert) } - _getPortFor(hostname) { + _getPortFor (hostname) { return this._getCertificatePathsFor(hostname) - .catch(err => { - return this._generateMissingCertificates(hostname); - }).then((data = {}) => { + .catch((err) => { + return this._generateMissingCertificates(hostname) + }).then((data = {}) => { if (net.isIP(hostname)) { - return this._getServerPortForIp(hostname, data); + return this._getServerPortForIp(hostname, data) } - this._sniServer.addContext(hostname, data); + this._sniServer.addContext(hostname, data) - return this._sniPort; - }); + return this._sniPort + }) } - _listenHttpsServer(data) { + _listenHttpsServer (data) { return new Promise((resolve, reject) => { - const server = https.createServer(data); + const server = https.createServer(data) - allowDestroy(server); + allowDestroy(server) - server.once("error", reject); - server.on("upgrade", this._onUpgrade.bind(this, this._options.onUpgrade)); - server.on("request", this._onRequest.bind(this, this._options.onRequest)); + server.once('error', reject) + server.on('upgrade', this._onUpgrade.bind(this, this._options.onUpgrade)) + server.on('request', this._onRequest.bind(this, this._options.onRequest)) return server.listen(0, '127.0.0.1', () => { const { - port - } = server.address(); + port, + } = server.address() - server.removeListener("error", reject); - server.on("error", onError); + server.removeListener('error', reject) + server.on('error', onError) - return resolve({ server, port }); - }); - }); + return resolve({ server, port }) + }) + }) } - //# browsers will not do SNI for an IP address - //# so we need to serve 1 HTTPS server per IP - //# https://github.com/cypress-io/cypress/issues/771 - _getServerPortForIp(ip, data) { - let server; - if (server = sslIpServers[ip]) { - return server.address().port; + // browsers will not do SNI for an IP address + // so we need to serve 1 HTTPS server per IP + // https://github.com/cypress-io/cypress/issues/771 + _getServerPortForIp (ip, data) { + let server + + server = sslIpServers[ip] + + if (server) { + return server.address().port } return this._listenHttpsServer(data) - .then(function({ server, port }) { - sslIpServers[ip] = server; + .then(({ server, port }) => { + sslIpServers[ip] = server - debug("Created IP HTTPS Proxy Server", { port, ip }); + debug('Created IP HTTPS Proxy Server', { port, ip }) - return port; - }); + return port + }) } - listen() { - this._onError = this._options.onError; + listen () { + this._onError = this._options.onError return this._listenHttpsServer({}) - .tap(({ server, port}) => { - this._sniPort = port; - this._sniServer = server; + .tap(({ server, port }) => { + this._sniPort = port + this._sniServer = server - return debug("Created SNI HTTPS Proxy Server", { port }); - }); + return debug('Created SNI HTTPS Proxy Server', { port }) + }) } - close() { + close () { const close = () => { - const servers = _.values(sslIpServers).concat(this._sniServer); - return Promise.map(servers, server => { + const servers = _.values(sslIpServers).concat(this._sniServer) + + return Promise.map(servers, (server) => { return Promise.fromCallback(server.destroy) - .catch(onError); - }); - }; + .catch(onError) + }) + } return close() - .finally(module.exports.reset); + .finally(module.exports.reset) } } module.exports = { - reset() { - sslServers = {}; - return sslIpServers = {}; + reset () { + sslServers = {} + sslIpServers = {} }, - create(ca, port, options = {}) { - const srv = new Server(ca, port, options); + create (ca, port, options = {}) { + const srv = new Server(ca, port, options) return srv .listen() - .return(srv); - } -}; + .return(srv) + }, +} diff --git a/packages/https-proxy/lib/util/parse.js b/packages/https-proxy/lib/util/parse.js index 2fcb1bedd7..f8bc776c25 100644 --- a/packages/https-proxy/lib/util/parse.js +++ b/packages/https-proxy/lib/util/parse.js @@ -1,48 +1,56 @@ +// TODO: This file was created by bulk-decaffeinate. +// Sanity-check the conversion and remove this comment. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const url = require("url"); +const url = require('url') module.exports = { - parseHost(hostString, defaultPort) { - let m; - if (m = hostString.match(/^http:\/\/(.*)/)) { - const parsedUrl = url.parse(hostString); + parseHost (hostString, defaultPort) { + let m + + m = hostString.match(/^http:\/\/(.*)/) + + if (m) { + const parsedUrl = url.parse(hostString) return { host: parsedUrl.hostname, - port: parsedUrl.port - }; + port: parsedUrl.port, + } } - const hostPort = hostString.split(':'); - const host = hostPort[0]; - const port = hostPort.length === 2 ? +hostPort[1] : defaultPort; + const hostPort = hostString.split(':') + const host = hostPort[0] + const port = hostPort.length === 2 ? +hostPort[1] : defaultPort return { host, - port - }; + port, + } }, - hostAndPort(reqUrl, headers, defaultPort) { - let m; + hostAndPort (reqUrl, headers, defaultPort) { + let m const { - host - } = headers; + host, + } = headers - const hostPort = this.parseHost(host, defaultPort); + const hostPort = this.parseHost(host, defaultPort) - //# this handles paths which include the full url. This could happen if it's a proxy - if (m = reqUrl.match(/^http:\/\/([^\/]*)\/?(.*)$/)) { - const parsedUrl = url.parse(reqUrl); - hostPort.host = parsedUrl.hostname; - hostPort.port = parsedUrl.port; - reqUrl = parsedUrl.path; + // this handles paths which include the full url. This could happen if it's a proxy + m = reqUrl.match(/^http:\/\/([^\/]*)\/?(.*)$/) + + if (m) { + const parsedUrl = url.parse(reqUrl) + + hostPort.host = parsedUrl.hostname + hostPort.port = parsedUrl.port + reqUrl = parsedUrl.path } - return hostPort; - } -}; \ No newline at end of file + return hostPort + }, +} diff --git a/packages/https-proxy/test/helpers/certs.js b/packages/https-proxy/test/helpers/certs.js index f00b11a4ad..435c7773ce 100644 --- a/packages/https-proxy/test/helpers/certs.js +++ b/packages/https-proxy/test/helpers/certs.js @@ -1,14 +1,16 @@ -const fs = require("fs"); -const path = require("path"); -const sslRootCas = require('ssl-root-cas'); +// TODO: This file was created by bulk-decaffeinate. +// Sanity-check the conversion and remove this comment. +const fs = require('fs') +const path = require('path') +const sslRootCas = require('ssl-root-cas') sslRootCas .inject() -.addFile(path.join(__dirname, "certs", "server", "my-root-ca.crt.pem")); +.addFile(path.join(__dirname, 'certs', 'server', 'my-root-ca.crt.pem')) const options = { - key: fs.readFileSync(path.join(__dirname, "certs", "server", "my-server.key.pem")), - cert: fs.readFileSync(path.join(__dirname, "certs", "server", "my-server.crt.pem")) -}; + key: fs.readFileSync(path.join(__dirname, 'certs', 'server', 'my-server.key.pem')), + cert: fs.readFileSync(path.join(__dirname, 'certs', 'server', 'my-server.crt.pem')), +} -module.exports = options; +module.exports = options diff --git a/packages/https-proxy/test/helpers/http_server.js b/packages/https-proxy/test/helpers/http_server.js index 6d209393b5..80abc71f7f 100644 --- a/packages/https-proxy/test/helpers/http_server.js +++ b/packages/https-proxy/test/helpers/http_server.js @@ -1,31 +1,42 @@ +/* eslint-disable + no-console, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const http = require("http"); -const Promise = require("bluebird"); +const http = require('http') +const Promise = require('bluebird') -const srv = http.createServer(function(req, res) { - console.log("HTTP SERVER REQUEST URL:", req.url); - console.log("HTTP SERVER REQUEST HEADERS:", req.headers); +const srv = http.createServer((req, res) => { + console.log('HTTP SERVER REQUEST URL:', req.url) + console.log('HTTP SERVER REQUEST HEADERS:', req.headers) - res.setHeader("Content-Type", "text/html"); - res.writeHead(200); - return res.end("http server"); -}); + res.setHeader('Content-Type', 'text/html') + res.writeHead(200) + + return res.end('http server') +}) module.exports = { srv, - start() { - return new Promise(resolve => srv.listen(8080, function() { - console.log("server listening on port: 8080"); - return resolve(srv); - })); + start () { + return new Promise((resolve) => { + return srv.listen(8080, () => { + console.log('server listening on port: 8080') + + return resolve(srv) + }) + }) }, - stop() { - return new Promise(resolve => srv.close(resolve)); - } -}; \ No newline at end of file + stop () { + return new Promise((resolve) => { + return srv.close(resolve) + }) + }, +} diff --git a/packages/https-proxy/test/helpers/https_server.js b/packages/https-proxy/test/helpers/https_server.js index 1caa310eef..671218f506 100644 --- a/packages/https-proxy/test/helpers/https_server.js +++ b/packages/https-proxy/test/helpers/https_server.js @@ -1,49 +1,64 @@ +/* eslint-disable + no-console, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const https = require("https"); -const Promise = require("bluebird"); -const { allowDestroy } = require("@packages/network"); -const certs = require("./certs"); +const https = require('https') +const Promise = require('bluebird') +const { allowDestroy } = require('@packages/network') +const certs = require('./certs') -const defaultOnRequest = function(req, res) { - console.log("HTTPS SERVER REQUEST URL:", req.url); - console.log("HTTPS SERVER REQUEST HEADERS:", req.headers); +const defaultOnRequest = function (req, res) { + console.log('HTTPS SERVER REQUEST URL:', req.url) + console.log('HTTPS SERVER REQUEST HEADERS:', req.headers) - res.setHeader("Content-Type", "text/html"); - res.writeHead(200); - return res.end("https server"); -}; + res.setHeader('Content-Type', 'text/html') + res.writeHead(200) -let servers = []; + return res.end('https server') +} -const create = onRequest => https.createServer(certs, onRequest != null ? onRequest : defaultOnRequest); +let servers = [] + +const create = (onRequest) => { + return https.createServer(certs, onRequest != null ? onRequest : defaultOnRequest) +} module.exports = { create, - start(port, onRequest) { - return new Promise(function(resolve) { - const srv = create(onRequest); + start (port, onRequest) { + return new Promise((resolve) => { + const srv = create(onRequest) - allowDestroy(srv); + allowDestroy(srv) - servers.push(srv); + servers.push(srv) - return srv.listen(port, function() { - console.log(`server listening on port: ${port}`); - return resolve(srv); - }); - }); + return srv.listen(port, () => { + console.log(`server listening on port: ${port}`) + + return resolve(srv) + }) + }) }, - stop() { - const stop = srv => new Promise(resolve => srv.destroy(resolve)); + stop () { + const stop = (srv) => { + return new Promise((resolve) => { + return srv.destroy(resolve) + }) + } return Promise.map(servers, stop) - .then(() => servers = []); - } -}; + .then(() => { + return servers = [] + }) + }, +} diff --git a/packages/https-proxy/test/helpers/proxy.js b/packages/https-proxy/test/helpers/proxy.js index 36cc913eab..3951fc1fb9 100644 --- a/packages/https-proxy/test/helpers/proxy.js +++ b/packages/https-proxy/test/helpers/proxy.js @@ -1,78 +1,101 @@ +/* eslint-disable + no-console, + no-undef, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const { allowDestroy } = require("@packages/network"); -const http = require("http"); -const path = require("path"); -const httpsProxy = require("../../lib/proxy"); +const { allowDestroy } = require('@packages/network') +const http = require('http') +const path = require('path') +const httpsProxy = require('../../lib/proxy') -let prx = null; +let prx = null -const pipe = (req, res) => req.pipe(request(req.url)) -.on("error", function() { - console.log("**ERROR**", req.url); - req.statusCode = 500; - return res.end(); -}).pipe(res); +const pipe = (req, res) => { + return req.pipe(request(req.url)) + .on('error', () => { + console.log('**ERROR**', req.url) + req.statusCode = 500 -const onConnect = (req, socket, head, proxy) => proxy.connect(req, socket, head, { - onDirectConnection(req, socket, head) { - return ["localhost:8444", "localhost:12344"].includes(req.url); - } -}); + return res.end() + }).pipe(res) +} -const onRequest = (req, res) => pipe(req, res); +const onConnect = (req, socket, head, proxy) => { + return proxy.connect(req, socket, head, { + onDirectConnection (req, socket, head) { + return ['localhost:8444', 'localhost:12344'].includes(req.url) + }, + }) +} + +const onRequest = (req, res) => { + return pipe(req, res) +} module.exports = { - reset() { - return httpsProxy.reset(); + reset () { + return httpsProxy.reset() }, - start(port) { - prx = http.createServer(); + start (port) { + prx = http.createServer() - allowDestroy(prx); + allowDestroy(prx) - const dir = path.join(process.cwd(), "ca"); + const dir = path.join(process.cwd(), 'ca') return httpsProxy.create(dir, port, { - onUpgrade(req, socket, head) {}, + onUpgrade (req, socket, head) {}, - onRequest(req, res) { - console.log("ON REQUEST FROM OUTER PROXY", req.url, req.headers, req.method); + onRequest (req, res) { + console.log('ON REQUEST FROM OUTER PROXY', req.url, req.headers, req.method) - if (req.url.includes("replace")) { + if (req.url.includes('replace')) { const { - write - } = res; - res.write = function(chunk) { - chunk = Buffer.from(chunk.toString().replace("https server", "replaced content")); + write, + } = res - return write.call(this, chunk); - }; + res.write = function (chunk) { + chunk = Buffer.from(chunk.toString().replace('https server', 'replaced content')) - return pipe(req, res); - } else { - return pipe(req, res); + return write.call(this, chunk) + } + + return pipe(req, res) } - } + + return pipe(req, res) + }, }) - .then(proxy => { - prx.on("request", onRequest); + .then((proxy) => { + prx.on('request', onRequest) - prx.on("connect", (req, socket, head) => onConnect(req, socket, head, proxy)); + prx.on('connect', (req, socket, head) => { + return onConnect(req, socket, head, proxy) + }) - return new Promise(resolve => prx.listen(port, function() { - prx.proxy = proxy; - console.log(`server listening on port: ${port}`); - return resolve(proxy); - })); - }); + return new Promise((resolve) => { + return prx.listen(port, () => { + prx.proxy = proxy + console.log(`server listening on port: ${port}`) + + return resolve(proxy) + }) + }) + }) }, - stop() { - return new Promise(resolve => prx.destroy(resolve)).then(() => prx.proxy.close()); - } -}; + stop () { + return new Promise((resolve) => { + return prx.destroy(resolve) + }).then(() => { + return prx.proxy.close() + }) + }, +} diff --git a/packages/https-proxy/test/integration/proxy_spec.js b/packages/https-proxy/test/integration/proxy_spec.js index d0174640ab..ef171fae0d 100644 --- a/packages/https-proxy/test/integration/proxy_spec.js +++ b/packages/https-proxy/test/integration/proxy_spec.js @@ -1,26 +1,33 @@ +/* eslint-disable + brace-style, + no-undef, + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -require("../spec_helper"); +require('../spec_helper') -process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' -const _ = require("lodash"); -const DebugProxy = require("@cypress/debugging-proxy"); -const fs = require("fs-extra"); -const https = require("https"); -const net = require("net"); -const network = require("@packages/network"); -const path = require("path"); -const Promise = require("bluebird"); -const proxy = require("../helpers/proxy"); -const httpServer = require("../helpers/http_server"); -const httpsServer = require("../helpers/https_server"); +const _ = require('lodash') +const DebugProxy = require('@cypress/debugging-proxy') +const fs = require('fs-extra') +const https = require('https') +const net = require('net') +const network = require('@packages/network') +const path = require('path') +const Promise = require('bluebird') +const proxy = require('../helpers/proxy') +const httpServer = require('../helpers/http_server') +const httpsServer = require('../helpers/https_server') -describe("Proxy", function() { - beforeEach(function() { +describe('Proxy', () => { + beforeEach(function () { return Promise.join( httpServer.start(), @@ -29,293 +36,326 @@ describe("Proxy", function() { httpsServer.start(8444), proxy.start(3333) - .then(proxy1 => { - this.proxy = proxy1; - - }) - ); - }); + .then((proxy1) => { + this.proxy = proxy1 + }) + ) + }) - afterEach(() => Promise.join( - httpServer.stop(), - httpsServer.stop(), - proxy.stop() - )); + afterEach(() => { + return Promise.join( + httpServer.stop(), + httpsServer.stop(), + proxy.stop() + ) + }) - it("can request the googles", function() { - //# give some padding to external - //# network request - this.timeout(10000); + it('can request the googles', function () { + // give some padding to external + // network request + this.timeout(10000) return Promise.all([ request({ strictSSL: false, - proxy: "http://localhost:3333", - url: "https://www.google.com" + proxy: 'http://localhost:3333', + url: 'https://www.google.com', }), request({ strictSSL: false, - proxy: "http://localhost:3333", - url: "https://mail.google.com" + proxy: 'http://localhost:3333', + url: 'https://mail.google.com', }), request({ strictSSL: false, - proxy: "http://localhost:3333", - url: "https://google.com" - }) - ]); - }); - - it("can call the httpsDirectly without a proxy", () => request({ - strictSSL: false, - url: "https://localhost:8443" - })); - - it("can boot the httpsServer", () => request({ - strictSSL: false, - url: "https://localhost:8443/", - proxy: "http://localhost:3333" + proxy: 'http://localhost:3333', + url: 'https://google.com', + }), + ]) }) - .then(html => expect(html).to.include("https server"))); - it("yields the onRequest callback", () => request({ - strictSSL: false, - url: "https://localhost:8443/replace", - proxy: "http://localhost:3333" + it('can call the httpsDirectly without a proxy', () => { + return request({ + strictSSL: false, + url: 'https://localhost:8443', + }) }) - .then(html => expect(html).to.include("replaced content"))); - it("can pass directly through", () => //# this will fail due to dynamic cert - //# generation when strict ssl is true - request({ - strictSSL: false, - url: "https://localhost:8444/replace", - proxy: "http://localhost:3333" + it('can boot the httpsServer', () => { + return request({ + strictSSL: false, + url: 'https://localhost:8443/', + proxy: 'http://localhost:3333', + }) + .then((html) => { + expect(html).to.include('https server') + }) }) - .then(html => expect(html).to.include("https server"))); - it("retries 5 times", function() { - this.sandbox.spy(net, 'connect'); + it('yields the onRequest callback', () => { + return request({ + strictSSL: false, + url: 'https://localhost:8443/replace', + proxy: 'http://localhost:3333', + }) + .then((html) => { + expect(html).to.include('replaced content') + }) + }) + + it('can pass directly through', () => // this will fail due to dynamic cert + // generation when strict ssl is true + { + return request({ + strictSSL: false, + url: 'https://localhost:8444/replace', + proxy: 'http://localhost:3333', + }) + .then((html) => { + expect(html).to.include('https server') + }) + }) + + it('retries 5 times', function () { + this.sandbox.spy(net, 'connect') return request({ strictSSL: false, - url: "https://localhost:12344", - proxy: "http://localhost:3333" + url: 'https://localhost:12344', + proxy: 'http://localhost:3333', }) - .then(function() { - throw new Error("should not reach");}).catch(() => expect(net.connect).to.have.callCount(5)); - }); + .then(() => { + throw new Error('should not reach') + }).catch(() => { + expect(net.connect).to.have.callCount(5) + }) + }) - it("closes outgoing connections when client disconnects", function() { - this.sandbox.spy(net, 'connect'); + it('closes outgoing connections when client disconnects', function () { + this.sandbox.spy(net, 'connect') return request({ strictSSL: false, - url: "https://localhost:8444/replace", - proxy: "http://localhost:3333", - resolveWithFullResponse: true + url: 'https://localhost:8444/replace', + proxy: 'http://localhost:3333', + resolveWithFullResponse: true, }) - .then(res => { - //# ensure client has disconnected - expect(res.socket.destroyed).to.be.true; - //# ensure the outgoing socket created for this connection was destroyed + .then((res) => { + // ensure client has disconnected + expect(res.socket.destroyed).to.be.true + // ensure the outgoing socket created for this connection was destroyed const socket = net.connect.getCalls() - .find(call => { - return (call.args[0].port === "8444") && (call.args[0].host === "localhost"); - }).returnValue; - return expect(socket.destroyed).to.be.true; - }); - }); + .find((call) => { + return (call.args[0].port === '8444') && (call.args[0].host === 'localhost') + }).returnValue - it("can boot the httpServer", () => request({ - strictSSL: false, - url: "http://localhost:8080/", - proxy: "http://localhost:3333" + expect(socket.destroyed).to.be.true + }) }) - .then(html => expect(html).to.include("http server"))); + it('can boot the httpServer', () => { + return request({ + strictSSL: false, + url: 'http://localhost:8080/', + proxy: 'http://localhost:3333', + }) - context("generating certificates", function() { - it("reuses existing certificates", function() { + .then((html) => { + expect(html).to.include('http server') + }) + }) + + context('generating certificates', () => { + it('reuses existing certificates', function () { return request({ strictSSL: false, - url: "https://localhost:8443/", - proxy: "http://localhost:3333" + url: 'https://localhost:8443/', + proxy: 'http://localhost:3333', }) .then(() => { - proxy.reset(); + proxy.reset() - //# force this to reject if its called - this.sandbox.stub(this.proxy, "_generateMissingCertificates").rejects(new Error("should not call")); + // force this to reject if its called + this.sandbox.stub(this.proxy, '_generateMissingCertificates').rejects(new Error('should not call')) return request({ strictSSL: false, - url: "https://localhost:8443/", - proxy: "http://localhost:3333" - }); - }); - }); + url: 'https://localhost:8443/', + proxy: 'http://localhost:3333', + }) + }) + }) - //# https://github.com/cypress-io/cypress/issues/771 - return it("generates certs and can proxy requests for HTTPS requests to IPs", function() { - this.sandbox.spy(this.proxy, "_generateMissingCertificates"); - this.sandbox.spy(this.proxy, "_getServerPortForIp"); + // https://github.com/cypress-io/cypress/issues/771 + it('generates certs and can proxy requests for HTTPS requests to IPs', function () { + this.sandbox.spy(this.proxy, '_generateMissingCertificates') + this.sandbox.spy(this.proxy, '_getServerPortForIp') return Promise.all([ httpsServer.start(8445), - this.proxy._ca.removeAll() + this.proxy._ca.removeAll(), ]) .then(() => { return request({ strictSSL: false, - url: "https://127.0.0.1:8445/", - proxy: "http://localhost:3333" - }); - }).then(() => { - //# this should not stand up its own https server + url: 'https://127.0.0.1:8445/', + proxy: 'http://localhost:3333', + }) + }).then(() => { + // this should not stand up its own https server return request({ strictSSL: false, - url: "https://localhost:8443/", - proxy: "http://localhost:3333" - }); + url: 'https://localhost:8443/', + proxy: 'http://localhost:3333', + }) }).then(() => { - expect(this.proxy._ipServers["127.0.0.1"]).to.be.an.instanceOf(https.Server); - expect(this.proxy._getServerPortForIp).to.be.calledWith('127.0.0.1').and.be.calledOnce; - return expect(this.proxy._generateMissingCertificates).to.be.calledTwice; - }); - }); - }); + expect(this.proxy._ipServers['127.0.0.1']).to.be.an.instanceOf(https.Server) + expect(this.proxy._getServerPortForIp).to.be.calledWith('127.0.0.1').and.be.calledOnce - context("closing", () => it("resets sslServers and can reopen", function() { - return request({ - strictSSL: false, - url: "https://localhost:8443/", - proxy: "http://localhost:3333" - }) - .then(() => { - return proxy.stop(); - }).then(() => { - return proxy.start(3333); - }).then(() => { - //# force this to reject if its called - this.sandbox.stub(this.proxy, "_generateMissingCertificates").rejects(new Error("should not call")); - - return request({ - strictSSL: false, - url: "https://localhost:8443/", - proxy: "http://localhost:3333" - }); - }); - })); - - return context("with an upstream proxy", function() { - beforeEach(function() { - process.env.NO_PROXY = ""; - process.env.HTTP_PROXY = (process.env.HTTPS_PROXY = "http://localhost:9001"); - - this.upstream = new DebugProxy({ - keepRequests: true - }); - - return this.upstream.start(9001); - }); - - it("passes a request to an https server through the upstream", function() { - this.upstream._onConnect = function(domain, port) { - expect(domain).to.eq('localhost'); - expect(port).to.eq('8444'); - return true; - }; - - return request({ - strictSSL: false, - url: "https://localhost:8444/", - proxy: "http://localhost:3333" - }).then(res => { - return expect(res).to.contain("https server"); - }); - }); - - it("uses HTTP basic auth when provided", function() { - this.upstream.setAuth({ - username: 'foo', - password: 'bar' - }); - - this.upstream._onConnect = function(domain, port) { - expect(domain).to.eq('localhost'); - expect(port).to.eq('8444'); - return true; - }; - - process.env.HTTP_PROXY = (process.env.HTTPS_PROXY = "http://foo:bar@localhost:9001"); - - return request({ - strictSSL: false, - url: "https://localhost:8444/", - proxy: "http://localhost:3333" - }).then(res => { - return expect(res).to.contain("https server"); - }); - }); - - it("closes outgoing connections when client disconnects", function() { - this.sandbox.spy(net, 'connect'); - - return request({ - strictSSL: false, - url: "https://localhost:8444/replace", - proxy: "http://localhost:3333", - resolveWithFullResponse: true, - forever: false + expect(this.proxy._generateMissingCertificates).to.be.calledTwice }) - .then(res => { - //# ensure client has disconnected - expect(res.socket.destroyed).to.be.true; - - //# ensure the outgoing socket created for this connection was destroyed - const socket = net.connect.getCalls() - .find(call => { - return (call.args[0].port === 9001) && (call.args[0].host === "localhost"); - }).returnValue; - - return new Promise(resolve => socket.on('close', () => { - expect(socket.destroyed).to.be.true; - return resolve(); - })); - }); - }); - - //# https://github.com/cypress-io/cypress/issues/4257 - it("passes through to SNI when it is intercepted and not through proxy", function() { - const createSocket = this.sandbox.stub(network.connect, 'createRetryingSocket').callsArgWith(1, new Error('stub')); - const createProxyConn = this.sandbox.spy(network.agent.httpsAgent, 'createUpstreamProxyConnection'); + }) + }) + context('closing', () => { + it('resets sslServers and can reopen', function () { return request({ strictSSL: false, - url: "https://localhost:8443", - proxy: "http://localhost:3333", - resolveWithFullResponse: true, - forever: false + url: 'https://localhost:8443/', + proxy: 'http://localhost:3333', }) .then(() => { - throw new Error('should not succeed'); - }).catch({ message: 'Error: Client network socket disconnected before secure TLS connection was established' }, () => { - expect(createProxyConn).to.not.be.called; - return expect(createSocket).to.be.calledWith({ - port: this.proxy._sniPort, - host: 'localhost' - }); - }); - }); + return proxy.stop() + }).then(() => { + return proxy.start(3333) + }).then(() => { + // force this to reject if its called + this.sandbox.stub(this.proxy, '_generateMissingCertificates').rejects(new Error('should not call')) - return afterEach(function() { - this.upstream.stop(); - delete process.env.HTTP_PROXY; - delete process.env.HTTPS_PROXY; - return delete process.env.NO_PROXY; - }); - }); -}); + return request({ + strictSSL: false, + url: 'https://localhost:8443/', + proxy: 'http://localhost:3333', + }) + }) + }) + }) + + context('with an upstream proxy', () => { + beforeEach(function () { + process.env.NO_PROXY = '' + process.env.HTTP_PROXY = (process.env.HTTPS_PROXY = 'http://localhost:9001') + + this.upstream = new DebugProxy({ + keepRequests: true, + }) + + return this.upstream.start(9001) + }) + + it('passes a request to an https server through the upstream', function () { + this.upstream._onConnect = function (domain, port) { + expect(domain).to.eq('localhost') + expect(port).to.eq('8444') + + return true + } + + return request({ + strictSSL: false, + url: 'https://localhost:8444/', + proxy: 'http://localhost:3333', + }).then((res) => { + expect(res).to.contain('https server') + }) + }) + + it('uses HTTP basic auth when provided', function () { + this.upstream.setAuth({ + username: 'foo', + password: 'bar', + }) + + this.upstream._onConnect = function (domain, port) { + expect(domain).to.eq('localhost') + expect(port).to.eq('8444') + + return true + } + + process.env.HTTP_PROXY = (process.env.HTTPS_PROXY = 'http://foo:bar@localhost:9001') + + return request({ + strictSSL: false, + url: 'https://localhost:8444/', + proxy: 'http://localhost:3333', + }).then((res) => { + expect(res).to.contain('https server') + }) + }) + + it('closes outgoing connections when client disconnects', function () { + this.sandbox.spy(net, 'connect') + + return request({ + strictSSL: false, + url: 'https://localhost:8444/replace', + proxy: 'http://localhost:3333', + resolveWithFullResponse: true, + forever: false, + }) + .then((res) => { + // ensure client has disconnected + expect(res.socket.destroyed).to.be.true + + // ensure the outgoing socket created for this connection was destroyed + const socket = net.connect.getCalls() + .find((call) => { + return (call.args[0].port === 9001) && (call.args[0].host === 'localhost') + }).returnValue + + return new Promise((resolve) => { + return socket.on('close', () => { + expect(socket.destroyed).to.be.true + + return resolve() + }) + }) + }) + }) + + // https://github.com/cypress-io/cypress/issues/4257 + it('passes through to SNI when it is intercepted and not through proxy', function () { + const createSocket = this.sandbox.stub(network.connect, 'createRetryingSocket').callsArgWith(1, new Error('stub')) + const createProxyConn = this.sandbox.spy(network.agent.httpsAgent, 'createUpstreamProxyConnection') + + return request({ + strictSSL: false, + url: 'https://localhost:8443', + proxy: 'http://localhost:3333', + resolveWithFullResponse: true, + forever: false, + }) + .then(() => { + throw new Error('should not succeed') + }).catch({ message: 'Error: Client network socket disconnected before secure TLS connection was established' }, () => { + expect(createProxyConn).to.not.be.called + + expect(createSocket).to.be.calledWith({ + port: this.proxy._sniPort, + host: 'localhost', + }) + }) + }) + + return afterEach(function () { + this.upstream.stop() + delete process.env.HTTP_PROXY + delete process.env.HTTPS_PROXY + + return delete process.env.NO_PROXY + }) + }) +}) diff --git a/packages/https-proxy/test/spec_helper.js b/packages/https-proxy/test/spec_helper.js index c1cfff6667..25b0cbbdf0 100644 --- a/packages/https-proxy/test/spec_helper.js +++ b/packages/https-proxy/test/spec_helper.js @@ -1,26 +1,31 @@ +/* eslint-disable + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -const chai = require("chai"); -const sinon = require("sinon"); -const Promise = require("bluebird"); -const sinonChai = require("sinon-chai"); -const sinonPromise = require("sinon-as-promised")(Promise); +const chai = require('chai') +const sinon = require('sinon') +const Promise = require('bluebird') +const sinonChai = require('sinon-chai') +const sinonPromise = require('sinon-as-promised')(Promise) -global.request = require("request-promise"); -global.sinon = sinon; -global.supertest = require("supertest"); +global.request = require('request-promise') +global.sinon = sinon +global.supertest = require('supertest') -chai.use(sinonChai); +chai.use(sinonChai) -global.expect = chai.expect; +global.expect = chai.expect -beforeEach(function() { - return this.sandbox = sinon.sandbox.create(); -}); +beforeEach(function () { + this.sandbox = sinon.sandbox.create() +}) -afterEach(function() { - return this.sandbox.restore(); -}); +afterEach(function () { + return this.sandbox.restore() +}) diff --git a/packages/https-proxy/test/unit/ca_spec.js b/packages/https-proxy/test/unit/ca_spec.js index b019e91e24..b6891d61d3 100644 --- a/packages/https-proxy/test/unit/ca_spec.js +++ b/packages/https-proxy/test/unit/ca_spec.js @@ -1,104 +1,110 @@ +// TODO: This file was created by bulk-decaffeinate. +// Sanity-check the conversion and remove this comment. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -require("../spec_helper"); +require('../spec_helper') -let fs = require("fs-extra"); -const path = require("path"); -const Promise = require("bluebird"); -const CA = require("../../lib/ca"); +let fs = require('fs-extra') +const path = require('path') +const Promise = require('bluebird') +const CA = require('../../lib/ca') -fs = Promise.promisifyAll(fs); +fs = Promise.promisifyAll(fs) -describe("lib/ca", function() { - beforeEach(function() { - this.timeout(5000); +describe('lib/ca', () => { + beforeEach(function () { + this.timeout(5000) - this.dir = path.join(process.cwd(), "tmp"); + this.dir = path.join(process.cwd(), 'tmp') return fs.ensureDirAsync(this.dir) .then(() => { - return CA.create(this.dir); - }).then(ca => { - this.ca = ca; - - }); - }); + return CA.create(this.dir) + }).then((ca) => { + this.ca = ca + }) + }) - afterEach(function() { - return fs.removeAsync(this.dir); - }); + afterEach(function () { + return fs.removeAsync(this.dir) + }) - context("#generateServerCertificateKeys", () => it("generates certs for each host", function() { - return this.ca.generateServerCertificateKeys("www.cypress.io") - .spread(function(certPem, keyPrivatePem) { - expect(certPem).to.include("-----BEGIN CERTIFICATE-----"); - return expect(keyPrivatePem).to.include("-----BEGIN RSA PRIVATE KEY-----"); - }); - })); + context('#generateServerCertificateKeys', () => { + it('generates certs for each host', function () { + return this.ca.generateServerCertificateKeys('www.cypress.io') + .spread((certPem, keyPrivatePem) => { + expect(certPem).to.include('-----BEGIN CERTIFICATE-----') - return context(".create", function() { - it("returns a new CA instance", function() { - return expect(this.ca).to.be.an.instanceof(CA); - }); + expect(keyPrivatePem).to.include('-----BEGIN RSA PRIVATE KEY-----') + }) + }) + }) - it("creates certs + keys dir", function() { + context('.create', () => { + it('returns a new CA instance', function () { + expect(this.ca).to.be.an.instanceof(CA) + }) + + it('creates certs + keys dir', function () { return Promise.join( - fs.statAsync(path.join(this.dir, "certs")), - fs.statAsync(path.join(this.dir, "keys")) - ); - }); + fs.statAsync(path.join(this.dir, 'certs')), + fs.statAsync(path.join(this.dir, 'keys')) + ) + }) - it("writes certs/ca.pem", function() { - return fs.statAsync(path.join(this.dir, "certs", "ca.pem")); - }); + it('writes certs/ca.pem', function () { + return fs.statAsync(path.join(this.dir, 'certs', 'ca.pem')) + }) - it("writes keys/ca.private.key", function() { - return fs.statAsync(path.join(this.dir, "keys", "ca.private.key")); - }); + it('writes keys/ca.private.key', function () { + return fs.statAsync(path.join(this.dir, 'keys', 'ca.private.key')) + }) - it("writes keys/ca.public.key", function() { - return fs.statAsync(path.join(this.dir, "keys", "ca.public.key")); - }); + it('writes keys/ca.public.key', function () { + return fs.statAsync(path.join(this.dir, 'keys', 'ca.public.key')) + }) - it("sets ca.CAcert", function() { - return expect(this.ca.CAcert).to.be.an("object"); - }); + it('sets ca.CAcert', function () { + expect(this.ca.CAcert).to.be.an('object') + }) - it("sets ca.CAkeys", function() { - expect(this.ca.CAkeys).to.be.an("object"); - expect(this.ca.CAkeys).to.have.a.property("privateKey"); - return expect(this.ca.CAkeys).to.have.a.property("publicKey"); - }); + it('sets ca.CAkeys', function () { + expect(this.ca.CAkeys).to.be.an('object') + expect(this.ca.CAkeys).to.have.a.property('privateKey') - return describe("existing CA folder", function() { - beforeEach(function() { - this.sandbox.spy(CA.prototype, "loadCA"); - this.sandbox.spy(CA.prototype, "generateCA"); + expect(this.ca.CAkeys).to.have.a.property('publicKey') + }) + + describe('existing CA folder', () => { + beforeEach(function () { + this.sandbox.spy(CA.prototype, 'loadCA') + this.sandbox.spy(CA.prototype, 'generateCA') return CA.create(this.dir) - .then(ca2 => { - this.ca2 = ca2; - - }); - }); + .then((ca2) => { + this.ca2 = ca2 + }) + }) - it("calls loadCA and not generateCA", function() { - expect(CA.prototype.loadCA).to.be.calledOnce; - return expect(CA.prototype.generateCA).not.to.be.called; - }); + it('calls loadCA and not generateCA', () => { + expect(CA.prototype.loadCA).to.be.calledOnce - it("sets ca.CAcert", function() { - return expect(this.ca2.CAcert).to.be.an("object"); - }); + expect(CA.prototype.generateCA).not.to.be.called + }) - return it("sets ca.CAkeys", function() { - expect(this.ca2.CAkeys).to.be.an("object"); - expect(this.ca2.CAkeys).to.have.a.property("privateKey"); - return expect(this.ca2.CAkeys).to.have.a.property("publicKey"); - }); - }); - }); -}); + it('sets ca.CAcert', function () { + expect(this.ca2.CAcert).to.be.an('object') + }) + + it('sets ca.CAkeys', function () { + expect(this.ca2.CAkeys).to.be.an('object') + expect(this.ca2.CAkeys).to.have.a.property('privateKey') + + expect(this.ca2.CAkeys).to.have.a.property('publicKey') + }) + }) + }) +}) diff --git a/packages/https-proxy/test/unit/server_spec.js b/packages/https-proxy/test/unit/server_spec.js index 997661cfcc..fd6a517e65 100644 --- a/packages/https-proxy/test/unit/server_spec.js +++ b/packages/https-proxy/test/unit/server_spec.js @@ -1,133 +1,141 @@ +/* eslint-disable + no-unused-vars, +*/ +// TODO: This file was created by bulk-decaffeinate. +// Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ -require("../spec_helper"); +require('../spec_helper') -const EE = require("events"); -const Promise = require("bluebird"); -const proxy = require("../helpers/proxy"); -const Server = require("../../lib/server"); +const EE = require('events') +const Promise = require('bluebird') +const proxy = require('../helpers/proxy') +const Server = require('../../lib/server') -describe("lib/server", function() { - beforeEach(function() { - return this.setup = (options = {}) => { - this.ca = {}; - this.port = 12345; +describe('lib/server', () => { + beforeEach(function () { + this.setup = (options = {}) => { + this.ca = {} + this.port = 12345 - return Server.create(this.ca, this.port, options); - }; - }); + return Server.create(this.ca, this.port, options) + } + }) - afterEach(function() { - delete process.env.HTTPS_PROXY; - return delete process.env.NO_PROXY; - }); + afterEach(() => { + delete process.env.HTTPS_PROXY - return context("#listen", function() { - it("calls options.onUpgrade with req, socket head", function() { - const onUpgrade = this.sandbox.stub(); + return delete process.env.NO_PROXY + }) - return this.setup({onUpgrade}) - .then(function(srv) { - srv._sniServer.emit("upgrade", 1, 2, 3); + context('#listen', () => { + it('calls options.onUpgrade with req, socket head', function () { + const onUpgrade = this.sandbox.stub() - return expect(onUpgrade).to.be.calledWith(1,2,3); - }); - }); + return this.setup({ onUpgrade }) + .then((srv) => { + srv._sniServer.emit('upgrade', 1, 2, 3) - it("calls options.onRequest with req, res", function() { - const onRequest = this.sandbox.stub(); - const req = {url: "https://www.foobar.com", headers: {host: "www.foobar.com"}}; - const res = {}; + expect(onUpgrade).to.be.calledWith(1, 2, 3) + }) + }) - return this.setup({onRequest}) - .then(function(srv) { - srv._sniServer.emit("request", req, res); + it('calls options.onRequest with req, res', function () { + const onRequest = this.sandbox.stub() + const req = { url: 'https://www.foobar.com', headers: { host: 'www.foobar.com' } } + const res = {} - return expect(onRequest).to.be.calledWith(req, res); - }); - }); + return this.setup({ onRequest }) + .then((srv) => { + srv._sniServer.emit('request', req, res) - it("calls options.onError with err and port and destroys the client socket", function(done) { - const socket = new EE(); - socket.destroy = this.sandbox.stub(); - const head = {}; + expect(onRequest).to.be.calledWith(req, res) + }) + }) - const onError = function(err, socket2, head2, port) { - expect(err.message).to.eq("connect ECONNREFUSED 127.0.0.1:8444"); + it('calls options.onError with err and port and destroys the client socket', function (done) { + const socket = new EE() - expect(socket).to.eq(socket2); - expect(head).to.eq(head2); - expect(port).to.eq("8444"); + socket.destroy = this.sandbox.stub() + const head = {} - expect(socket.destroy).to.be.calledOnce; + const onError = function (err, socket2, head2, port) { + expect(err.message).to.eq('connect ECONNREFUSED 127.0.0.1:8444') - return done(); - }; + expect(socket).to.eq(socket2) + expect(head).to.eq(head2) + expect(port).to.eq('8444') + + expect(socket.destroy).to.be.calledOnce + + return done() + } this.setup({ onError }) - .then(function(srv) { - let conn; - return conn = srv._makeDirectConnection({url: "localhost:8444"}, socket, head); - }); + .then((srv) => { + let conn - }); + conn = srv._makeDirectConnection({ url: 'localhost:8444' }, socket, head) + }) + }) - //# https://github.com/cypress-io/cypress/issues/3250 - it("does not crash when an erroneous URL is provided, just destroys socket", function(done) { - const socket = new EE(); - socket.destroy = this.sandbox.stub(); - const head = {}; + // https://github.com/cypress-io/cypress/issues/3250 + it('does not crash when an erroneous URL is provided, just destroys socket', function (done) { + const socket = new EE() - const onError = function(err, socket2, head2, port) { - expect(err.message).to.eq("connect ECONNREFUSED 127.0.0.1:443"); + socket.destroy = this.sandbox.stub() + const head = {} - expect(socket).to.eq(socket2); - expect(head).to.eq(head2); - expect(port).to.eq("443"); + const onError = function (err, socket2, head2, port) { + expect(err.message).to.eq('connect ECONNREFUSED 127.0.0.1:443') - expect(socket.destroy).to.be.calledOnce; + expect(socket).to.eq(socket2) + expect(head).to.eq(head2) + expect(port).to.eq('443') - return done(); - }; + expect(socket.destroy).to.be.calledOnce + + return done() + } this.setup({ onError }) - .then(function(srv) { - let conn; - return conn = srv._makeDirectConnection({url: "%7Balgolia_application_id%7D-dsn.algolia.net:443"}, socket, head); - }); + .then((srv) => { + let conn - }); + conn = srv._makeDirectConnection({ url: '%7Balgolia_application_id%7D-dsn.algolia.net:443' }, socket, head) + }) + }) - return it("with proxied connection calls options.onError with err and port and destroys the client socket", function(done) { - const socket = new EE(); - socket.destroy = this.sandbox.stub(); - const head = {}; + it('with proxied connection calls options.onError with err and port and destroys the client socket', function (done) { + const socket = new EE() - const onError = function(err, socket2, head2, port) { - expect(err.message).to.eq("A connection to the upstream proxy could not be established: connect ECONNREFUSED 127.0.0.1:8444"); + socket.destroy = this.sandbox.stub() + const head = {} - expect(socket).to.eq(socket2); - expect(head).to.eq(head2); - expect(port).to.eq("11111"); + const onError = function (err, socket2, head2, port) { + expect(err.message).to.eq('A connection to the upstream proxy could not be established: connect ECONNREFUSED 127.0.0.1:8444') - expect(socket.destroy).to.be.calledOnce; + expect(socket).to.eq(socket2) + expect(head).to.eq(head2) + expect(port).to.eq('11111') - return done(); - }; + expect(socket.destroy).to.be.calledOnce - process.env.HTTPS_PROXY = 'http://localhost:8444'; - process.env.NO_PROXY = ''; + return done() + } + + process.env.HTTPS_PROXY = 'http://localhost:8444' + process.env.NO_PROXY = '' this.setup({ onError }) - .then(function(srv) { - let conn; - return conn = srv._makeDirectConnection({url: "should-not-reach.invalid:11111"}, socket, head); - }); - - }); - }); -}); + .then((srv) => { + let conn + conn = srv._makeDirectConnection({ url: 'should-not-reach.invalid:11111' }, socket, head) + }) + }) + }) +})