From 1aa5e3c3d0b37ac83b78c9971177700ae0de2c72 Mon Sep 17 00:00:00 2001 From: Dave Cardwell Date: Tue, 26 Apr 2022 18:31:58 +0000 Subject: [PATCH] feat: pass the request method to beforeRedirect --- README.md | 4 +++- index.js | 2 ++ test/test.js | 28 ++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e41384b..15f3419 100644 --- a/README.md +++ b/README.md @@ -63,12 +63,14 @@ const { http, https } = require('follow-redirects'); const options = url.parse('http://bit.ly/900913'); options.maxRedirects = 10; -options.beforeRedirect = (options, { headers, statusCode, requestUrl }) => { +options.beforeRedirect = (options, { headers, statusCode, requestMethod, requestUrl }) => { // Use this to adjust the request options upon redirecting, // to inspect the latest response headers, // or to cancel the request by throwing an error + // headers = the redirect response headers // statusCode = the redirect response code (eg. 301, 307, etc.) + // requestMethod = the request method that resulted in a redirect // requestUrl = the requested URL that resulted in a redirect if (options.hostname === "example.com") { options.auth = "user:password"; diff --git a/index.js b/index.js index 5ff7532..0201acd 100644 --- a/index.js +++ b/index.js @@ -366,6 +366,7 @@ RedirectableRequest.prototype._processResponse = function (response) { // care for methods not known to be safe, […] // RFC7231§6.4.2–3: For historical reasons, a user agent MAY change // the request method from POST to GET for the subsequent request. + var originalRequestMethod = this._options.method; if ((statusCode === 301 || statusCode === 302) && this._options.method === "POST" || // RFC7231§6.4.4: The 303 (See Other) status code indicates that // the server is redirecting the user agent to a different resource […] @@ -417,6 +418,7 @@ RedirectableRequest.prototype._processResponse = function (response) { var responseDetails = { headers: response.headers, statusCode: statusCode, + requestMethod: originalRequestMethod, requestUrl: currentUrl, }; try { diff --git a/test/test.js b/test/test.js index 5e96924..3b6ac8b 100644 --- a/test/test.js +++ b/test/test.js @@ -1613,6 +1613,34 @@ describe("follow-redirects", function () { }); }); + it("passes the request method to beforeRedirect", function () { + app.post("/a", redirectsTo("/b", 308)); + app.post("/b", redirectsTo("/c", 301)); + app.get("/c", redirectsTo("/d", 301)); + app.get("/d", sendsJson({ a: "b" })); + + const requestMethods = []; + + return server.start(app) + .then(asPromise(function (resolve, reject) { + var options = { + host: "localhost", + port: 3600, + path: "/a", + method: "POST", + beforeRedirect: function (_, response) { + requestMethods.push(response.requestMethod); + }, + }; + http.get(options, concatJson(resolve, reject)).on("error", reject); + })) + .then(function (res) { + assert.deepEqual(res.responseUrl, "http://localhost:3600/d"); + assert.deepEqual(res.parsedJson, { a: "b" }); + assert.deepEqual(requestMethods, ["POST", "POST", "GET"]); + }); + }); + it("passes the original request URL to beforeRedirect", function () { app.get("/a", redirectsTo("/b")); app.get("/b", redirectsTo("/c"));