Best JavaScript code snippet using playwright-internal
crNetworkManager.js
Source:crNetworkManager.js
1"use strict";2Object.defineProperty(exports, "__esModule", {3 value: true4});5exports.CRNetworkManager = void 0;6var _helper = require("../helper");7var _eventsHelper = require("../../utils/eventsHelper");8var network = _interopRequireWildcard(require("../network"));9var _utils = require("../../utils/utils");10function _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); }11function _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; }12/**13 * Copyright 2017 Google Inc. All rights reserved.14 * Modifications copyright (c) Microsoft Corporation.15 *16 * Licensed under the Apache License, Version 2.0 (the "License");17 * you may not use this file except in compliance with the License.18 * You may obtain a copy of the License at19 *20 * http://www.apache.org/licenses/LICENSE-2.021 *22 * Unless required by applicable law or agreed to in writing, software23 * distributed under the License is distributed on an "AS IS" BASIS,24 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.25 * See the License for the specific language governing permissions and26 * limitations under the License.27 */28class CRNetworkManager {29 constructor(client, page, parentManager) {30 this._client = void 0;31 this._page = void 0;32 this._parentManager = void 0;33 this._requestIdToRequest = new Map();34 this._requestIdToRequestWillBeSentEvent = new Map();35 this._credentials = null;36 this._attemptedAuthentications = new Set();37 this._userRequestInterceptionEnabled = false;38 this._protocolRequestInterceptionEnabled = false;39 this._requestIdToRequestPausedEvent = new Map();40 this._eventListeners = void 0;41 this._responseExtraInfoTracker = new ResponseExtraInfoTracker();42 this._client = client;43 this._page = page;44 this._parentManager = parentManager;45 this._eventListeners = this.instrumentNetworkEvents(client);46 }47 instrumentNetworkEvents(session, workerFrame) {48 return [_eventsHelper.eventsHelper.addEventListener(session, 'Fetch.requestPaused', this._onRequestPaused.bind(this, workerFrame)), _eventsHelper.eventsHelper.addEventListener(session, 'Fetch.authRequired', this._onAuthRequired.bind(this)), _eventsHelper.eventsHelper.addEventListener(session, 'Network.requestWillBeSent', this._onRequestWillBeSent.bind(this, workerFrame)), _eventsHelper.eventsHelper.addEventListener(session, 'Network.requestWillBeSentExtraInfo', this._onRequestWillBeSentExtraInfo.bind(this)), _eventsHelper.eventsHelper.addEventListener(session, 'Network.responseReceived', this._onResponseReceived.bind(this)), _eventsHelper.eventsHelper.addEventListener(session, 'Network.responseReceivedExtraInfo', this._onResponseReceivedExtraInfo.bind(this)), _eventsHelper.eventsHelper.addEventListener(session, 'Network.loadingFinished', this._onLoadingFinished.bind(this)), _eventsHelper.eventsHelper.addEventListener(session, 'Network.loadingFailed', this._onLoadingFailed.bind(this, workerFrame)), _eventsHelper.eventsHelper.addEventListener(session, 'Network.webSocketCreated', e => this._page._frameManager.onWebSocketCreated(e.requestId, e.url)), _eventsHelper.eventsHelper.addEventListener(session, 'Network.webSocketWillSendHandshakeRequest', e => this._page._frameManager.onWebSocketRequest(e.requestId)), _eventsHelper.eventsHelper.addEventListener(session, 'Network.webSocketHandshakeResponseReceived', e => this._page._frameManager.onWebSocketResponse(e.requestId, e.response.status, e.response.statusText)), _eventsHelper.eventsHelper.addEventListener(session, 'Network.webSocketFrameSent', e => e.response.payloadData && this._page._frameManager.onWebSocketFrameSent(e.requestId, e.response.opcode, e.response.payloadData)), _eventsHelper.eventsHelper.addEventListener(session, 'Network.webSocketFrameReceived', e => e.response.payloadData && this._page._frameManager.webSocketFrameReceived(e.requestId, e.response.opcode, e.response.payloadData)), _eventsHelper.eventsHelper.addEventListener(session, 'Network.webSocketClosed', e => this._page._frameManager.webSocketClosed(e.requestId)), _eventsHelper.eventsHelper.addEventListener(session, 'Network.webSocketFrameError', e => this._page._frameManager.webSocketError(e.requestId, e.errorMessage))];49 }50 async initialize() {51 await this._client.send('Network.enable');52 }53 dispose() {54 _eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);55 }56 async authenticate(credentials) {57 this._credentials = credentials;58 await this._updateProtocolRequestInterception();59 }60 async setOffline(offline) {61 await this._client.send('Network.emulateNetworkConditions', {62 offline,63 // values of 0 remove any active throttling. crbug.com/456324#c964 latency: 0,65 downloadThroughput: -1,66 uploadThroughput: -167 });68 }69 async setRequestInterception(value) {70 this._userRequestInterceptionEnabled = value;71 await this._updateProtocolRequestInterception();72 }73 async _updateProtocolRequestInterception() {74 const enabled = this._userRequestInterceptionEnabled || !!this._credentials;75 if (enabled === this._protocolRequestInterceptionEnabled) return;76 this._protocolRequestInterceptionEnabled = enabled;77 if (enabled) {78 await Promise.all([this._client.send('Network.setCacheDisabled', {79 cacheDisabled: true80 }), this._client.send('Fetch.enable', {81 handleAuthRequests: true,82 patterns: [{83 urlPattern: '*',84 requestStage: 'Request'85 }]86 })]);87 } else {88 await Promise.all([this._client.send('Network.setCacheDisabled', {89 cacheDisabled: false90 }), this._client.send('Fetch.disable')]);91 }92 }93 _onRequestWillBeSent(workerFrame, event) {94 this._responseExtraInfoTracker.requestWillBeSent(event); // Request interception doesn't happen for data URLs with Network Service.95 if (this._protocolRequestInterceptionEnabled && !event.request.url.startsWith('data:')) {96 const requestId = event.requestId;97 const requestPausedEvent = this._requestIdToRequestPausedEvent.get(requestId);98 if (requestPausedEvent) {99 this._onRequest(workerFrame, event, requestPausedEvent);100 this._requestIdToRequestPausedEvent.delete(requestId);101 } else {102 this._requestIdToRequestWillBeSentEvent.set(event.requestId, event);103 }104 } else {105 this._onRequest(workerFrame, event, null);106 }107 }108 _onRequestWillBeSentExtraInfo(event) {109 this._responseExtraInfoTracker.requestWillBeSentExtraInfo(event);110 }111 _onAuthRequired(event) {112 let response = 'Default';113 if (this._attemptedAuthentications.has(event.requestId)) {114 response = 'CancelAuth';115 } else if (this._credentials) {116 response = 'ProvideCredentials';117 this._attemptedAuthentications.add(event.requestId);118 }119 const {120 username,121 password122 } = this._credentials || {123 username: undefined,124 password: undefined125 };126 this._client._sendMayFail('Fetch.continueWithAuth', {127 requestId: event.requestId,128 authChallengeResponse: {129 response,130 username,131 password132 }133 });134 }135 _onRequestPaused(workerFrame, event) {136 if (!event.responseStatusCode && !event.responseErrorReason) {137 // Request intercepted, deliver signal to the tracker.138 const request = this._requestIdToRequest.get(event.networkId);139 if (request) this._responseExtraInfoTracker.requestPaused(request.request, event);140 }141 if (!event.networkId) {142 // Fetch without networkId means that request was not recongnized by inspector, and143 // it will never receive Network.requestWillBeSent. Most likely, this is an internal request144 // that we can safely fail.145 this._client._sendMayFail('Fetch.failRequest', {146 requestId: event.requestId,147 errorReason: 'Aborted'148 });149 return;150 }151 if (event.request.url.startsWith('data:')) return;152 const requestId = event.networkId;153 const requestWillBeSentEvent = this._requestIdToRequestWillBeSentEvent.get(requestId);154 if (requestWillBeSentEvent) {155 this._onRequest(workerFrame, requestWillBeSentEvent, event);156 this._requestIdToRequestWillBeSentEvent.delete(requestId);157 } else {158 this._requestIdToRequestPausedEvent.set(requestId, event);159 }160 }161 _onRequest(workerFrame, requestWillBeSentEvent, requestPausedEvent) {162 if (requestWillBeSentEvent.request.url.startsWith('data:')) return;163 let redirectedFrom = null;164 if (requestWillBeSentEvent.redirectResponse) {165 const request = this._requestIdToRequest.get(requestWillBeSentEvent.requestId); // If we connect late to the target, we could have missed the requestWillBeSent event.166 if (request) {167 this._handleRequestRedirect(request, requestWillBeSentEvent.redirectResponse, requestWillBeSentEvent.timestamp);168 redirectedFrom = request;169 }170 }171 let frame = requestWillBeSentEvent.frameId ? this._page._frameManager.frame(requestWillBeSentEvent.frameId) : workerFrame; // Requests from workers lack frameId, because we receive Network.requestWillBeSent172 // on the worker target. However, we receive Fetch.requestPaused on the page target,173 // and lack workerFrame there. Luckily, Fetch.requestPaused provides a frameId.174 if (!frame && requestPausedEvent && requestPausedEvent.frameId) frame = this._page._frameManager.frame(requestPausedEvent.frameId); // Check if it's main resource request interception (targetId === main frame id).175 if (!frame && requestWillBeSentEvent.frameId === this._page._delegate._targetId) {176 // Main resource request for the page is being intercepted so the Frame is not created177 // yet. Precreate it here for the purposes of request interception. It will be updated178 // later as soon as the request continues and we receive frame tree from the page.179 frame = this._page._frameManager.frameAttached(requestWillBeSentEvent.frameId, null);180 } // CORS options request is generated by the network stack. If interception is enabled,181 // we accept all CORS options, assuming that this was intended when setting route.182 //183 // Note: it would be better to match the URL against interception patterns, but184 // that information is only available to the client. Perhaps we can just route to the client?185 if (requestPausedEvent && requestPausedEvent.request.method === 'OPTIONS' && this._page._needsRequestInterception()) {186 const requestHeaders = requestPausedEvent.request.headers;187 const responseHeaders = [{188 name: 'Access-Control-Allow-Origin',189 value: requestHeaders['Origin'] || '*'190 }, {191 name: 'Access-Control-Allow-Methods',192 value: requestHeaders['Access-Control-Request-Method'] || 'GET, POST, OPTIONS, DELETE'193 }, {194 name: 'Access-Control-Allow-Credentials',195 value: 'true'196 }];197 if (requestHeaders['Access-Control-Request-Headers']) responseHeaders.push({198 name: 'Access-Control-Allow-Headers',199 value: requestHeaders['Access-Control-Request-Headers']200 });201 this._client._sendMayFail('Fetch.fulfillRequest', {202 requestId: requestPausedEvent.requestId,203 responseCode: 204,204 responsePhrase: network.STATUS_TEXTS['204'],205 responseHeaders,206 body: ''207 });208 return;209 }210 if (!frame) {211 if (requestPausedEvent) this._client._sendMayFail('Fetch.continueRequest', {212 requestId: requestPausedEvent.requestId213 });214 return;215 }216 let route = null;217 if (requestPausedEvent) {218 // We do not support intercepting redirects.219 if (redirectedFrom || !this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) this._client._sendMayFail('Fetch.continueRequest', {220 requestId: requestPausedEvent.requestId221 });else route = new RouteImpl(this._client, requestPausedEvent.requestId);222 }223 const isNavigationRequest = requestWillBeSentEvent.requestId === requestWillBeSentEvent.loaderId && requestWillBeSentEvent.type === 'Document';224 const documentId = isNavigationRequest ? requestWillBeSentEvent.loaderId : undefined;225 const request = new InterceptableRequest({226 frame,227 documentId,228 route,229 requestWillBeSentEvent,230 requestPausedEvent,231 redirectedFrom232 });233 this._requestIdToRequest.set(requestWillBeSentEvent.requestId, request);234 this._page._frameManager.requestStarted(request.request, route || undefined);235 }236 _createResponse(request, responsePayload) {237 var _responsePayload$secu, _responsePayload$secu2, _responsePayload$secu3, _responsePayload$secu4, _responsePayload$secu5;238 const getResponseBody = async () => {239 const response = await this._client.send('Network.getResponseBody', {240 requestId: request._requestId241 });242 return Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8');243 };244 const timingPayload = responsePayload.timing;245 let timing;246 if (timingPayload) {247 timing = {248 startTime: (timingPayload.requestTime - request._timestamp + request._wallTime) * 1000,249 domainLookupStart: timingPayload.dnsStart,250 domainLookupEnd: timingPayload.dnsEnd,251 connectStart: timingPayload.connectStart,252 secureConnectionStart: timingPayload.sslStart,253 connectEnd: timingPayload.connectEnd,254 requestStart: timingPayload.sendStart,255 responseStart: timingPayload.receiveHeadersEnd256 };257 } else {258 timing = {259 startTime: request._wallTime * 1000,260 domainLookupStart: -1,261 domainLookupEnd: -1,262 connectStart: -1,263 secureConnectionStart: -1,264 connectEnd: -1,265 requestStart: -1,266 responseStart: -1267 };268 }269 const response = new network.Response(request.request, responsePayload.status, responsePayload.statusText, (0, _utils.headersObjectToArray)(responsePayload.headers), timing, getResponseBody, responsePayload.protocol);270 if (responsePayload !== null && responsePayload !== void 0 && responsePayload.remoteIPAddress && typeof (responsePayload === null || responsePayload === void 0 ? void 0 : responsePayload.remotePort) === 'number') {271 response._serverAddrFinished({272 ipAddress: responsePayload.remoteIPAddress,273 port: responsePayload.remotePort274 });275 } else {276 response._serverAddrFinished();277 }278 response._securityDetailsFinished({279 protocol: responsePayload === null || responsePayload === void 0 ? void 0 : (_responsePayload$secu = responsePayload.securityDetails) === null || _responsePayload$secu === void 0 ? void 0 : _responsePayload$secu.protocol,280 subjectName: responsePayload === null || responsePayload === void 0 ? void 0 : (_responsePayload$secu2 = responsePayload.securityDetails) === null || _responsePayload$secu2 === void 0 ? void 0 : _responsePayload$secu2.subjectName,281 issuer: responsePayload === null || responsePayload === void 0 ? void 0 : (_responsePayload$secu3 = responsePayload.securityDetails) === null || _responsePayload$secu3 === void 0 ? void 0 : _responsePayload$secu3.issuer,282 validFrom: responsePayload === null || responsePayload === void 0 ? void 0 : (_responsePayload$secu4 = responsePayload.securityDetails) === null || _responsePayload$secu4 === void 0 ? void 0 : _responsePayload$secu4.validFrom,283 validTo: responsePayload === null || responsePayload === void 0 ? void 0 : (_responsePayload$secu5 = responsePayload.securityDetails) === null || _responsePayload$secu5 === void 0 ? void 0 : _responsePayload$secu5.validTo284 });285 this._responseExtraInfoTracker.processResponse(request._requestId, response, request.wasFulfilled());286 return response;287 }288 _handleRequestRedirect(request, responsePayload, timestamp) {289 const response = this._createResponse(request, responsePayload);290 response._requestFinished((timestamp - request._timestamp) * 1000);291 this._requestIdToRequest.delete(request._requestId);292 if (request._interceptionId) this._attemptedAuthentications.delete(request._interceptionId);293 this._page._frameManager.requestReceivedResponse(response);294 this._page._frameManager.reportRequestFinished(request.request, response);295 }296 _onResponseReceivedExtraInfo(event) {297 this._responseExtraInfoTracker.responseReceivedExtraInfo(event);298 }299 _onResponseReceived(event) {300 this._responseExtraInfoTracker.responseReceived(event);301 const request = this._requestIdToRequest.get(event.requestId); // FileUpload sends a response without a matching request.302 if (!request) return;303 const response = this._createResponse(request, event.response);304 this._page._frameManager.requestReceivedResponse(response);305 }306 _onLoadingFinished(event) {307 this._responseExtraInfoTracker.loadingFinished(event);308 let request = this._requestIdToRequest.get(event.requestId);309 if (!request) request = this._maybeAdoptMainRequest(event.requestId); // For certain requestIds we never receive requestWillBeSent event.310 // @see https://crbug.com/750469311 if (!request) return; // Under certain conditions we never get the Network.responseReceived312 // event from protocol. @see https://crbug.com/883475313 const response = request.request._existingResponse();314 if (response) {315 request.request.responseSize.transferSize = event.encodedDataLength;316 request.request.responseSize.encodedBodySize = event.encodedDataLength - request.request.responseSize.responseHeadersSize;317 response._requestFinished(_helper.helper.secondsToRoundishMillis(event.timestamp - request._timestamp));318 }319 this._requestIdToRequest.delete(request._requestId);320 if (request._interceptionId) this._attemptedAuthentications.delete(request._interceptionId);321 this._page._frameManager.reportRequestFinished(request.request, response);322 }323 _onLoadingFailed(workerFrame, event) {324 this._responseExtraInfoTracker.loadingFailed(event);325 let request = this._requestIdToRequest.get(event.requestId);326 if (!request) request = this._maybeAdoptMainRequest(event.requestId);327 if (!request) {328 const requestWillBeSentEvent = this._requestIdToRequestWillBeSentEvent.get(event.requestId);329 if (requestWillBeSentEvent) {330 // This is a case where request has failed before we had a chance to intercept it.331 // We stop waiting for Fetch.requestPaused (it might never come), and dispatch request event332 // right away, followed by requestfailed event.333 this._requestIdToRequestWillBeSentEvent.delete(event.requestId);334 this._onRequest(workerFrame, requestWillBeSentEvent, null);335 request = this._requestIdToRequest.get(event.requestId);336 }337 } // For certain requestIds we never receive requestWillBeSent event.338 // @see https://crbug.com/750469339 if (!request) return;340 const response = request.request._existingResponse();341 if (response) response._requestFinished(_helper.helper.secondsToRoundishMillis(event.timestamp - request._timestamp));342 this._requestIdToRequest.delete(request._requestId);343 if (request._interceptionId) this._attemptedAuthentications.delete(request._interceptionId);344 request.request._setFailureText(event.errorText);345 this._page._frameManager.requestFailed(request.request, !!event.canceled);346 }347 _maybeAdoptMainRequest(requestId) {348 // OOPIF has a main request that starts in the parent session but finishes in the child session.349 if (!this._parentManager) return;350 const request = this._parentManager._requestIdToRequest.get(requestId); // Main requests have matching loaderId and requestId.351 if (!request || request._documentId !== requestId) return;352 this._requestIdToRequest.set(requestId, request);353 this._parentManager._requestIdToRequest.delete(requestId);354 if (request._interceptionId && this._parentManager._attemptedAuthentications.has(request._interceptionId)) {355 this._parentManager._attemptedAuthentications.delete(request._interceptionId);356 this._attemptedAuthentications.add(request._interceptionId);357 }358 return request;359 }360}361exports.CRNetworkManager = CRNetworkManager;362class InterceptableRequest {363 constructor(options) {364 this.request = void 0;365 this._requestId = void 0;366 this._interceptionId = void 0;367 this._documentId = void 0;368 this._timestamp = void 0;369 this._wallTime = void 0;370 this._route = void 0;371 this._redirectedFrom = void 0;372 const {373 frame,374 documentId,375 route,376 requestWillBeSentEvent,377 requestPausedEvent,378 redirectedFrom379 } = options;380 this._timestamp = requestWillBeSentEvent.timestamp;381 this._wallTime = requestWillBeSentEvent.wallTime;382 this._requestId = requestWillBeSentEvent.requestId;383 this._interceptionId = requestPausedEvent && requestPausedEvent.requestId;384 this._documentId = documentId;385 this._route = route;386 this._redirectedFrom = redirectedFrom;387 const {388 headers,389 method,390 url,391 postDataEntries = null392 } = requestPausedEvent ? requestPausedEvent.request : requestWillBeSentEvent.request;393 const type = (requestWillBeSentEvent.type || '').toLowerCase();394 let postDataBuffer = null;395 if (postDataEntries && postDataEntries.length && postDataEntries[0].bytes) postDataBuffer = Buffer.from(postDataEntries[0].bytes, 'base64');396 this.request = new network.Request(frame, (redirectedFrom === null || redirectedFrom === void 0 ? void 0 : redirectedFrom.request) || null, documentId, url, type, method, postDataBuffer, (0, _utils.headersObjectToArray)(headers));397 }398 _routeForRedirectChain() {399 let request = this;400 while (request._redirectedFrom) request = request._redirectedFrom;401 return request._route;402 }403 wasFulfilled() {404 var _this$_routeForRedire;405 return ((_this$_routeForRedire = this._routeForRedirectChain()) === null || _this$_routeForRedire === void 0 ? void 0 : _this$_routeForRedire._wasFulfilled) || false;406 }407}408class RouteImpl {409 constructor(client, interceptionId) {410 this._client = void 0;411 this._interceptionId = void 0;412 this._wasFulfilled = false;413 this._client = client;414 this._interceptionId = interceptionId;415 }416 async continue(request, overrides) {417 // In certain cases, protocol will return error if the request was already canceled418 // or the page was closed. We should tolerate these errors.419 await this._client._sendMayFail('Fetch.continueRequest', {420 requestId: this._interceptionId,421 url: overrides.url,422 headers: overrides.headers,423 method: overrides.method,424 postData: overrides.postData ? overrides.postData.toString('base64') : undefined425 });426 }427 async fulfill(response) {428 this._wasFulfilled = true;429 const body = response.isBase64 ? response.body : Buffer.from(response.body).toString('base64');430 const responseHeaders = splitSetCookieHeader(response.headers); // In certain cases, protocol will return error if the request was already canceled431 // or the page was closed. We should tolerate these errors.432 await this._client._sendMayFail('Fetch.fulfillRequest', {433 requestId: this._interceptionId,434 responseCode: response.status,435 responsePhrase: network.STATUS_TEXTS[String(response.status)],436 responseHeaders,437 body438 });439 }440 async abort(errorCode = 'failed') {441 const errorReason = errorReasons[errorCode];442 (0, _utils.assert)(errorReason, 'Unknown error code: ' + errorCode); // In certain cases, protocol will return error if the request was already canceled443 // or the page was closed. We should tolerate these errors.444 await this._client._sendMayFail('Fetch.failRequest', {445 requestId: this._interceptionId,446 errorReason447 });448 }449}450function splitSetCookieHeader(headers) {451 const index = headers.findIndex(({452 name453 }) => name.toLowerCase() === 'set-cookie');454 if (index === -1) return headers;455 const header = headers[index];456 const values = header.value.split('\n');457 if (values.length === 1) return headers;458 const result = headers.slice();459 result.splice(index, 1, ...values.map(value => ({460 name: header.name,461 value462 })));463 return result;464}465const errorReasons = {466 'aborted': 'Aborted',467 'accessdenied': 'AccessDenied',468 'addressunreachable': 'AddressUnreachable',469 'blockedbyclient': 'BlockedByClient',470 'blockedbyresponse': 'BlockedByResponse',471 'connectionaborted': 'ConnectionAborted',472 'connectionclosed': 'ConnectionClosed',473 'connectionfailed': 'ConnectionFailed',474 'connectionrefused': 'ConnectionRefused',475 'connectionreset': 'ConnectionReset',476 'internetdisconnected': 'InternetDisconnected',477 'namenotresolved': 'NameNotResolved',478 'timedout': 'TimedOut',479 'failed': 'Failed'480};481// This class aligns responses with response headers from extra info:482// - Network.requestWillBeSent, Network.responseReceived, Network.loadingFinished/loadingFailed are483// dispatched using one channel.484// - Network.requestWillBeSentExtraInfo and Network.responseReceivedExtraInfo are dispatches on485// another channel. Those channels are not associated, so events come in random order.486//487// This class will associate responses with the new headers. These extra info headers will become488// available to client reliably upon requestfinished event only. It consumes CDP489// signals on one end and processResponse(network.Response) signals on the other hands. It then makes490// sure that responses have all the extra headers in place by the time request finises.491//492// The shape of the instrumentation API is deliberately following the CDP, so that it493// what clear what is called when and what this means to the tracker without extra494// documentation.495class ResponseExtraInfoTracker {496 constructor() {497 this._requests = new Map();498 }499 requestWillBeSent(event) {500 const info = this._requests.get(event.requestId);501 if (info && event.redirectResponse) this._innerResponseReceived(info, event.redirectResponse);else this._getOrCreateEntry(event.requestId);502 }503 requestWillBeSentExtraInfo(event) {504 const info = this._getOrCreateEntry(event.requestId);505 if (!info) return;506 info.requestWillBeSentExtraInfo.push(event);507 this._patchHeaders(info, info.requestWillBeSentExtraInfo.length - 1);508 }509 responseReceived(event) {510 const info = this._requests.get(event.requestId);511 if (!info) return;512 this._innerResponseReceived(info, event.response);513 }514 requestPaused(request, event) {515 // requestWillBeSentExtraInfo is not being called when interception516 // is enabled. But interception is mutually exclusive with the redirects.517 // So we can use the headers from the Fetch.requestPausedPayload immediately.518 request.setRawRequestHeaders((0, _utils.headersObjectToArray)(event.request.headers, '\n'));519 }520 _innerResponseReceived(info, response) {521 if (!response.connectionId) {522 // Starting with this response we no longer can guarantee that response and extra info correspond to the same index.523 info.sawResponseWithoutConnectionId = true;524 }525 }526 responseReceivedExtraInfo(event) {527 const info = this._getOrCreateEntry(event.requestId);528 info.responseReceivedExtraInfo.push(event);529 this._patchHeaders(info, info.responseReceivedExtraInfo.length - 1);530 this._checkFinished(info);531 }532 processResponse(requestId, response, wasFulfilled) {533 // We are not interested in ExtraInfo tracking for fulfilled requests, our Blink534 // headers are the ones that contain fulfilled headers.535 if (wasFulfilled) {536 this._stopTracking(requestId);537 return;538 }539 const info = this._requests.get(requestId);540 if (!info || info.sawResponseWithoutConnectionId) return;541 response.setWillReceiveExtraHeaders();542 info.responses.push(response);543 this._patchHeaders(info, info.responses.length - 1);544 }545 loadingFinished(event) {546 const info = this._requests.get(event.requestId);547 if (!info) return;548 info.loadingFinished = event;549 this._checkFinished(info);550 }551 loadingFailed(event) {552 const info = this._requests.get(event.requestId);553 if (!info) return;554 info.loadingFailed = event;555 this._checkFinished(info);556 }557 _getOrCreateEntry(requestId) {558 let info = this._requests.get(requestId);559 if (!info) {560 info = {561 requestId: requestId,562 requestWillBeSentExtraInfo: [],563 responseReceivedExtraInfo: [],564 responses: [],565 sawResponseWithoutConnectionId: false566 };567 this._requests.set(requestId, info);568 }569 return info;570 }571 _patchHeaders(info, index) {572 const response = info.responses[index];573 const requestExtraInfo = info.requestWillBeSentExtraInfo[index];574 if (response && requestExtraInfo) response.request().setRawRequestHeaders((0, _utils.headersObjectToArray)(requestExtraInfo.headers, '\n'));575 const responseExtraInfo = info.responseReceivedExtraInfo[index];576 if (response && responseExtraInfo) {577 var _responseExtraInfo$he;578 response.setRawResponseHeaders((0, _utils.headersObjectToArray)(responseExtraInfo.headers, '\n'));579 response.request().responseSize.responseHeadersSize = ((_responseExtraInfo$he = responseExtraInfo.headersText) === null || _responseExtraInfo$he === void 0 ? void 0 : _responseExtraInfo$he.length) || 0;580 }581 }582 _checkFinished(info) {583 if (!info.loadingFinished && !info.loadingFailed) return;584 if (info.responses.length <= info.responseReceivedExtraInfo.length) {585 // We have extra info for each response.586 // We could have more extra infos because we stopped collecting responses at some point.587 this._stopTracking(info.requestId);588 return;589 } // We are not done yet.590 }591 _stopTracking(requestId) {592 this._requests.delete(requestId);593 }...
fetch.js
Source:fetch.js
1"use strict";2Object.defineProperty(exports, "__esModule", {3 value: true4});5exports.APIResponse = exports.APIRequestContext = exports.APIRequest = void 0;6var _fs = _interopRequireDefault(require("fs"));7var _path = _interopRequireDefault(require("path"));8var util = _interopRequireWildcard(require("util"));9var _errors = require("../utils/errors");10var _utils = require("../utils/utils");11var _channelOwner = require("./channelOwner");12var network = _interopRequireWildcard(require("./network"));13var _clientInstrumentation = require("./clientInstrumentation");14let _util$inspect$custom;15function _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); }16function _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; }17function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }18class APIRequest {19 // Instrumentation.20 constructor(playwright) {21 this._playwright = void 0;22 this._contexts = new Set();23 this._onDidCreateContext = void 0;24 this._onWillCloseContext = void 0;25 this._playwright = playwright;26 }27 async newContext(options = {}) {28 var _this$_onDidCreateCon;29 const storageState = typeof options.storageState === 'string' ? JSON.parse(await _fs.default.promises.readFile(options.storageState, 'utf8')) : options.storageState;30 const context = APIRequestContext.from((await this._playwright._channel.newRequest({ ...options,31 extraHTTPHeaders: options.extraHTTPHeaders ? (0, _utils.headersObjectToArray)(options.extraHTTPHeaders) : undefined,32 storageState33 })).request);34 this._contexts.add(context);35 await ((_this$_onDidCreateCon = this._onDidCreateContext) === null || _this$_onDidCreateCon === void 0 ? void 0 : _this$_onDidCreateCon.call(this, context));36 return context;37 }38}39exports.APIRequest = APIRequest;40class APIRequestContext extends _channelOwner.ChannelOwner {41 static from(channel) {42 return channel._object;43 }44 constructor(parent, type, guid, initializer) {45 super(parent, type, guid, initializer, (0, _clientInstrumentation.createInstrumentation)());46 this._request = void 0;47 if (parent instanceof APIRequest) this._request = parent;48 }49 async dispose() {50 var _this$_request, _this$_request$_onWil, _this$_request2;51 await ((_this$_request = this._request) === null || _this$_request === void 0 ? void 0 : (_this$_request$_onWil = _this$_request._onWillCloseContext) === null || _this$_request$_onWil === void 0 ? void 0 : _this$_request$_onWil.call(_this$_request, this));52 await this._channel.dispose();53 (_this$_request2 = this._request) === null || _this$_request2 === void 0 ? void 0 : _this$_request2._contexts.delete(this);54 }55 async delete(url, options) {56 return this.fetch(url, { ...options,57 method: 'DELETE'58 });59 }60 async head(url, options) {61 return this.fetch(url, { ...options,62 method: 'HEAD'63 });64 }65 async get(url, options) {66 return this.fetch(url, { ...options,67 method: 'GET'68 });69 }70 async patch(url, options) {71 return this.fetch(url, { ...options,72 method: 'PATCH'73 });74 }75 async post(url, options) {76 return this.fetch(url, { ...options,77 method: 'POST'78 });79 }80 async put(url, options) {81 return this.fetch(url, { ...options,82 method: 'PUT'83 });84 }85 async fetch(urlOrRequest, options = {}) {86 return this._wrapApiCall(async () => {87 const request = urlOrRequest instanceof network.Request ? urlOrRequest : undefined;88 (0, _utils.assert)(request || typeof urlOrRequest === 'string', 'First argument must be either URL string or Request');89 (0, _utils.assert)((options.data === undefined ? 0 : 1) + (options.form === undefined ? 0 : 1) + (options.multipart === undefined ? 0 : 1) <= 1, `Only one of 'data', 'form' or 'multipart' can be specified`);90 const url = request ? request.url() : urlOrRequest;91 const params = (0, _utils.objectToArray)(options.params);92 const method = options.method || (request === null || request === void 0 ? void 0 : request.method()); // Cannot call allHeaders() here as the request may be paused inside route handler.93 const headersObj = options.headers || (request === null || request === void 0 ? void 0 : request.headers());94 const headers = headersObj ? (0, _utils.headersObjectToArray)(headersObj) : undefined;95 let jsonData;96 let formData;97 let multipartData;98 let postDataBuffer;99 if (options.data !== undefined) {100 if ((0, _utils.isString)(options.data)) {101 if (isJsonContentType(headers)) jsonData = options.data;else postDataBuffer = Buffer.from(options.data, 'utf8');102 } else if (Buffer.isBuffer(options.data)) {103 postDataBuffer = options.data;104 } else if (typeof options.data === 'object' || typeof options.data === 'number' || typeof options.data === 'boolean') {105 jsonData = options.data;106 } else {107 throw new Error(`Unexpected 'data' type`);108 }109 } else if (options.form) {110 formData = (0, _utils.objectToArray)(options.form);111 } else if (options.multipart) {112 multipartData = []; // Convert file-like values to ServerFilePayload structs.113 for (const [name, value] of Object.entries(options.multipart)) {114 if ((0, _utils.isFilePayload)(value)) {115 const payload = value;116 if (!Buffer.isBuffer(payload.buffer)) throw new Error(`Unexpected buffer type of 'data.${name}'`);117 multipartData.push({118 name,119 file: filePayloadToJson(payload)120 });121 } else if (value instanceof _fs.default.ReadStream) {122 multipartData.push({123 name,124 file: await readStreamToJson(value)125 });126 } else {127 multipartData.push({128 name,129 value: String(value)130 });131 }132 }133 }134 if (postDataBuffer === undefined && jsonData === undefined && formData === undefined && multipartData === undefined) postDataBuffer = (request === null || request === void 0 ? void 0 : request.postDataBuffer()) || undefined;135 const postData = postDataBuffer ? postDataBuffer.toString('base64') : undefined;136 const result = await this._channel.fetch({137 url,138 params,139 method,140 headers,141 postData,142 jsonData,143 formData,144 multipartData,145 timeout: options.timeout,146 failOnStatusCode: options.failOnStatusCode,147 ignoreHTTPSErrors: options.ignoreHTTPSErrors148 });149 return new APIResponse(this, result.response);150 });151 }152 async storageState(options = {}) {153 const state = await this._channel.storageState();154 if (options.path) {155 await (0, _utils.mkdirIfNeeded)(options.path);156 await _fs.default.promises.writeFile(options.path, JSON.stringify(state, undefined, 2), 'utf8');157 }158 return state;159 }160}161exports.APIRequestContext = APIRequestContext;162_util$inspect$custom = util.inspect.custom;163class APIResponse {164 constructor(context, initializer) {165 this._initializer = void 0;166 this._headers = void 0;167 this._request = void 0;168 this._request = context;169 this._initializer = initializer;170 this._headers = new network.RawHeaders(this._initializer.headers);171 }172 ok() {173 return this._initializer.status >= 200 && this._initializer.status <= 299;174 }175 url() {176 return this._initializer.url;177 }178 status() {179 return this._initializer.status;180 }181 statusText() {182 return this._initializer.statusText;183 }184 headers() {185 return this._headers.headers();186 }187 headersArray() {188 return this._headers.headersArray();189 }190 async body() {191 try {192 const result = await this._request._channel.fetchResponseBody({193 fetchUid: this._fetchUid()194 });195 if (result.binary === undefined) throw new Error('Response has been disposed');196 return Buffer.from(result.binary, 'base64');197 } catch (e) {198 if (e.message.includes(_errors.kBrowserOrContextClosedError)) throw new Error('Response has been disposed');199 throw e;200 }201 }202 async text() {203 const content = await this.body();204 return content.toString('utf8');205 }206 async json() {207 const content = await this.text();208 return JSON.parse(content);209 }210 async dispose() {211 await this._request._channel.disposeAPIResponse({212 fetchUid: this._fetchUid()213 });214 }215 [_util$inspect$custom]() {216 const headers = this.headersArray().map(({217 name,218 value219 }) => ` ${name}: ${value}`);220 return `APIResponse: ${this.status()} ${this.statusText()}\n${headers.join('\n')}`;221 }222 _fetchUid() {223 return this._initializer.fetchUid;224 }225 async _fetchLog() {226 const {227 log228 } = await this._request._channel.fetchLog({229 fetchUid: this._fetchUid()230 });231 return log;232 }233}234exports.APIResponse = APIResponse;235function filePayloadToJson(payload) {236 return {237 name: payload.name,238 mimeType: payload.mimeType,239 buffer: payload.buffer.toString('base64')240 };241}242async function readStreamToJson(stream) {243 const buffer = await new Promise((resolve, reject) => {244 const chunks = [];245 stream.on('data', chunk => chunks.push(chunk));246 stream.on('end', () => resolve(Buffer.concat(chunks)));247 stream.on('error', err => reject(err));248 });249 const streamPath = Buffer.isBuffer(stream.path) ? stream.path.toString('utf8') : stream.path;250 return {251 name: _path.default.basename(streamPath),252 buffer: buffer.toString('base64')253 };254}255function isJsonContentType(headers) {256 if (!headers) return false;257 for (const {258 name,259 value260 } of headers) {261 if (name.toLocaleLowerCase() === 'content-type') return value === 'application/json';262 }263 return false;...
wkInterceptableRequest.js
Source:wkInterceptableRequest.js
1"use strict";2Object.defineProperty(exports, "__esModule", {3 value: true4});5exports.WKRouteImpl = exports.WKInterceptableRequest = void 0;6var network = _interopRequireWildcard(require("../network"));7var _utils = require("../../utils/utils");8var _async = require("../../utils/async");9function _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); }10function _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; }11/**12 * Copyright 2017 Google Inc. All rights reserved.13 * Modifications copyright (c) Microsoft Corporation.14 *15 * Licensed under the Apache License, Version 2.0 (the "License");16 * you may not use this file except in compliance with the License.17 * You may obtain a copy of the License at18 *19 * http://www.apache.org/licenses/LICENSE-2.020 *21 * Unless required by applicable law or agreed to in writing, software22 * distributed under the License is distributed on an "AS IS" BASIS,23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.24 * See the License for the specific language governing permissions and25 * limitations under the License.26 */27const errorReasons = {28 'aborted': 'Cancellation',29 'accessdenied': 'AccessControl',30 'addressunreachable': 'General',31 'blockedbyclient': 'Cancellation',32 'blockedbyresponse': 'General',33 'connectionaborted': 'General',34 'connectionclosed': 'General',35 'connectionfailed': 'General',36 'connectionrefused': 'General',37 'connectionreset': 'General',38 'internetdisconnected': 'General',39 'namenotresolved': 'General',40 'timedout': 'Timeout',41 'failed': 'General'42};43class WKInterceptableRequest {44 constructor(session, route, frame, event, redirectedFrom, documentId) {45 this._session = void 0;46 this.request = void 0;47 this._requestId = void 0;48 this._timestamp = void 0;49 this._wallTime = void 0;50 this._route = void 0;51 this._redirectedFrom = void 0;52 this._session = session;53 this._requestId = event.requestId;54 this._route = route;55 this._redirectedFrom = redirectedFrom;56 const resourceType = event.type ? event.type.toLowerCase() : redirectedFrom ? redirectedFrom.request.resourceType() : 'other';57 let postDataBuffer = null;58 this._timestamp = event.timestamp;59 this._wallTime = event.walltime * 1000;60 if (event.request.postData) postDataBuffer = Buffer.from(event.request.postData, 'base64');61 this.request = new network.Request(frame, (redirectedFrom === null || redirectedFrom === void 0 ? void 0 : redirectedFrom.request) || null, documentId, event.request.url, resourceType, event.request.method, postDataBuffer, (0, _utils.headersObjectToArray)(event.request.headers));62 }63 _routeForRedirectChain() {64 let request = this;65 while (request._redirectedFrom) request = request._redirectedFrom;66 return request._route;67 }68 createResponse(responsePayload) {69 const getResponseBody = async () => {70 const response = await this._session.send('Network.getResponseBody', {71 requestId: this._requestId72 });73 return Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8');74 };75 const timingPayload = responsePayload.timing;76 const timing = {77 startTime: this._wallTime,78 domainLookupStart: timingPayload ? wkMillisToRoundishMillis(timingPayload.domainLookupStart) : -1,79 domainLookupEnd: timingPayload ? wkMillisToRoundishMillis(timingPayload.domainLookupEnd) : -1,80 connectStart: timingPayload ? wkMillisToRoundishMillis(timingPayload.connectStart) : -1,81 secureConnectionStart: timingPayload ? wkMillisToRoundishMillis(timingPayload.secureConnectionStart) : -1,82 connectEnd: timingPayload ? wkMillisToRoundishMillis(timingPayload.connectEnd) : -1,83 requestStart: timingPayload ? wkMillisToRoundishMillis(timingPayload.requestStart) : -1,84 responseStart: timingPayload ? wkMillisToRoundishMillis(timingPayload.responseStart) : -185 };86 const setCookieSeparator = process.platform === 'darwin' ? ',' : '\n';87 return new network.Response(this.request, responsePayload.status, responsePayload.statusText, (0, _utils.headersObjectToArray)(responsePayload.headers, ',', setCookieSeparator), timing, getResponseBody);88 }89}90exports.WKInterceptableRequest = WKInterceptableRequest;91class WKRouteImpl {92 constructor(session, page, requestId) {93 this._session = void 0;94 this._requestId = void 0;95 this._requestInterceptedPromise = new _async.ManualPromise();96 this._responseInterceptedPromise = void 0;97 this._page = void 0;98 this._session = session;99 this._page = page;100 this._requestId = requestId;101 }102 async responseBody() {103 const response = await this._session.send('Network.getInterceptedResponseBody', {104 requestId: this._requestId105 });106 return Buffer.from(response.body, 'base64');107 }108 async abort(errorCode) {109 const errorType = errorReasons[errorCode];110 (0, _utils.assert)(errorType, 'Unknown error code: ' + errorCode);111 await this._requestInterceptedPromise;112 const isResponseIntercepted = await this._responseInterceptedPromise; // In certain cases, protocol will return error if the request was already canceled113 // or the page was closed. We should tolerate these errors.114 await this._session.sendMayFail(isResponseIntercepted ? 'Network.interceptResponseWithError' : 'Network.interceptRequestWithError', {115 requestId: this._requestId,116 errorType117 });118 }119 async fulfill(response) {120 if (300 <= response.status && response.status < 400) throw new Error('Cannot fulfill with redirect status: ' + response.status);121 await this._requestInterceptedPromise; // In certain cases, protocol will return error if the request was already canceled122 // or the page was closed. We should tolerate these errors.123 let mimeType = response.isBase64 ? 'application/octet-stream' : 'text/plain';124 const headers = (0, _utils.headersArrayToObject)(response.headers, true125 /* lowerCase */126 );127 const contentType = headers['content-type'];128 if (contentType) mimeType = contentType.split(';')[0].trim();129 const isResponseIntercepted = await this._responseInterceptedPromise;130 await this._session.sendMayFail(isResponseIntercepted ? 'Network.interceptWithResponse' : 'Network.interceptRequestWithResponse', {131 requestId: this._requestId,132 status: response.status,133 statusText: network.STATUS_TEXTS[String(response.status)],134 mimeType,135 headers,136 base64Encoded: response.isBase64,137 content: response.body138 });139 }140 async continue(request, overrides) {141 if (overrides.interceptResponse) {142 await this._page._ensureResponseInterceptionEnabled();143 this._responseInterceptedPromise = new _async.ManualPromise();144 }145 await this._requestInterceptedPromise; // In certain cases, protocol will return error if the request was already canceled146 // or the page was closed. We should tolerate these errors.147 await this._session.sendMayFail('Network.interceptWithRequest', {148 requestId: this._requestId,149 url: overrides.url,150 method: overrides.method,151 headers: overrides.headers ? (0, _utils.headersArrayToObject)(overrides.headers, false152 /* lowerCase */153 ) : undefined,154 postData: overrides.postData ? Buffer.from(overrides.postData).toString('base64') : undefined155 });156 if (!this._responseInterceptedPromise) return null;157 const {158 response,159 error160 } = await this._responseInterceptedPromise;161 if (error) throw new Error(`Request failed: ${error.errorText}`);162 return new network.InterceptedResponse(request, response.status, response.statusText, (0, _utils.headersObjectToArray)(response.headers));163 }164}165exports.WKRouteImpl = WKRouteImpl;166function wkMillisToRoundishMillis(value) {167 // WebKit uses -1000 for unavailable.168 if (value === -1000) return -1; // WebKit has a bug, instead of -1 it sends -1000 to be in ms.169 if (value <= 0) {170 // DNS can start before request start on Mac Network Stack171 return -1;172 }173 return (value * 1000 | 0) / 1000;...
index.js
Source:index.js
...120function getAsBooleanFromENV(name) {121 const value = getFromENV(name);122 return !!value && value !== 'false' && value !== '0';123}124function headersObjectToArray(headers, separator, setCookieSeparator) {125 if (!setCookieSeparator) setCookieSeparator = separator;126 const result = [];127 for (const name in headers) {128 const values = headers[name];129 if (separator) {130 const sep = name.toLowerCase() === 'set-cookie' ? setCookieSeparator : separator;131 for (const value of values.split(sep)) result.push({132 name,133 value: value.trim()134 });135 } else {136 result.push({137 name,138 value: values...
utils.js
Source:utils.js
...102export async function mkdirIfNeeded(filePath) {103 // This will harmlessly throw on windows if the dirname is the root directory.104 await mkdirAsync(path.dirname(filePath), { recursive: true }).catch(() => {})105}106export function headersObjectToArray(headers) {107 const result = []108 for (const name in headers) {109 if (!Object.is(headers[name], undefined))110 result.push({ name, value: headers[name] })111 }112 return result113}114export function headersArrayToObject(headers, lowerCase) {115 const result = {}116 for (const { name, value } of headers)117 result[lowerCase ? name.toLowerCase() : name] = value118 return result119}120export function monotonicTime() {...
Using AI Code Generation
1const { headersObjectToArray } = require('playwright/lib/utils/utils');2const headers = {3};4const headerArray = headersObjectToArray(headers);5console.log(headerArray);6const { headersArrayToObject } = require('playwright/lib/utils/utils');7const headersArray = [ 'Content-Type: application/json', 'Content-Length: 123' ];8const headers = headersArrayToObject(headersArray);9console.log(headers);10headersArrayToObject(headersArray)11const { headersArrayToObject } = require('playwright/lib/utils/utils');12const headersArray = [ 'Content-Type: application/json', 'Content-Length: 123' ];13const headers = headersArrayToObject(headersArray);14console.log(headers);15headersObjectToArray(headers)16const { headersObjectToArray } = require('playwright/lib/utils/utils');17const headers = {18};19const headerArray = headersObjectToArray(headers);20console.log(headerArray);21isUnderTest()
Using AI Code Generation
1const headersObjectToArray = require('playwright/lib/utils/utils').headersObjectToArray;2const headers = {3};4const array = headersObjectToArray(headers);5console.log(array);6const headersArrayToObject = require('playwright/lib/utils/utils').headersArrayToObject;7 { name: 'content-type', value: 'application/json' },8 { name: 'x-custom-header', value: 'custom' }9];10const headers = headersArrayToObject(array);11console.log(headers);12const headersObjectToArray = require('playwright/lib/utils/utils').headersObjectToArray;13const headers = {14};15const array = headersObjectToArray(headers);16console.log(array);17const headersArrayToObject = require('playwright/lib/utils/utils').headersArrayToObject;18 { name: 'content-type', value: 'application/json' },19 { name: 'x-custom-header', value: 'custom' }20];21const headers = headersArrayToObject(array);22console.log(headers);23const headersObjectToArray = require('playwright/lib/utils/utils').headersObjectToArray;24const headers = {25};26const array = headersObjectToArray(headers);27console.log(array);
Using AI Code Generation
1const { headersObjectToArray } = require('playwright/lib/utils/utils');2const headersObject = { 'Content-Type': 'application/json' };3const headersArray = headersObjectToArray(headersObject);4console.log(headersArray);5const { headersArrayToObject } = require('playwright/lib/utils/utils');6const headersArray = [ [ 'Content-Type', 'application/json' ] ];7const headersObject = headersArrayToObject(headersArray);8console.log(headersObject);9const { isSafeCloseError } = require('playwright/lib/utils/utils');10const error = new Error('Browser has been closed.');11const isSafe = isSafeCloseError(error);12console.log(isSafe);13const { waitForEvent } = require('playwright/lib/utils/utils');14const emitter = new EventEmitter();15const event = waitForEvent(emitter, 'event');16emitter.emit('event');17const eventResult = await event;18console.log(eventResult);
Using AI Code Generation
1const headersObjectToArray = require('playwright-core/lib/server/network').headersObjectToArray;2const headers = {3};4const headersArray = headersObjectToArray(headers);5console.log(headersArray);6const { headersObjectToArray } = require('playwright');7const headers = {8};9const headersArray = headersObjectToArray(headers);10console.log(headersArray);11const { headersObjectToArray } = require('playwright');12const headers = {13};14const headersArray = headersObjectToArray(headers);15console.log(headersArray);16import { headersObjectToArray } from 'playwright';17const headers = {18};19const headersArray = headersObjectToArray(headers);20console.log(headersArray);21import { headersObjectToArray } from 'playwright';22const headers = {23};24const headersArray = headersObjectToArray(headers);25console.log(headersArray);26import { headersObjectToArray } from 'playwright';27const headers = {
Using AI Code Generation
1const { headersObjectToArray } = require('playwright/lib/utils/utils');2const headers = {3};4const headersArray = headersObjectToArray(headers);5console.log(headersArray);6const { headersArrayToObject } = require('playwright/lib/utils/utils');7];8const headers = headersArrayToObject(headersArray);9console.log(headers);10const { parseURL } = require('playwright/lib/utils/utils');11console.log(url);12const { isString } = require('playwright/lib/utils/utils');13const { isNumber } = require('playwright/lib/utils/utils');
Using AI Code Generation
1const { headersObjectToArray } = require('playwright/lib/utils/utils');2const headers = {3};4console.log(headersObjectToArray(headers));5const { headersArrayToObject } = require('playwright/lib/utils/utils');6];7console.log(headersArrayToObject(headers));8const { mergeHeaders } = require('playwright/lib/utils/utils');9const headers1 = {10};11const headers2 = {12};13console.log(mergeHeaders(headers1, headers2));14const { assert } = require('playwright/lib/utils/utils');15assert(false, 'This will throw an error');16const { createGuid } = require('playwright/lib/utils/utils');17console.log(createGuid());18const { createGuid } = require('playwright/lib/utils/utils');19console.log(createGuid
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!