Skip to content

Commit

Permalink
Merge a2a8f23 into 22e81fc
Browse files Browse the repository at this point in the history
  • Loading branch information
mbargiel committed May 26, 2022
2 parents 22e81fc + a2a8f23 commit 6874512
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 6 deletions.
15 changes: 10 additions & 5 deletions index.js
Expand Up @@ -274,21 +274,26 @@ RedirectableRequest.prototype._performRequest = function () {
this._options.agent = this._options.agents[scheme];
}

// Create the native request
// Create the native request and set up its event handlers
var request = this._currentRequest =
nativeProtocol.request(this._options, this._onNativeResponse);
this._currentUrl = url.format(this._options);

// Set up event handlers
request._redirectable = this;
for (var e = 0; e < events.length; e++) {
request.on(events[e], eventHandlers[events[e]]);
}

// RFC7230§5.3.1: When making a request directly to an origin server, […]
// a client MUST send only the absolute path […] as the request-target.
this._currentUrl = /^\//.test(this._options.path) ?
url.format(this._options) :
// When making a request to a proxy, […]
// a client MUST send the target URI in absolute-form […].
this._currentUrl = this._options.path;

// End a redirected request
// (The first request must be ended explicitly with RedirectableRequest#end)
if (this._isRedirect) {
// Write the request entity and end.
// Write the request entity and end
var i = 0;
var self = this;
var buffers = this._requestBodyBuffers;
Expand Down
42 changes: 41 additions & 1 deletion test/test.js
Expand Up @@ -17,6 +17,7 @@ var delay = util.delay;
var redirectsTo = util.redirectsTo;
var sendsJson = util.sendsJson;
var asPromise = util.asPromise;
var proxy = util.proxy;

var testFile = path.resolve(__dirname, "assets/input.txt");
var testFileBuffer = fs.readFileSync(testFile);
Expand Down Expand Up @@ -297,7 +298,7 @@ describe("follow-redirects", function () {
});
});

it("emits an error whem url.resolve fails", function () {
it("emits an error when url.resolve fails", function () {
app.get("/a", redirectsTo("/b"));
var urlResolve = url.resolve;
url.resolve = function () {
Expand Down Expand Up @@ -2080,6 +2081,45 @@ describe("follow-redirects", function () {
});
});
});

describe("when request is going through an HTTP proxy (without a tunnel)", function () {
[
{ redirectType: "absolute", redirectUrl: "http://localhost:3600/b" },
{ redirectType: "relative", redirectUrl: "/b" },
].forEach(function (testCase) {
it("redirects to proper URL when Location header is " + testCase.redirectType, function () {
app.get("/a", redirectsTo(testCase.redirectUrl));
app.get("/b", sendsJson({ good: "yes" }));
app2.port = 3601;
app2.all("*", proxy("localhost:3601"));

function setProxy(opts) {
// assuming opts is a url.parse result
// Update path and Host header
opts.path = opts.href;
opts.pathname = opts.href;

// Update port and host to target proxy host
opts.port = 3601;
opts.host = opts.hostname + ":" + opts.port;

// redirected requests use proxy too
opts.beforeRedirect = setProxy;
}
return Promise.all([server.start(app), server.start(app2)])
.then(asPromise(function (resolve, reject) {
var opts = Object.assign({}, url.parse("http://localhost:3600/a"));
setProxy(opts);

http.get(opts, concatJson(resolve, reject)).on("error", reject);
}))
.then(function (res) {
assert.deepEqual(res.parsedJson, { good: "yes" });
assert.deepEqual(res.responseUrl, "http://localhost:3600/b");
});
});
});
});
});

function noop() { /* noop */ }
25 changes: 25 additions & 0 deletions test/util.js
@@ -1,4 +1,7 @@
var concat = require("concat-stream");
var http = require("http");
var https = require("https");
var url = require("url");

function redirectsTo() {
var args = Array.prototype.slice.call(arguments);
Expand Down Expand Up @@ -42,10 +45,32 @@ function asPromise(cb) {
};
}

function proxy(proxyHost) {
return function (req, res) {
var upstreamUrl = url.parse(req.originalUrl);
if (upstreamUrl.host === proxyHost) {
res.writeHead(400, "Bad request");
res.write(JSON.stringify({ bad: "detected proxy recursion" }));
res.end();
}
else {
var transport = /https:?/.test(upstreamUrl.protocol) ? https : http;
var upstreamReq = transport.request(req.originalUrl, {
headers: req.headers,
}, function (upstreamRes) {
res.writeHead(upstreamRes.statusCode, upstreamRes.statusMessage, upstreamRes.headers);
upstreamRes.pipe(res);
});
upstreamReq.end();
}
};
}

module.exports = {
asPromise: asPromise,
concatJson: concatJson,
delay: delay,
proxy: proxy,
redirectsTo: redirectsTo,
sendsJson: sendsJson,
};

0 comments on commit 6874512

Please sign in to comment.