Skip to content

Commit

Permalink
Merge pull request #76 from rexxars/fix-proxy-issue
Browse files Browse the repository at this point in the history
Fix proxying when target protocol differs from proxy protocol
  • Loading branch information
rexxars committed May 28, 2017
2 parents 0c9eae0 + 70cfe6e commit 7ece6ba
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 6 deletions.
6 changes: 5 additions & 1 deletion lib/eventsource.js
Expand Up @@ -86,8 +86,12 @@ function EventSource (url, eventSourceInitDict) {

// If specify http proxy, make the request to sent to the proxy server,
// and include the original url in path and Host headers
if (eventSourceInitDict && eventSourceInitDict.proxy) {
var useProxy = eventSourceInitDict && eventSourceInitDict.proxy
if (useProxy) {
var proxy = parse(eventSourceInitDict.proxy)
isSecure = proxy.protocol === 'https:'

options.protocol = isSecure ? 'https:' : 'http:'
options.path = url
options.headers.Host = options.host
options.hostname = proxy.hostname
Expand Down
115 changes: 110 additions & 5 deletions test/eventsource_test.js
Expand Up @@ -11,6 +11,11 @@ var u = require('url')
var it = mocha.it
var describe = mocha.describe

var httpsServerOptions = {
key: fs.readFileSync(path.join(__dirname, 'server_certs', 'key.pem')),
cert: fs.readFileSync(path.join(__dirname, 'server_certs', 'certificate.pem'))
}

var _port = 20000
var servers = []
process.on('exit', function () {
Expand All @@ -25,11 +30,7 @@ function createServer (callback) {
}

function createHttpsServer (callback) {
var options = {
key: fs.readFileSync(path.join(__dirname, 'server_certs', 'key.pem')),
cert: fs.readFileSync(path.join(__dirname, 'server_certs', 'certificate.pem'))
}
var server = https.createServer(options)
var server = https.createServer(httpsServerOptions)
configureServer(server, 'https', _port++, callback)
}

Expand Down Expand Up @@ -72,6 +73,48 @@ function configureServer (server, protocol, port, callback) {
})
}

function createProxy (target, protocol, callback) {
var proxyPort = _port++
var targetProtocol = target.indexOf('https') === 0 ? 'https' : 'http'
var requester = targetProtocol === 'https' ? https : http
var serve = protocol === 'https' ? https : http

var proxied = []
var server = serve.createServer(serve === https ? httpsServerOptions : undefined)

server.on('request', function (req, res) {
var options = u.parse(target)
options.headers = req.headers
options.rejectUnauthorized = false

var upstreamReq = requester.request(options, function (upstreamRes) {
upstreamRes.pipe(res)
})

proxied.push(upstreamReq)
upstreamReq.end()
})

servers.push(server)

var oldClose = server.close
server.close = function (closeCb) {
proxied.forEach(function (res) {
res.abort()
})

oldClose.call(server, function () {
servers.splice(servers.indexOf(server), 1)
closeCb()
})
}

server.listen(proxyPort, function onOpen (err) {
server.url = protocol + '://localhost:' + proxyPort
callback(err, server)
})
}

function writeEvents (chunks) {
return function (req, res) {
res.writeHead(200, {'Content-Type': 'text/event-stream'})
Expand Down Expand Up @@ -1037,3 +1080,65 @@ describe('Events', function () {
})
})
})

describe('Proxying', function () {
it('proxies http->http requests', function (done) {
createServer(function (err, server) {
if (err) return done(err)

server.on('request', writeEvents(['data: World\n\n']))

createProxy(server.url, 'http', function (err, proxy) {
if (err) return done(err)

var es = new EventSource(server.url, {proxy: proxy.url})
es.onmessage = function (m) {
assert.equal(m.data, 'World')
proxy.close(function () {
server.close(done)
})
}
})
})
})

it('proxies http->https requests', function (done) {
createHttpsServer(function (err, server) {
if (err) return done(err)

server.on('request', writeEvents(['data: World\n\n']))

createProxy(server.url, 'http', function (err, proxy) {
if (err) return done(err)

var es = new EventSource(server.url, {proxy: proxy.url})
es.onmessage = function (m) {
assert.equal(m.data, 'World')
proxy.close(function () {
server.close(done)
})
}
})
})
})

it('proxies https->http requests', function (done) {
createHttpsServer(function (err, server) {
if (err) return done(err)

server.on('request', writeEvents(['data: World\n\n']))

createProxy(server.url, 'https', function (err, proxy) {
if (err) return done(err)

var es = new EventSource(server.url, {proxy: proxy.url, rejectUnauthorized: false})
es.onmessage = function (m) {
assert.equal(m.data, 'World')
proxy.close(function () {
server.close(done)
})
}
})
})
})
})

0 comments on commit 7ece6ba

Please sign in to comment.