Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix proxying when target protocol differs from proxy protocol #76

Merged
merged 1 commit into from May 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 @@ -1019,3 +1062,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)
})
}
})
})
})
})