Proxies the given request to the given URL, writing the result
in the given response object.

@method proxyRequest
@for robohydra
@param {Request} req The request object to proxy.
@param {Response} res The response object to write the result to.
@param {URL} proxyTo The URL to proxy to, either in the form of
a URL object (result of the url.parse method) or a string.
@param {Object} opts
@param {Function} opts.httpRequestFunction The http.request
function or a mock of it.
@param {Function} opts.httpsRequestFunction The https.request
function or a mock of it.
@param {Boolean} opts.setHostHeader Specifies if the "Host"
header should be set in the proxied request, so pretend as if
the original request was indeed intended for the final
URL. Defaults to false.
function proxyRequest(req, res, proxyTo, opts) {
        opts = opts || {};
        var httpRequestFunction  = opts.httpRequestFunction  || http.request;
        var httpsRequestFunction = opts.httpsRequestFunction || https.request;
        var setHostHeader = opts.setHostHeader;

        var proxyUrl = proxyTo;
        if (typeof(proxyTo) === 'string') {
            proxyUrl = url.parse(proxyTo, true);
        }
        var proxyToHost = proxyUrl.hostname;
        var proxyToPort = proxyUrl.port ||
                (proxyUrl.protocol === 'https:' ? 443 : 80);
        var proxyToPath = proxyUrl.pathname +
            (proxyUrl.search === null ? "" : proxyUrl.search);
        var requestFunction = (proxyUrl.protocol === 'https:') ?
                httpsRequestFunction : httpRequestFunction;
        var headers = {};
        for (var h in req.headers) { headers[h] = req.headers[h]; }
        if (setHostHeader) {
            headers.host = proxyToHost +
                (proxyUrl.port ? ":" + proxyUrl.port : "");
        }

        var proxyReq = requestFunction(
            {host: proxyToHost,
             port: proxyToPort,
             method: req.method,
             path: proxyToPath,
             headers: headers},
            function (proxyRes) {
                // Copy over headers and status code from proxied request
                res.statusCode = proxyRes.statusCode;
                res.headers    = proxyRes.headers;

                proxyRes.on("data", function (chunk) {
                    res.write(chunk);
                });

                proxyRes.on("end", function () {
                    res.end();
                });
            });

        proxyReq.on('error', function (err) {
            res.statusCode = 502;
            res.send('Bad Gateway! Could not proxy request. Invalid host or proxy destination down? Reported error was: ' + err);
        });

        if (req.rawBody) {
            proxyReq.write(req.rawBody);
        }
        proxyReq.end();
    }