UNPKG

rekwest

Version:

The robust request library that humanity deserves 🌐

117 lines (116 loc) 4.49 kB
"use strict"; 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;