mirror of
https://github.com/fjogeleit/http-request-action.git
synced 2024-12-27 20:34:43 -05:00
parent
31fad16908
commit
046e838b3a
2 changed files with 96 additions and 90 deletions
173
dist/index.js
vendored
173
dist/index.js
vendored
|
@ -4158,96 +4158,101 @@ RedirectableRequest.prototype._processResponse = function (response) {
|
|||
// the user agent MAY automatically redirect its request to the URI
|
||||
// referenced by the Location field value,
|
||||
// even if the specific status code is not understood.
|
||||
|
||||
// If the response is not a redirect; return it as-is
|
||||
var location = response.headers.location;
|
||||
if (location && this._options.followRedirects !== false &&
|
||||
statusCode >= 300 && statusCode < 400) {
|
||||
// Abort the current request
|
||||
abortRequest(this._currentRequest);
|
||||
// Discard the remainder of the response to avoid waiting for data
|
||||
response.destroy();
|
||||
|
||||
// RFC7231§6.4: A client SHOULD detect and intervene
|
||||
// in cyclical redirections (i.e., "infinite" redirection loops).
|
||||
if (++this._redirectCount > this._options.maxRedirects) {
|
||||
this.emit("error", new TooManyRedirectsError());
|
||||
return;
|
||||
}
|
||||
|
||||
// RFC7231§6.4: Automatic redirection needs to done with
|
||||
// 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.
|
||||
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 […]
|
||||
// A user agent can perform a retrieval request targeting that URI
|
||||
// (a GET or HEAD request if using HTTP) […]
|
||||
(statusCode === 303) && !/^(?:GET|HEAD)$/.test(this._options.method)) {
|
||||
this._options.method = "GET";
|
||||
// Drop a possible entity and headers related to it
|
||||
this._requestBodyBuffers = [];
|
||||
removeMatchingHeaders(/^content-/i, this._options.headers);
|
||||
}
|
||||
|
||||
// Drop the Host header, as the redirect might lead to a different host
|
||||
var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers);
|
||||
|
||||
// If the redirect is relative, carry over the host of the last request
|
||||
var currentUrlParts = url.parse(this._currentUrl);
|
||||
var currentHost = currentHostHeader || currentUrlParts.host;
|
||||
var currentUrl = /^\w+:/.test(location) ? this._currentUrl :
|
||||
url.format(Object.assign(currentUrlParts, { host: currentHost }));
|
||||
|
||||
// Determine the URL of the redirection
|
||||
var redirectUrl;
|
||||
try {
|
||||
redirectUrl = url.resolve(currentUrl, location);
|
||||
}
|
||||
catch (cause) {
|
||||
this.emit("error", new RedirectionError(cause));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the redirected request
|
||||
debug("redirecting to", redirectUrl);
|
||||
this._isRedirect = true;
|
||||
var redirectUrlParts = url.parse(redirectUrl);
|
||||
Object.assign(this._options, redirectUrlParts);
|
||||
|
||||
// Drop the confidential headers when redirecting to another domain
|
||||
if (!(redirectUrlParts.host === currentHost || isSubdomainOf(redirectUrlParts.host, currentHost))) {
|
||||
removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers);
|
||||
}
|
||||
|
||||
// Evaluate the beforeRedirect callback
|
||||
if (typeof this._options.beforeRedirect === "function") {
|
||||
var responseDetails = { headers: response.headers };
|
||||
try {
|
||||
this._options.beforeRedirect.call(null, this._options, responseDetails);
|
||||
}
|
||||
catch (err) {
|
||||
this.emit("error", err);
|
||||
return;
|
||||
}
|
||||
this._sanitizeOptions(this._options);
|
||||
}
|
||||
|
||||
// Perform the redirected request
|
||||
try {
|
||||
this._performRequest();
|
||||
}
|
||||
catch (cause) {
|
||||
this.emit("error", new RedirectionError(cause));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The response is not a redirect; return it as-is
|
||||
if (!location || this._options.followRedirects === false ||
|
||||
statusCode < 300 || statusCode >= 400) {
|
||||
response.responseUrl = this._currentUrl;
|
||||
response.redirects = this._redirects;
|
||||
this.emit("response", response);
|
||||
|
||||
// Clean up
|
||||
this._requestBodyBuffers = [];
|
||||
return;
|
||||
}
|
||||
|
||||
// The response is a redirect, so abort the current request
|
||||
abortRequest(this._currentRequest);
|
||||
// Discard the remainder of the response to avoid waiting for data
|
||||
response.destroy();
|
||||
|
||||
// RFC7231§6.4: A client SHOULD detect and intervene
|
||||
// in cyclical redirections (i.e., "infinite" redirection loops).
|
||||
if (++this._redirectCount > this._options.maxRedirects) {
|
||||
this.emit("error", new TooManyRedirectsError());
|
||||
return;
|
||||
}
|
||||
|
||||
// RFC7231§6.4: Automatic redirection needs to done with
|
||||
// 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.
|
||||
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 […]
|
||||
// A user agent can perform a retrieval request targeting that URI
|
||||
// (a GET or HEAD request if using HTTP) […]
|
||||
(statusCode === 303) && !/^(?:GET|HEAD)$/.test(this._options.method)) {
|
||||
this._options.method = "GET";
|
||||
// Drop a possible entity and headers related to it
|
||||
this._requestBodyBuffers = [];
|
||||
removeMatchingHeaders(/^content-/i, this._options.headers);
|
||||
}
|
||||
|
||||
// Drop the Host header, as the redirect might lead to a different host
|
||||
var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers);
|
||||
|
||||
// If the redirect is relative, carry over the host of the last request
|
||||
var currentUrlParts = url.parse(this._currentUrl);
|
||||
var currentHost = currentHostHeader || currentUrlParts.host;
|
||||
var currentUrl = /^\w+:/.test(location) ? this._currentUrl :
|
||||
url.format(Object.assign(currentUrlParts, { host: currentHost }));
|
||||
|
||||
// Determine the URL of the redirection
|
||||
var redirectUrl;
|
||||
try {
|
||||
redirectUrl = url.resolve(currentUrl, location);
|
||||
}
|
||||
catch (cause) {
|
||||
this.emit("error", new RedirectionError(cause));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the redirected request
|
||||
debug("redirecting to", redirectUrl);
|
||||
this._isRedirect = true;
|
||||
var redirectUrlParts = url.parse(redirectUrl);
|
||||
Object.assign(this._options, redirectUrlParts);
|
||||
|
||||
// Drop confidential headers when redirecting to a less secure protocol
|
||||
// or to a different domain that is not a superdomain
|
||||
if (redirectUrlParts.protocol !== currentUrlParts.protocol &&
|
||||
redirectUrlParts.protocol !== "https:" ||
|
||||
redirectUrlParts.host !== currentHost &&
|
||||
!isSubdomain(redirectUrlParts.host, currentHost)) {
|
||||
removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers);
|
||||
}
|
||||
|
||||
// Evaluate the beforeRedirect callback
|
||||
if (typeof this._options.beforeRedirect === "function") {
|
||||
var responseDetails = { headers: response.headers };
|
||||
try {
|
||||
this._options.beforeRedirect.call(null, this._options, responseDetails);
|
||||
}
|
||||
catch (err) {
|
||||
this.emit("error", err);
|
||||
return;
|
||||
}
|
||||
this._sanitizeOptions(this._options);
|
||||
}
|
||||
|
||||
// Perform the redirected request
|
||||
try {
|
||||
this._performRequest();
|
||||
}
|
||||
catch (cause) {
|
||||
this.emit("error", new RedirectionError(cause));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -4381,7 +4386,7 @@ function abortRequest(request) {
|
|||
request.abort();
|
||||
}
|
||||
|
||||
function isSubdomainOf(subdomain, domain) {
|
||||
function isSubdomain(subdomain, domain) {
|
||||
const dot = subdomain.length - domain.length - 1;
|
||||
return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
|
||||
}
|
||||
|
|
13
package-lock.json
generated
13
package-lock.json
generated
|
@ -5,6 +5,7 @@
|
|||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "http-request-action",
|
||||
"version": "1.9.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
@ -76,9 +77,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.14.8",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
|
||||
"integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==",
|
||||
"version": "1.14.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
|
||||
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
|
@ -187,9 +188,9 @@
|
|||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.14.8",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
|
||||
"integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA=="
|
||||
"version": "1.14.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
|
||||
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w=="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
|
|
Loading…
Reference in a new issue