Skip to content

Commit

Permalink
- Remove Host header only if redirecting to a new host.
Browse files Browse the repository at this point in the history
- Clarify logic to operate on host instead of hostname to keep/remove Host and Authorization headers. Host header is hostname+port.
  • Loading branch information
skillsoftstevemarusa committed Oct 4, 2021
1 parent 77e2a58 commit 2f7164f
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 7 deletions.
21 changes: 16 additions & 5 deletions index.js
Expand Up @@ -360,9 +360,9 @@ RedirectableRequest.prototype._processResponse = function (response) {
removeMatchingHeaders(/^content-/i, this._options.headers);
}

// Drop the Host header, as the redirect might lead to a different host
var previousHostName = removeMatchingHeaders(/^host$/i, this._options.headers) ||
url.parse(this._currentUrl).hostname;
// Prefer previous host from Host header
var previousHost = getMatchingHeader(/^host$/i, this._options.headers) ||
url.parse(this._currentUrl).host;

// Create the redirected request
var redirectUrl = url.resolve(this._currentUrl, location);
Expand All @@ -371,8 +371,9 @@ RedirectableRequest.prototype._processResponse = function (response) {
var redirectUrlParts = url.parse(redirectUrl);
Object.assign(this._options, redirectUrlParts);

// Drop the Authorization header if redirecting to another host
if (redirectUrlParts.hostname !== previousHostName) {
// Drop the Host & Authorization header if redirecting to another host
if (redirectUrlParts.host !== previousHost && url.parse(location).host) {
removeMatchingHeaders(/^host$/i, this._options.headers);
removeMatchingHeaders(/^authorization$/i, this._options.headers);
}

Expand Down Expand Up @@ -502,6 +503,16 @@ function urlToOptions(urlObject) {
return options;
}

function getMatchingHeader(regex, headers) {
var lastValue;
for (var header in headers) {
if (regex.test(header)) {
lastValue = headers[header];
}
}
return lastValue;
}

function removeMatchingHeaders(regex, headers) {
var lastValue;
for (var header in headers) {
Expand Down
52 changes: 50 additions & 2 deletions test/test.js
Expand Up @@ -1219,7 +1219,7 @@ describe("follow-redirects", function () {
});

describe("when redirecting to a different host while the host header is set", function () {
it("uses the new host header", function () {
it("uses the new host header if redirect host is different", function () {
app.get("/a", redirectsTo(302, "http://localhost:3600/b"));
app.get("/b", function (req, res) {
res.write(JSON.stringify(req.headers));
Expand All @@ -1242,6 +1242,54 @@ describe("follow-redirects", function () {
assert.equal(body.host, "localhost:3600");
});
});

it("uses the existing host header if redirect host is the same", function () {
app.get("/a", redirectsTo(302, "http://localhost:3600/b"));
app.get("/b", function (req, res) {
res.write(JSON.stringify(req.headers));
req.pipe(res); // will invalidate JSON if non-empty
});

return server.start(app)
.then(asPromise(function (resolve, reject) {
var opts = url.parse("http://127.0.0.1:3600/a");
opts.headers = { hOsT: "localhost:3600" };
http.get(opts, resolve).on("error", reject);
}))
.then(asPromise(function (resolve, reject, res) {
assert.deepEqual(res.statusCode, 200);
assert.deepEqual(res.responseUrl, "http://localhost:3600/b");
res.pipe(concat({ encoding: "string" }, resolve)).on("error", reject);
}))
.then(function (str) {
var body = JSON.parse(str);
assert.equal(body.host, "localhost:3600");
});
});

it("uses the existing host header if redirect host is relative", function () {
app.get("/a", redirectsTo(302, "/b"));
app.get("/b", function (req, res) {
res.write(JSON.stringify(req.headers));
req.pipe(res); // will invalidate JSON if non-empty
});

return server.start(app)
.then(asPromise(function (resolve, reject) {
var opts = url.parse("http://127.0.0.1:3600/a");
opts.headers = { hOsT: "localhost:3600" };
http.get(opts, resolve).on("error", reject);
}))
.then(asPromise(function (resolve, reject, res) {
assert.deepEqual(res.statusCode, 200);
assert.deepEqual(res.responseUrl, "http://127.0.0.1:3600/b");
res.pipe(concat({ encoding: "string" }, resolve)).on("error", reject);
}))
.then(function (str) {
var body = JSON.parse(str);
assert.equal(body.host, "localhost:3600");
});
});
});

describe("when the client passes an Authorization header", function () {
Expand Down Expand Up @@ -1278,7 +1326,7 @@ describe("follow-redirects", function () {

var opts = url.parse("http://127.0.0.1:3600/a");
opts.headers = {
host: "localhost",
host: "localhost:3600",
authorization: "bearer my-token-1234",
};

Expand Down

0 comments on commit 2f7164f

Please sign in to comment.