mirror of
https://github.com/cypress-io/cypress.git
synced 2026-01-04 05:29:45 -06:00
Revert "server, launcher, ts: typescript"
This reverts commit d3f8b8bbb6.
This commit is contained in:
10
package.json
10
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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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<Number>) => {
|
||||
.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, <RequestOptionsWithProxy>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 = <string>proxy
|
||||
if (proxy) {
|
||||
options.proxy = proxy
|
||||
|
||||
return this.createProxiedConnection(<RequestOptionsWithProxy>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)
|
||||
|
||||
62
packages/server/lib/util/connect.js
Normal file
62
packages/server/lib/util/connect.js
Normal file
@@ -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)
|
||||
},
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
42
packages/server/lib/util/proxy.js
Normal file
42
packages/server/lib/util/proxy.js
Normal file
@@ -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'
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -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'
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"extends": "./../ts/tsconfig.json",
|
||||
"include": [
|
||||
"lib/*.ts",
|
||||
"lib/**/*.ts"
|
||||
],
|
||||
"files": [
|
||||
"./../ts/index.d.ts"
|
||||
]
|
||||
}
|
||||
75
packages/ts/index.d.ts
vendored
75
packages/ts/index.d.ts
vendored
@@ -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<ProxyConfig>
|
||||
export = getWindowsProxy
|
||||
}
|
||||
|
||||
declare module 'http' {
|
||||
import { Socket } from 'net'
|
||||
import { Url } from 'url'
|
||||
|
||||
type SocketCallback = (err: Optional<Error>, sock: Optional<Socket>) => void
|
||||
|
||||
interface Agent {
|
||||
addRequest(req: ClientRequest, options: RequestOptions): void
|
||||
createSocket(req: ClientRequest, options: RequestOptions, cb: SocketCallback): void
|
||||
createConnection(options: RequestOptions, cb: Optional<SocketCallback>): void
|
||||
}
|
||||
|
||||
interface ClientRequest {
|
||||
_header: { [key: string]:string }
|
||||
_implicitHeader: () => void
|
||||
output: string[]
|
||||
path: string
|
||||
agent: Agent
|
||||
}
|
||||
|
||||
interface RequestOptions {
|
||||
_agentKey: Optional<symbol>
|
||||
host: string
|
||||
href: string
|
||||
path: Optional<string>
|
||||
port: number
|
||||
proxy: Optional<string>
|
||||
servername: Optional<string>
|
||||
socket: Optional<Socket>
|
||||
uri: Url
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'net' {
|
||||
interface Address {
|
||||
address: string
|
||||
family: 4 | 6
|
||||
}
|
||||
}
|
||||
|
||||
declare interface Object {
|
||||
assign(...obj: any[]): any
|
||||
}
|
||||
|
||||
declare type Optional<T> = 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
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user