rekwest
Version:
The robust request library that humanity deserves 🌐
117 lines (116 loc) • 4.49 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.postflight = void 0;
var _nodeHttp = _interopRequireDefault(require("node:http2"));
var _promises = require("node:timers/promises");
var _constants = require("./constants");
var _cookies = require("./cookies");
var _errors = require("./errors");
var _index = _interopRequireDefault(require("./index"));
var _mixin = require("./mixin");
var _utils = require("./utils");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const {
HTTP2_HEADER_LOCATION,
HTTP2_HEADER_RETRY_AFTER,
HTTP2_HEADER_SET_COOKIE,
HTTP2_METHOD_GET,
HTTP2_METHOD_HEAD,
HTTP2_METHOD_POST,
HTTP_STATUS_BAD_REQUEST,
HTTP_STATUS_FOUND,
HTTP_STATUS_MOVED_PERMANENTLY,
HTTP_STATUS_SEE_OTHER
} = _nodeHttp.default.constants;
const postflight = (req, res, options, {
reject,
resolve
}) => {
const {
cookies,
credentials,
follow,
h2,
redirect,
url
} = options;
let headers;
if (h2) {
headers = res;
res = req;
} else {
res.once('error', reject);
}
(0, _utils.admix)(res, headers, options);
if (cookies !== false && res.headers[HTTP2_HEADER_SET_COOKIE]) {
if (_cookies.Cookies.jar.has(url.origin)) {
const cookie = new _cookies.Cookies(res.headers[HTTP2_HEADER_SET_COOKIE], options);
_cookies.Cookies.jar.get(url.origin).forEach((val, key) => {
if (!cookie.has(key)) {
cookie.set(key, val);
}
});
_cookies.Cookies.jar.set(url.origin, cookie);
} else {
_cookies.Cookies.jar.set(url.origin, new _cookies.Cookies(res.headers[HTTP2_HEADER_SET_COOKIE], options));
}
}
Reflect.defineProperty(res, 'cookies', {
enumerable: true,
value: cookies !== false && _cookies.Cookies.jar.has(url.origin) ? _cookies.Cookies.jar.get(url.origin) : void 0
});
const {
statusCode
} = res;
if (follow && /3\d{2}/.test(statusCode) && res.headers[HTTP2_HEADER_LOCATION]) {
if (!_constants.requestRedirectCodes.includes(statusCode)) {
return res.emit('error', new RangeError(`Invalid status code: ${statusCode}`));
}
if (redirect === _constants.requestRedirect.error) {
return res.emit('error', new _errors.RequestError(`Unexpected redirect, redirect mode is set to '${redirect}'.`));
}
if (redirect === _constants.requestRedirect.follow) {
const location = new URL(res.headers[HTTP2_HEADER_LOCATION], url);
if (!/^https?:/i.test(location.protocol)) {
return res.emit('error', new _errors.RequestError('URL scheme must be "http" or "https".'));
}
if (!(0, _utils.sameOrigin)(location, url)) {
if (credentials !== _constants.requestCredentials.include) {
options.credentials = _constants.requestCredentials.omit;
}
options.h2 = false;
}
if (statusCode !== HTTP_STATUS_SEE_OTHER && options.body?.pipe?.constructor === Function) {
return res.emit('error', new _errors.RequestError(`Unable to ${redirect} redirect with streamable body.`));
}
if ([HTTP_STATUS_MOVED_PERMANENTLY, HTTP_STATUS_FOUND].includes(statusCode) && options.method === HTTP2_METHOD_POST || statusCode === HTTP_STATUS_SEE_OTHER && ![HTTP2_METHOD_GET, HTTP2_METHOD_HEAD].includes(options.method)) {
for (const it of Object.keys(options.headers).filter(val => /^content-/i.test(val))) {
Reflect.deleteProperty(options.headers, it);
}
options.body = null;
options.method = HTTP2_METHOD_GET;
}
options.follow--;
options.redirected = true;
options.url = location;
if (statusCode === HTTP_STATUS_MOVED_PERMANENTLY && res.headers[HTTP2_HEADER_RETRY_AFTER]) {
let interval = res.headers[HTTP2_HEADER_RETRY_AFTER];
interval = Number(interval) * 1e3 || new Date(interval) - Date.now();
if (interval > options.maxRetryAfter) {
return res.emit('error', (0, _utils.maxRetryAfterError)(interval, {
cause: (0, _mixin.mixin)(res, options)
}));
}
return (0, _promises.setTimeout)(interval).then(() => (0, _index.default)(options.url, options).then(resolve, reject));
}
return (0, _index.default)(options.url, options).then(resolve, reject);
}
}
if (statusCode >= HTTP_STATUS_BAD_REQUEST) {
return reject((0, _mixin.mixin)(res, options));
}
resolve((0, _mixin.mixin)(res, options));
};
exports.postflight = postflight;