-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathproxy.js
136 lines (114 loc) · 4 KB
/
proxy.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
var url = require('url')
var httpProxy = require('http-proxy')
var log = require('../logger').create('proxy')
var _ = require('../helper')._
var parseProxyConfig = function (proxies, config) {
var endsWithSlash = function (str) {
return str.substr(-1) === '/'
}
if (!proxies) {
return []
}
return _.sortBy(_.map(proxies, function (proxyConfiguration, proxyPath) {
if (typeof proxyConfiguration === 'string') {
proxyConfiguration = {target: proxyConfiguration}
}
var proxyUrl = proxyConfiguration.target
var proxyDetails = url.parse(proxyUrl)
var pathname = proxyDetails.pathname
// normalize the proxies config
// should we move this to lib/config.js ?
if (endsWithSlash(proxyPath) && !endsWithSlash(proxyUrl)) {
log.warn('proxy "%s" normalized to "%s"', proxyUrl, proxyUrl + '/')
proxyUrl += '/'
pathname += '/'
}
if (!endsWithSlash(proxyPath) && endsWithSlash(proxyUrl)) {
log.warn('proxy "%s" normalized to "%s"', proxyPath, proxyPath + '/')
proxyPath += '/'
}
if (pathname === '/' && !endsWithSlash(proxyUrl)) {
pathname = ''
}
var hostname = proxyDetails.hostname || config.hostname
var protocol = proxyDetails.protocol || config.protocol
var port = proxyDetails.port || config.port ||
(proxyDetails.protocol === 'https:' ? '443' : '80')
var https = proxyDetails.protocol === 'https:'
var changeOrigin = 'changeOrigin' in proxyConfiguration ? proxyConfiguration.changeOrigin : false
var proxy = httpProxy.createProxyServer({
target: {
host: hostname,
port: port,
https: https,
protocol: protocol
},
xfwd: true,
changeOrigin: changeOrigin,
secure: config.proxyValidateSSL
})
proxy.on('error', function proxyError (err, req, res) {
if (err.code === 'ECONNRESET' && req.socket.destroyed) {
log.debug('failed to proxy %s (browser hung up the socket)', req.url)
} else {
log.warn('failed to proxy %s (%s)', req.url, err.message)
}
res.destroy()
})
return {
path: proxyPath,
baseUrl: pathname,
host: hostname,
port: port,
https: https,
proxy: proxy
}
}), 'path').reverse()
}
/**
* Returns a handler which understands the proxies and its redirects, along with the proxy to use
* @param proxies An array of proxy record objects
* @param urlRoot The URL root that karma is mounted on
* @return {Function} handler function
*/
var createProxyHandler = function (proxies, urlRoot) {
if (!proxies.length) {
var nullProxy = function createNullProxy (request, response, next) {
return next()
}
nullProxy.upgrade = function upgradeNullProxy () {}
return nullProxy
}
var middleware = function createProxy (request, response, next) {
var proxyRecord = _.find(proxies, function (p) {
return request.url.indexOf(p.path) === 0
})
if (!proxyRecord) {
return next()
}
log.debug('proxying request - %s to %s:%s', request.url, proxyRecord.host, proxyRecord.port)
request.url = request.url.replace(proxyRecord.path, proxyRecord.baseUrl)
proxyRecord.proxy.web(request, response)
}
middleware.upgrade = function upgradeProxy (request, socket, head) {
// special-case karma's route to avoid upgrading it
if (request.url.indexOf(urlRoot) === 0) {
log.debug('NOT upgrading proxyWebSocketRequest %s', request.url)
return
}
var proxyRecord = _.find(proxies, function (p) {
return request.url.indexOf(p.path) === 0
})
if (!proxyRecord) {
return
}
log.debug('upgrade proxyWebSocketRequest %s to %s:%s',
request.url, proxyRecord.host, proxyRecord.port)
request.url = request.url.replace(proxyRecord.path, proxyRecord.baseUrl)
proxyRecord.proxy.ws(request, socket, head)
}
return middleware
}
exports.create = function (/* config */config, /* config.proxies */proxies) {
return createProxyHandler(parseProxyConfig(proxies, config), config.urlRoot)
}