From 818dfdfd0096f4cc2c5f05b4852bb3c65a1d71e4 Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Tue, 26 Mar 2019 17:14:21 -0400 Subject: [PATCH] Revert "server, launcher, ts: typescript" This reverts commit d3f8b8bbb6ba7b5c935fab5aa42b99ad13149576. --- package.json | 10 ---- packages/launcher/package.json | 9 ++++ packages/server/lib/util/agent.ts | 63 ++++++++++++------------ packages/server/lib/util/connect.js | 62 ++++++++++++++++++++++++ packages/server/lib/util/connect.ts | 58 ---------------------- packages/server/lib/util/proxy.js | 42 ++++++++++++++++ packages/server/lib/util/proxy.ts | 41 ---------------- packages/server/tsconfig.json | 10 ---- packages/ts/index.d.ts | 75 ++++++++--------------------- packages/ts/tsconfig.json | 4 +- 10 files changed, 164 insertions(+), 210 deletions(-) create mode 100644 packages/server/lib/util/connect.js delete mode 100644 packages/server/lib/util/connect.ts create mode 100644 packages/server/lib/util/proxy.js delete mode 100644 packages/server/lib/util/proxy.ts delete mode 100644 packages/server/tsconfig.json diff --git a/package.json b/package.json index 1b50dfbe61..9a65867892 100644 --- a/package.json +++ b/package.json @@ -67,16 +67,6 @@ "@cypress/env-or-json-file": "2.0.0", "@cypress/npm-run-all": "4.0.5", "@cypress/questions-remain": "1.0.1", - "@types/bluebird": "3.5.21", - "@types/chai": "3.5.2", - "@types/debug": "0.0.31", - "@types/execa": "0.7.2", - "@types/fs-extra": "3.0.0", - "@types/lodash": "4.14.122", - "@types/mocha": "2.2.48", - "@types/node": "7.10.3", - "@types/ramda": "0.25.47", - "@types/request-promise": "4.1.42", "ansi-styles": "3.2.1", "ascii-table": "0.0.9", "babel-eslint": "10.0.1", diff --git a/packages/launcher/package.json b/packages/launcher/package.json index 04915561e3..7f294d88ad 100644 --- a/packages/launcher/package.json +++ b/packages/launcher/package.json @@ -25,6 +25,15 @@ "lib" ], "devDependencies": { + "@types/bluebird": "3.5.21", + "@types/chai": "3.5.2", + "@types/debug": "0.0.31", + "@types/execa": "0.7.2", + "@types/fs-extra": "3.0.0", + "@types/lodash": "4.14.122", + "@types/mocha": "2.2.48", + "@types/node": "7.10.3", + "@types/ramda": "0.25.47", "bin-up": "1.1.0", "chai": "3.5.0", "prettier": "1.16.4", diff --git a/packages/server/lib/util/agent.ts b/packages/server/lib/util/agent.ts index 66ccf46a17..7aae063d95 100644 --- a/packages/server/lib/util/agent.ts +++ b/packages/server/lib/util/agent.ts @@ -6,14 +6,10 @@ import * as url from 'url' import * as debugModule from 'debug' import { getProxyForUrl } from 'proxy-from-env' import * as Promise from 'bluebird' -import { getAddress } from './connect' +import * as connect from './connect' const debug = debugModule('cypress:server:agent') -interface RequestOptionsWithProxy extends http.RequestOptions { - proxy: string -} - function createProxySock (proxy: url.Url) { if (proxy.protocol === 'http:') { return net.connect(Number(proxy.port || 80), proxy.hostname) @@ -28,21 +24,21 @@ function createProxySock (proxy: url.Url) { throw new Error(`Unsupported proxy protocol: ${proxy.protocol}`) } -function regenerateRequestHead(req: http.ClientRequest) { - delete req._header - req._implicitHeader() +function regenerateRequestHead(req) { + req._header = null; + req._implicitHeader(); if (req.output && req.output.length > 0) { // the _header has already been queued to be written to the socket - var first = req.output[0] - var endOfHeaders = first.indexOf('\r\n\r\n') + 4 - req.output[0] = req._header + first.substring(endOfHeaders) + var first = req.output[0]; + var endOfHeaders = first.indexOf('\r\n\r\n') + 4; + req.output[0] = req._header + first.substring(endOfHeaders); } } export class CombinedAgent { httpAgent: HttpAgent httpsAgent: HttpsAgent - familyCache: { [host: string] : 4 | 6 } = {} + familyCache = {} constructor(httpOpts: http.AgentOptions = {}, httpsOpts: https.AgentOptions = {}) { this.httpAgent = new HttpAgent(httpOpts) @@ -73,7 +69,7 @@ export class CombinedAgent { debug(`addRequest called for ${options.href}`) this._getFirstWorkingFamily(options) - .then((family: Optional) => { + .then(family => { options.family = family if (isHttps) { @@ -84,7 +80,7 @@ export class CombinedAgent { }) } - _getFirstWorkingFamily({ port, host }: http.RequestOptions) { + _getFirstWorkingFamily({ port, host }) { // this is a workaround for localhost (and potentially others) having invalid // A records but valid AAAA records. here, we just cache the family of the first // returned A/AAAA record for a host that we can establish a connection to. @@ -105,8 +101,8 @@ export class CombinedAgent { return Promise.resolve(this.familyCache[host]) } - return getAddress(port, host) - .then((firstWorkingAddress: net.Address) => { + return connect.getAddress(port, host) + .then(firstWorkingAddress => { this.familyCache[host] = firstWorkingAddress.family return firstWorkingAddress.family }) @@ -124,21 +120,21 @@ class HttpAgent extends http.Agent { this.httpsAgent = new https.Agent({ keepAlive: true }) } - createSocket (req: http.ClientRequest, options: http.RequestOptions, cb: http.SocketCallback) { + createSocket (req, options, cb) { if (process.env.HTTP_PROXY) { const proxy = getProxyForUrl(options.href) if (proxy) { options.proxy = proxy - return this._createProxiedSocket(req, options, cb) + return this._createProxiedSocket(req, options, cb) } } super.createSocket(req, options, cb) } - _createProxiedSocket (req: http.ClientRequest, options: RequestOptionsWithProxy, cb: http.SocketCallback) { + _createProxiedSocket (req, options, cb) { debug(`Creating proxied socket for ${options.href} through ${options.proxy}`) const proxy = url.parse(options.proxy) @@ -158,8 +154,8 @@ class HttpAgent extends http.Agent { // https://github.com/TooTallNate/node-http-proxy-agent/blob/master/index.js#L93 regenerateRequestHead(req) - options.port = Number(proxy.port || 80) - options.host = proxy.hostname || 'localhost' + options.port = proxy.port + options.host = proxy.hostname delete options.path // so the underlying net.connect doesn't default to IPC if (proxy.protocol === 'https:') { @@ -179,14 +175,14 @@ class HttpsAgent extends https.Agent { super(opts) } - createConnection (options: http.RequestOptions, cb: http.SocketCallback) { + createConnection (options, cb) { if (process.env.HTTPS_PROXY) { const proxy = getProxyForUrl(options.href) - if (typeof proxy === "string") { - options.proxy = proxy + if (proxy) { + options.proxy = proxy - return this.createProxiedConnection(options, cb) + return this.createProxiedConnection(options, cb) } } @@ -194,7 +190,7 @@ class HttpsAgent extends https.Agent { cb(null, super.createConnection(options)) } - createProxiedConnection (options: RequestOptionsWithProxy, cb: http.SocketCallback) { + createProxiedConnection (options, cb) { // heavily inspired by // https://github.com/mknj/node-keepalive-proxy-agent/blob/master/index.js debug(`Creating proxied socket for ${options.href} through ${options.proxy}`) @@ -205,14 +201,14 @@ class HttpsAgent extends https.Agent { const proxySocket = createProxySock(proxy) - const onError = (err: Error) => { + const onError = (err) => { proxySocket.destroy() - cb(err, undefined) + cb(err) } let buffer = '' - const onData = (data: Buffer) => { + const onData = (data) => { debug(`Proxy socket for ${options.href} established`) buffer += data.toString() @@ -227,18 +223,19 @@ class HttpsAgent extends https.Agent { // read status code from proxy's response const matches = buffer.match(/^HTTP\/1.1 (\d*)/) - if (!matches || matches[1] !== '200') { - return onError(new Error(`Error establishing proxy connection: ${matches ? matches[0] : buffer}`)) + if (matches[1] !== '200') { + return onError(new Error(`Error establishing proxy connection: ${matches[0]}`)) } if (options._agentKey) { // https.Agent will upgrade and reuse this socket now options.socket = proxySocket options.servername = hostname - return cb(undefined, super.createConnection(options, undefined)) + // @ts-ignore + return cb(null, super.createConnection(options)) } - cb(undefined, proxySocket) + cb(null, proxySocket) } proxySocket.once('error', onError) diff --git a/packages/server/lib/util/connect.js b/packages/server/lib/util/connect.js new file mode 100644 index 0000000000..d5712bfdc4 --- /dev/null +++ b/packages/server/lib/util/connect.js @@ -0,0 +1,62 @@ +const net = require('net') +const dns = require('dns') +const url = require('url') +const rp = require('request-promise') +const Promise = require('bluebird') + +module.exports = { + byPortAndAddress (port, address) { + // https://nodejs.org/api/net.html#net_net_connect_port_host_connectlistener + return new Promise((resolve, reject) => { + const client = net.connect(port, address.address) + + client.on('connect', () => { + client.end() + + resolve(address) + }) + + client.on('error', reject) + }) + }, + + getAddress (port, hostname) { + const fn = this.byPortAndAddress.bind(this, port) + + // promisify at the very last second which enables us to + // modify dns lookup function (via hosts overrides) + const lookupAsync = Promise.promisify(dns.lookup, { context: dns }) + + // this does not go out to the network to figure + // out the addresess. in fact it respects the /etc/hosts file + // https://github.com/nodejs/node/blob/dbdbdd4998e163deecefbb1d34cda84f749844a4/lib/dns.js#L108 + // https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback + return lookupAsync(hostname, { all: true }) + .then((addresses) => { + // convert to an array if string + return [].concat(addresses).map(fn) + }) + .any() + }, + + ensureUrl (urlStr) { + // takes a urlStr and verifies the hostname + port + let { hostname, protocol, port } = url.parse(urlStr) + + if (port == null) { + port = protocol === 'https:' ? '443' : '80' + } + + if (process.env.HTTP_PROXY) { + // cannot make arbitrary connections behind a proxy, attempt HTTP/HTTPS + return rp({ + url: urlStr, + agent: require('./agent'), + proxy: null, + }) + .catch({ name: 'StatusCodeError' }, () => {}) // we just care if it can connect, not if it's a valid resource + } + + return this.getAddress(port, hostname) + }, +} diff --git a/packages/server/lib/util/connect.ts b/packages/server/lib/util/connect.ts deleted file mode 100644 index 170e278a19..0000000000 --- a/packages/server/lib/util/connect.ts +++ /dev/null @@ -1,58 +0,0 @@ -import * as net from 'net' -import * as dns from 'dns' -import * as url from 'url' -import * as rp from 'request-promise' -import * as Promise from 'bluebird' - -export function byPortAndAddress (port: number, address: net.Address) { - // https://nodejs.org/api/net.html#net_net_connect_port_host_connectlistener - return new Promise((resolve, reject) => { - const client = net.connect(port, address.address, () => { - client.end() - resolve(address) - }) - - client.on('error', reject) - }) -} - -export function getAddress (port: number, hostname: string) { - const fn = byPortAndAddress.bind({}, port) - - // promisify at the very last second which enables us to - // modify dns lookup function (via hosts overrides) - const lookupAsync = Promise.promisify(dns.lookup, { context: dns }) - - // this does not go out to the network to figure - // out the addresess. in fact it respects the /etc/hosts file - // https://github.com/nodejs/node/blob/dbdbdd4998e163deecefbb1d34cda84f749844a4/lib/dns.js#L108 - // https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback - // @ts-ignore - return lookupAsync(hostname, { all: true }) - .then((addresses: net.Address[]) => { - // convert to an array if string - return Array.prototype.concat.call(addresses).map(fn) - }) - .any() -} - -export function ensureUrl (urlStr: string) { - // takes a urlStr and verifies the hostname + port - let { hostname, protocol, port } = url.parse(urlStr) - - if (port == null) { - port = protocol === 'https:' ? '443' : '80' - } - - if (process.env.HTTP_PROXY) { - // cannot make arbitrary connections behind a proxy, attempt HTTP/HTTPS - return rp({ - url: urlStr, - agent: require('./agent'), - proxy: null, - }) - .catch({ name: 'StatusCodeError' }, () => {}) // we just care if it can connect, not if it's a valid resource - } - - return getAddress(Number(port), String(hostname)) -} diff --git a/packages/server/lib/util/proxy.js b/packages/server/lib/util/proxy.js new file mode 100644 index 0000000000..4c7e98a4b5 --- /dev/null +++ b/packages/server/lib/util/proxy.js @@ -0,0 +1,42 @@ +const os = require('os') +const getWindowsProxy = require('@cypress/get-windows-proxy') + +module.exports = { + _getWindowsProxy () { + return getWindowsProxy() + }, + + _normalizeEnvironmentProxy () { + if (!process.env.HTTPS_PROXY) { + // request library will use HTTP_PROXY as a fallback for HTTPS urls, but + // proxy-from-env will not, so let's just force it to fall back like this + process.env.HTTPS_PROXY = process.env.HTTP_PROXY + } + + if (!process.env.NO_PROXY) { + // don't proxy localhost, to match Chrome's default behavior and user expectation + process.env.NO_PROXY = 'localhost' + } + }, + + loadSystemProxySettings () { + if (process.env.HTTP_PROXY !== undefined) { + this._normalizeEnvironmentProxy() + + return + } + + if (os.platform() === 'win32') { + const windowsProxy = this._getWindowsProxy() + + if (windowsProxy) { + process.env.HTTP_PROXY = process.env.HTTPS_PROXY = windowsProxy.httpProxy + process.env.NO_PROXY = process.env.NO_PROXY || windowsProxy.noProxy + } + + this._normalizeEnvironmentProxy() + + return 'win32' + } + }, +} diff --git a/packages/server/lib/util/proxy.ts b/packages/server/lib/util/proxy.ts deleted file mode 100644 index d8e0f36f27..0000000000 --- a/packages/server/lib/util/proxy.ts +++ /dev/null @@ -1,41 +0,0 @@ -import * as os from 'os' -import getWindowsProxy = require('@cypress/get-windows-proxy') - -export function _getWindowsProxy () { - return getWindowsProxy() -} - -export function _normalizeEnvironmentProxy () { - if (!process.env.HTTPS_PROXY) { - // request library will use HTTP_PROXY as a fallback for HTTPS urls, but - // proxy-from-env will not, so let's just force it to fall back like this - process.env.HTTPS_PROXY = process.env.HTTP_PROXY - } - - if (!process.env.NO_PROXY) { - // don't proxy localhost, to match Chrome's default behavior and user expectation - process.env.NO_PROXY = 'localhost' - } -} - -// @ts-ignore: Not all code paths return a value -export function loadSystemProxySettings () { - if (process.env.HTTP_PROXY !== undefined) { - _normalizeEnvironmentProxy() - - return - } - - if (os.platform() === 'win32') { - const windowsProxy = _getWindowsProxy() - - if (windowsProxy) { - process.env.HTTP_PROXY = process.env.HTTPS_PROXY = windowsProxy.httpProxy - process.env.NO_PROXY = process.env.NO_PROXY || windowsProxy.noProxy - } - - _normalizeEnvironmentProxy() - - return 'win32' - } -} diff --git a/packages/server/tsconfig.json b/packages/server/tsconfig.json deleted file mode 100644 index ffda540c36..0000000000 --- a/packages/server/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "./../ts/tsconfig.json", - "include": [ - "lib/*.ts", - "lib/**/*.ts" - ], - "files": [ - "./../ts/index.d.ts" - ] -} diff --git a/packages/ts/index.d.ts b/packages/ts/index.d.ts index 5b113bb25b..da2b5ea179 100644 --- a/packages/ts/index.d.ts +++ b/packages/ts/index.d.ts @@ -1,62 +1,6 @@ // missing type definitions for libraries // https://glebbahmutov.com/blog/trying-typescript/#manual-types-for-3rd-party-libraries -declare module '@cypress/get-windows-proxy' { - type ProxyConfig = { - httpProxy: string, - noProxy: string - } - function getWindowsProxy(): Optional - export = getWindowsProxy -} - -declare module 'http' { - import { Socket } from 'net' - import { Url } from 'url' - - type SocketCallback = (err: Optional, sock: Optional) => void - - interface Agent { - addRequest(req: ClientRequest, options: RequestOptions): void - createSocket(req: ClientRequest, options: RequestOptions, cb: SocketCallback): void - createConnection(options: RequestOptions, cb: Optional): void - } - - interface ClientRequest { - _header: { [key: string]:string } - _implicitHeader: () => void - output: string[] - path: string - agent: Agent - } - - interface RequestOptions { - _agentKey: Optional - host: string - href: string - path: Optional - port: number - proxy: Optional - servername: Optional - socket: Optional - uri: Url - } -} - -declare module 'net' { - interface Address { - address: string - family: 4 | 6 - } -} - -declare interface Object { - assign(...obj: any[]): any -} - -declare type Optional = T | void - - declare module 'plist' { interface Plist { parse: (s:string) => any @@ -69,6 +13,25 @@ declare module 'proxy-from-env' { const getProxyForUrl: (url: string) => string } +declare module 'http' { + import { Socket } from 'net' + + export interface Agent { + addRequest(req: ClientRequest, options: any): void + createSocket(req: ClientRequest, options: any, cb: (err: Error | undefined, sock: Socket) => void): void + } + + export interface ClientRequest { + _header: { [key: string]:string } + _implicitHeader: () => void + output: string[] + } +} + +declare interface Object { + assign(...obj: any[]): any +} + declare interface SymbolConstructor { for(str: string): SymbolConstructor } diff --git a/packages/ts/tsconfig.json b/packages/ts/tsconfig.json index b6741d9fc2..f41a73893b 100644 --- a/packages/ts/tsconfig.json +++ b/packages/ts/tsconfig.json @@ -36,8 +36,8 @@ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - //"typeRoots": [], /* List of folders to include type definitions from. */ - "types": ["mocha", "node"] /* Type declaration files to be included in compilation. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + "types": ["mocha"] /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ /* Source Map Options */