123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.GlobalAPIRequestContext = exports.BrowserContextAPIRequestContext = exports.APIRequestContext = void 0;
- var http = _interopRequireWildcard(require("http"));
- var https = _interopRequireWildcard(require("https"));
- var _stream = require("stream");
- var _url = _interopRequireDefault(require("url"));
- var _zlib = _interopRequireDefault(require("zlib"));
- var _timeoutSettings = require("../common/timeoutSettings");
- var _userAgent = require("../utils/userAgent");
- var _utils = require("../utils");
- var _utilsBundle = require("../utilsBundle");
- var _browserContext = require("./browserContext");
- var _cookieStore = require("./cookieStore");
- var _formData = require("./formData");
- var _happyEyeballs = require("../utils/happy-eyeballs");
- var _instrumentation = require("./instrumentation");
- var _progress = require("./progress");
- var _tracing = require("./trace/recorder/tracing");
- var _network = require("./network");
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
- /**
- * Copyright (c) Microsoft Corporation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class APIRequestContext extends _instrumentation.SdkObject {
- static findResponseBody(guid) {
- for (const request of APIRequestContext.allInstances) {
- const body = request.fetchResponses.get(guid);
- if (body) return body;
- }
- return undefined;
- }
- constructor(parent) {
- super(parent, 'request-context');
- this.fetchResponses = new Map();
- this.fetchLog = new Map();
- this._activeProgressControllers = new Set();
- this._closeReason = void 0;
- APIRequestContext.allInstances.add(this);
- }
- _disposeImpl() {
- APIRequestContext.allInstances.delete(this);
- this.fetchResponses.clear();
- this.fetchLog.clear();
- this.emit(APIRequestContext.Events.Dispose);
- }
- disposeResponse(fetchUid) {
- this.fetchResponses.delete(fetchUid);
- this.fetchLog.delete(fetchUid);
- }
- _storeResponseBody(body) {
- const uid = (0, _utils.createGuid)();
- this.fetchResponses.set(uid, body);
- return uid;
- }
- async fetch(params, metadata) {
- var _params$method;
- const defaults = this._defaultOptions();
- const headers = {
- 'user-agent': defaults.userAgent,
- 'accept': '*/*',
- 'accept-encoding': 'gzip,deflate,br'
- };
- if (defaults.extraHTTPHeaders) {
- for (const {
- name,
- value
- } of defaults.extraHTTPHeaders) setHeader(headers, name, value);
- }
- if (params.headers) {
- for (const {
- name,
- value
- } of params.headers) setHeader(headers, name, value);
- }
- const requestUrl = new URL(params.url, defaults.baseURL);
- if (params.params) {
- for (const {
- name,
- value
- } of params.params) requestUrl.searchParams.set(name, value);
- }
- const method = ((_params$method = params.method) === null || _params$method === void 0 ? void 0 : _params$method.toUpperCase()) || 'GET';
- const proxy = defaults.proxy;
- let agent;
- if (proxy && proxy.server !== 'per-context' && !shouldBypassProxy(requestUrl, proxy.bypass)) {
- var _proxyOpts$protocol;
- const proxyOpts = _url.default.parse(proxy.server);
- if ((_proxyOpts$protocol = proxyOpts.protocol) !== null && _proxyOpts$protocol !== void 0 && _proxyOpts$protocol.startsWith('socks')) {
- agent = new _utilsBundle.SocksProxyAgent({
- host: proxyOpts.hostname,
- port: proxyOpts.port || undefined
- });
- } else {
- if (proxy.username) proxyOpts.auth = `${proxy.username}:${proxy.password || ''}`;
- // TODO: We should use HttpProxyAgent conditional on proxyOpts.protocol instead of always using CONNECT method.
- agent = new _utilsBundle.HttpsProxyAgent(proxyOpts);
- }
- }
- const timeout = defaults.timeoutSettings.timeout(params);
- const deadline = timeout && (0, _utils.monotonicTime)() + timeout;
- const options = {
- method,
- headers,
- agent,
- maxRedirects: params.maxRedirects === 0 ? -1 : params.maxRedirects === undefined ? 20 : params.maxRedirects,
- timeout,
- deadline,
- __testHookLookup: params.__testHookLookup
- };
- // rejectUnauthorized = undefined is treated as true in node 12.
- if (params.ignoreHTTPSErrors || defaults.ignoreHTTPSErrors) options.rejectUnauthorized = false;
- const postData = serializePostData(params, headers);
- if (postData) setHeader(headers, 'content-length', String(postData.byteLength));
- const controller = new _progress.ProgressController(metadata, this);
- const fetchResponse = await controller.run(progress => {
- return this._sendRequest(progress, requestUrl, options, postData);
- });
- const fetchUid = this._storeResponseBody(fetchResponse.body);
- this.fetchLog.set(fetchUid, controller.metadata.log);
- if (params.failOnStatusCode && (fetchResponse.status < 200 || fetchResponse.status >= 400)) throw new Error(`${fetchResponse.status} ${fetchResponse.statusText}`);
- return {
- ...fetchResponse,
- fetchUid
- };
- }
- _parseSetCookieHeader(responseUrl, setCookie) {
- if (!setCookie) return [];
- const url = new URL(responseUrl);
- // https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4
- const defaultPath = '/' + url.pathname.substr(1).split('/').slice(0, -1).join('/');
- const cookies = [];
- for (const header of setCookie) {
- // Decode cookie value?
- const cookie = parseCookie(header);
- if (!cookie) continue;
- // https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3
- if (!cookie.domain) cookie.domain = url.hostname;else (0, _utils.assert)(cookie.domain.startsWith('.') || !cookie.domain.includes('.'));
- if (!(0, _cookieStore.domainMatches)(url.hostname, cookie.domain)) continue;
- // https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.4
- if (!cookie.path || !cookie.path.startsWith('/')) cookie.path = defaultPath;
- cookies.push(cookie);
- }
- return cookies;
- }
- async _updateRequestCookieHeader(url, headers) {
- if (getHeader(headers, 'cookie') !== undefined) return;
- const cookies = await this._cookies(url);
- if (cookies.length) {
- const valueArray = cookies.map(c => `${c.name}=${c.value}`);
- setHeader(headers, 'cookie', valueArray.join('; '));
- }
- }
- async _sendRequest(progress, url, options, postData) {
- var _getHeader;
- await this._updateRequestCookieHeader(url, options.headers);
- const requestCookies = ((_getHeader = getHeader(options.headers, 'cookie')) === null || _getHeader === void 0 ? void 0 : _getHeader.split(';').map(p => {
- const [name, value] = p.split('=').map(v => v.trim());
- return {
- name,
- value
- };
- })) || [];
- const requestEvent = {
- url,
- method: options.method,
- headers: options.headers,
- cookies: requestCookies,
- postData
- };
- this.emit(APIRequestContext.Events.Request, requestEvent);
- return new Promise((fulfill, reject) => {
- const requestConstructor = (url.protocol === 'https:' ? https : http).request;
- // If we have a proxy agent already, do not override it.
- const agent = options.agent || (url.protocol === 'https:' ? _happyEyeballs.httpsHappyEyeballsAgent : _happyEyeballs.httpHappyEyeballsAgent);
- const requestOptions = {
- ...options,
- agent
- };
- const request = requestConstructor(url, requestOptions, async response => {
- const notifyRequestFinished = body => {
- const requestFinishedEvent = {
- requestEvent,
- httpVersion: response.httpVersion,
- statusCode: response.statusCode || 0,
- statusMessage: response.statusMessage || '',
- headers: response.headers,
- rawHeaders: response.rawHeaders,
- cookies,
- body
- };
- this.emit(APIRequestContext.Events.RequestFinished, requestFinishedEvent);
- };
- progress.log(`← ${response.statusCode} ${response.statusMessage}`);
- for (const [name, value] of Object.entries(response.headers)) progress.log(` ${name}: ${value}`);
- const cookies = this._parseSetCookieHeader(response.url || url.toString(), response.headers['set-cookie']);
- if (cookies.length) {
- try {
- await this._addCookies(cookies);
- } catch (e) {
- // Cookie value is limited by 4096 characters in the browsers. If setCookies failed,
- // we try setting each cookie individually just in case only some of them are bad.
- await Promise.all(cookies.map(c => this._addCookies([c]).catch(() => {})));
- }
- }
- if (redirectStatus.includes(response.statusCode) && options.maxRedirects >= 0) {
- if (!options.maxRedirects) {
- reject(new Error('Max redirect count exceeded'));
- request.destroy();
- return;
- }
- const headers = {
- ...options.headers
- };
- removeHeader(headers, `cookie`);
- // HTTP-redirect fetch step 13 (https://fetch.spec.whatwg.org/#http-redirect-fetch)
- const status = response.statusCode;
- let method = options.method;
- if ((status === 301 || status === 302) && method === 'POST' || status === 303 && !['GET', 'HEAD'].includes(method)) {
- method = 'GET';
- postData = undefined;
- removeHeader(headers, `content-encoding`);
- removeHeader(headers, `content-language`);
- removeHeader(headers, `content-length`);
- removeHeader(headers, `content-location`);
- removeHeader(headers, `content-type`);
- }
- const redirectOptions = {
- method,
- headers,
- agent: options.agent,
- maxRedirects: options.maxRedirects - 1,
- timeout: options.timeout,
- deadline: options.deadline,
- __testHookLookup: options.__testHookLookup
- };
- // rejectUnauthorized = undefined is treated as true in node 12.
- if (options.rejectUnauthorized === false) redirectOptions.rejectUnauthorized = false;
- // HTTP-redirect fetch step 4: If locationURL is null, then return response.
- if (response.headers.location) {
- let locationURL;
- try {
- locationURL = new URL(response.headers.location, url);
- } catch (error) {
- reject(new Error(`uri requested responds with an invalid redirect URL: ${response.headers.location}`));
- request.destroy();
- return;
- }
- if (headers['host']) headers['host'] = locationURL.host;
- notifyRequestFinished();
- fulfill(this._sendRequest(progress, locationURL, redirectOptions, postData));
- request.destroy();
- return;
- }
- }
- if (response.statusCode === 401 && !getHeader(options.headers, 'authorization')) {
- const auth = response.headers['www-authenticate'];
- const credentials = this._getHttpCredentials(url);
- if (auth !== null && auth !== void 0 && auth.trim().startsWith('Basic') && credentials) {
- const {
- username,
- password
- } = credentials;
- const encoded = Buffer.from(`${username || ''}:${password || ''}`).toString('base64');
- setHeader(options.headers, 'authorization', `Basic ${encoded}`);
- notifyRequestFinished();
- fulfill(this._sendRequest(progress, url, options, postData));
- request.destroy();
- return;
- }
- }
- response.on('aborted', () => reject(new Error('aborted')));
- const chunks = [];
- const notifyBodyFinished = () => {
- const body = Buffer.concat(chunks);
- notifyRequestFinished(body);
- fulfill({
- url: response.url || url.toString(),
- status: response.statusCode || 0,
- statusText: response.statusMessage || '',
- headers: toHeadersArray(response.rawHeaders),
- body
- });
- };
- let body = response;
- let transform;
- const encoding = response.headers['content-encoding'];
- if (encoding === 'gzip' || encoding === 'x-gzip') {
- transform = _zlib.default.createGunzip({
- flush: _zlib.default.constants.Z_SYNC_FLUSH,
- finishFlush: _zlib.default.constants.Z_SYNC_FLUSH
- });
- } else if (encoding === 'br') {
- transform = _zlib.default.createBrotliDecompress();
- } else if (encoding === 'deflate') {
- transform = _zlib.default.createInflate();
- }
- if (transform) {
- // Brotli and deflate decompressors throw if the input stream is empty.
- const emptyStreamTransform = new SafeEmptyStreamTransform(notifyBodyFinished);
- body = (0, _stream.pipeline)(response, emptyStreamTransform, transform, e => {
- if (e) reject(new Error(`failed to decompress '${encoding}' encoding: ${e.message}`));
- });
- body.on('error', e => reject(new Error(`failed to decompress '${encoding}' encoding: ${e}`)));
- } else {
- body.on('error', reject);
- }
- body.on('data', chunk => chunks.push(chunk));
- body.on('end', notifyBodyFinished);
- });
- request.on('error', reject);
- const disposeListener = () => {
- reject(new Error('Request context disposed.'));
- request.destroy();
- };
- this.on(APIRequestContext.Events.Dispose, disposeListener);
- request.on('close', () => this.off(APIRequestContext.Events.Dispose, disposeListener));
- progress.log(`→ ${options.method} ${url.toString()}`);
- if (options.headers) {
- for (const [name, value] of Object.entries(options.headers)) progress.log(` ${name}: ${value}`);
- }
- if (options.deadline) {
- const rejectOnTimeout = () => {
- reject(new Error(`Request timed out after ${options.timeout}ms`));
- request.destroy();
- };
- const remaining = options.deadline - (0, _utils.monotonicTime)();
- if (remaining <= 0) {
- rejectOnTimeout();
- return;
- }
- request.setTimeout(remaining, rejectOnTimeout);
- }
- if (postData) request.write(postData);
- request.end();
- });
- }
- _getHttpCredentials(url) {
- var _this$_defaultOptions, _this$_defaultOptions2, _this$_defaultOptions3;
- if (!((_this$_defaultOptions = this._defaultOptions().httpCredentials) !== null && _this$_defaultOptions !== void 0 && _this$_defaultOptions.origin) || url.origin.toLowerCase() === ((_this$_defaultOptions2 = this._defaultOptions().httpCredentials) === null || _this$_defaultOptions2 === void 0 ? void 0 : (_this$_defaultOptions3 = _this$_defaultOptions2.origin) === null || _this$_defaultOptions3 === void 0 ? void 0 : _this$_defaultOptions3.toLowerCase())) return this._defaultOptions().httpCredentials;
- return undefined;
- }
- }
- exports.APIRequestContext = APIRequestContext;
- APIRequestContext.Events = {
- Dispose: 'dispose',
- Request: 'request',
- RequestFinished: 'requestfinished'
- };
- APIRequestContext.allInstances = new Set();
- class SafeEmptyStreamTransform extends _stream.Transform {
- constructor(onEmptyStreamCallback) {
- super();
- this._receivedSomeData = false;
- this._onEmptyStreamCallback = void 0;
- this._onEmptyStreamCallback = onEmptyStreamCallback;
- }
- _transform(chunk, encoding, callback) {
- this._receivedSomeData = true;
- callback(null, chunk);
- }
- _flush(callback) {
- if (this._receivedSomeData) callback(null);else this._onEmptyStreamCallback();
- }
- }
- class BrowserContextAPIRequestContext extends APIRequestContext {
- constructor(context) {
- super(context);
- this._context = void 0;
- this._context = context;
- context.once(_browserContext.BrowserContext.Events.Close, () => this._disposeImpl());
- }
- tracing() {
- return this._context.tracing;
- }
- async dispose() {
- this.fetchResponses.clear();
- }
- _defaultOptions() {
- return {
- userAgent: this._context._options.userAgent || this._context._browser.userAgent(),
- extraHTTPHeaders: this._context._options.extraHTTPHeaders,
- httpCredentials: this._context._options.httpCredentials,
- proxy: this._context._options.proxy || this._context._browser.options.proxy,
- timeoutSettings: this._context._timeoutSettings,
- ignoreHTTPSErrors: this._context._options.ignoreHTTPSErrors,
- baseURL: this._context._options.baseURL
- };
- }
- async _addCookies(cookies) {
- await this._context.addCookies(cookies);
- }
- async _cookies(url) {
- return await this._context.cookies(url.toString());
- }
- async storageState() {
- return this._context.storageState();
- }
- }
- exports.BrowserContextAPIRequestContext = BrowserContextAPIRequestContext;
- class GlobalAPIRequestContext extends APIRequestContext {
- constructor(playwright, options) {
- super(playwright);
- this._cookieStore = new _cookieStore.CookieStore();
- this._options = void 0;
- this._origins = void 0;
- this._tracing = void 0;
- this.attribution.context = this;
- const timeoutSettings = new _timeoutSettings.TimeoutSettings();
- if (options.timeout !== undefined) timeoutSettings.setDefaultTimeout(options.timeout);
- const proxy = options.proxy;
- if (proxy !== null && proxy !== void 0 && proxy.server) {
- let url = proxy === null || proxy === void 0 ? void 0 : proxy.server.trim();
- if (!/^\w+:\/\//.test(url)) url = 'http://' + url;
- proxy.server = url;
- }
- if (options.storageState) {
- this._origins = options.storageState.origins;
- this._cookieStore.addCookies(options.storageState.cookies || []);
- }
- this._options = {
- baseURL: options.baseURL,
- userAgent: options.userAgent || (0, _userAgent.getUserAgent)(),
- extraHTTPHeaders: options.extraHTTPHeaders,
- ignoreHTTPSErrors: !!options.ignoreHTTPSErrors,
- httpCredentials: options.httpCredentials,
- proxy,
- timeoutSettings
- };
- this._tracing = new _tracing.Tracing(this, options.tracesDir);
- }
- tracing() {
- return this._tracing;
- }
- async dispose() {
- await this._tracing.flush();
- await this._tracing.deleteTmpTracesDir();
- this._disposeImpl();
- }
- _defaultOptions() {
- return this._options;
- }
- async _addCookies(cookies) {
- this._cookieStore.addCookies(cookies);
- }
- async _cookies(url) {
- return this._cookieStore.cookies(url);
- }
- async storageState() {
- return {
- cookies: this._cookieStore.allCookies(),
- origins: this._origins || []
- };
- }
- }
- exports.GlobalAPIRequestContext = GlobalAPIRequestContext;
- function toHeadersArray(rawHeaders) {
- const result = [];
- for (let i = 0; i < rawHeaders.length; i += 2) result.push({
- name: rawHeaders[i],
- value: rawHeaders[i + 1]
- });
- return result;
- }
- const redirectStatus = [301, 302, 303, 307, 308];
- function parseCookie(header) {
- const pairs = header.split(';').filter(s => s.trim().length > 0).map(p => {
- let key = '';
- let value = '';
- const separatorPos = p.indexOf('=');
- if (separatorPos === -1) {
- // If only a key is specified, the value is left undefined.
- key = p.trim();
- } else {
- // Otherwise we assume that the key is the element before the first `=`
- key = p.slice(0, separatorPos).trim();
- // And the value is the rest of the string.
- value = p.slice(separatorPos + 1).trim();
- }
- return [key, value];
- });
- if (!pairs.length) return null;
- const [name, value] = pairs[0];
- const cookie = {
- name,
- value,
- domain: '',
- path: '',
- expires: -1,
- httpOnly: false,
- secure: false,
- // From https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
- // The cookie-sending behavior if SameSite is not specified is SameSite=Lax.
- sameSite: 'Lax'
- };
- for (let i = 1; i < pairs.length; i++) {
- const [name, value] = pairs[i];
- switch (name.toLowerCase()) {
- case 'expires':
- const expiresMs = +new Date(value);
- // https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.1
- if (isFinite(expiresMs)) {
- if (expiresMs <= 0) cookie.expires = 0;else cookie.expires = Math.min(expiresMs / 1000, _network.kMaxCookieExpiresDateInSeconds);
- }
- break;
- case 'max-age':
- const maxAgeSec = parseInt(value, 10);
- if (isFinite(maxAgeSec)) {
- // From https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.2
- // If delta-seconds is less than or equal to zero (0), let expiry-time
- // be the earliest representable date and time.
- if (maxAgeSec <= 0) cookie.expires = 0;else cookie.expires = Math.min(Date.now() / 1000 + maxAgeSec, _network.kMaxCookieExpiresDateInSeconds);
- }
- break;
- case 'domain':
- cookie.domain = value.toLocaleLowerCase() || '';
- if (cookie.domain && !cookie.domain.startsWith('.') && cookie.domain.includes('.')) cookie.domain = '.' + cookie.domain;
- break;
- case 'path':
- cookie.path = value || '';
- break;
- case 'secure':
- cookie.secure = true;
- break;
- case 'httponly':
- cookie.httpOnly = true;
- break;
- case 'samesite':
- switch (value.toLowerCase()) {
- case 'none':
- cookie.sameSite = 'None';
- break;
- case 'lax':
- cookie.sameSite = 'Lax';
- break;
- case 'strict':
- cookie.sameSite = 'Strict';
- break;
- }
- break;
- }
- }
- return cookie;
- }
- function serializePostData(params, headers) {
- (0, _utils.assert)((params.postData ? 1 : 0) + (params.jsonData ? 1 : 0) + (params.formData ? 1 : 0) + (params.multipartData ? 1 : 0) <= 1, `Only one of 'data', 'form' or 'multipart' can be specified`);
- if (params.jsonData !== undefined) {
- setHeader(headers, 'content-type', 'application/json', true);
- return Buffer.from(params.jsonData, 'utf8');
- } else if (params.formData) {
- const searchParams = new URLSearchParams();
- for (const {
- name,
- value
- } of params.formData) searchParams.append(name, value);
- setHeader(headers, 'content-type', 'application/x-www-form-urlencoded', true);
- return Buffer.from(searchParams.toString(), 'utf8');
- } else if (params.multipartData) {
- const formData = new _formData.MultipartFormData();
- for (const field of params.multipartData) {
- if (field.file) formData.addFileField(field.name, field.file);else if (field.value) formData.addField(field.name, field.value);
- }
- setHeader(headers, 'content-type', formData.contentTypeHeader(), true);
- return formData.finish();
- } else if (params.postData !== undefined) {
- setHeader(headers, 'content-type', 'application/octet-stream', true);
- return params.postData;
- }
- return undefined;
- }
- function setHeader(headers, name, value, keepExisting = false) {
- const existing = Object.entries(headers).find(pair => pair[0].toLowerCase() === name.toLowerCase());
- if (!existing) headers[name] = value;else if (!keepExisting) headers[existing[0]] = value;
- }
- function getHeader(headers, name) {
- const existing = Object.entries(headers).find(pair => pair[0].toLowerCase() === name.toLowerCase());
- return existing ? existing[1] : undefined;
- }
- function removeHeader(headers, name) {
- delete headers[name];
- }
- function shouldBypassProxy(url, bypass) {
- if (!bypass) return false;
- const domains = bypass.split(',').map(s => {
- s = s.trim();
- if (!s.startsWith('.')) s = '.' + s;
- return s;
- });
- const domain = '.' + url.hostname;
- return domains.some(d => domain.endsWith(d));
- }
|