Repository: microsoft/playwright
File: packages/playwright-core/src/server/bidi/bidiNetworkManager.ts (TypeScript)

Code before:
    this._eventListeners = [
      eventsHelper.addEventListener(bidiSession, 'network.beforeRequestSent', this._onBeforeRequestSent.bind(this)),
      eventsHelper.addEventListener(bidiSession, 'network.responseStarted', this._onResponseStarted.bind(this)),
      eventsHelper.addEventListener(bidiSession, 'network.responseCompleted', this._onResponseCompleted.bind(this)),
      eventsHelper.addEventListener(bidiSession, 'network.fetchError', this._onFetchError.bind(this)),
      eventsHelper.addEventListener(bidiSession, 'network.authRequired', this._onAuthRequired.bind(this)),
    ];
  }

  dispose() {
    eventsHelper.removeEventListeners(this._eventListeners);
  }

  private _onBeforeRequestSent(param: bidi.Network.BeforeRequestSentParameters) {
    if (param.request.url.startsWith('data:'))
      return;
    const redirectedFrom = param.redirectCount ? (this._requests.get(param.request.request) || null) : null;
    const frame = redirectedFrom ? redirectedFrom.request.frame() : (param.context ? this._page.frameManager.frame(param.context) : null);
    if (!frame)
      return;
    if (redirectedFrom)
      this._deleteRequest(redirectedFrom._id);

    // handle CORS preflight requests
    if (param.request.method === 'OPTIONS') {
      // TODO: we should detect preflight requests by looking at param.initiator.type, but the Bidi spec for
      // the initiator type is incomplete and browser implementations are inconsistent, so we check for an
      // Access-Control-Request-Method header instead. See https://github.com/w3c/webdriver-bidi/issues/698.
      const requestHeaders = Object.fromEntries(param.request.headers.map(h => [h.name.toLowerCase(), bidiBytesValueToString(h.value)]));
      if (requestHeaders['access-control-request-method']) {
        if (param.intercepts) {
          // If interception is enabled, we accept all CORS options, assuming that this was intended when setting the route.
          const responseHeaders: types.HeadersArray = [
            { name: 'Access-Control-Allow-Origin', value: requestHeaders['origin'] || '*' },
            { name: 'Access-Control-Allow-Methods', value: requestHeaders['access-control-request-method'] },
            { name: 'Access-Control-Allow-Credentials', value: 'true' }
          ];
          if (requestHeaders['access-control-request-headers'])
            responseHeaders.push({ name: 'Access-Control-Allow-Headers', value: requestHeaders['access-control-request-headers'] });
          this._session.sendMayFail('network.provideResponse', {
            request: param.request.request,
            statusCode: 204,
            headers: toBidiHeaders(responseHeaders),
          });
        }
        return;
      }
    }

    let route;
    let headersOverride: types.HeadersArray | undefined;

Review comment (suggestion):
I don't know about other types, but marking `preflight` sounds non-controversial.

Code after:
    this._eventListeners = [
      eventsHelper.addEventListener(bidiSession, 'network.beforeRequestSent', this._onBeforeRequestSent.bind(this)),
      eventsHelper.addEventListener(bidiSession, 'network.responseStarted', this._onResponseStarted.bind(this)),
      eventsHelper.addEventListener(bidiSession, 'network.responseCompleted', this._onResponseCompleted.bind(this)),
      eventsHelper.addEventListener(bidiSession, 'network.fetchError', this._onFetchError.bind(this)),
      eventsHelper.addEventListener(bidiSession, 'network.authRequired', this._onAuthRequired.bind(this)),
    ];
  }

  dispose() {
    eventsHelper.removeEventListeners(this._eventListeners);
  }

  private _onBeforeRequestSent(param: bidi.Network.BeforeRequestSentParameters) {
    if (param.request.url.startsWith('data:'))
      return;
    const redirectedFrom = param.redirectCount ? (this._requests.get(param.request.request) || null) : null;
    const frame = redirectedFrom ? redirectedFrom.request.frame() : (param.context ? this._page.frameManager.frame(param.context) : null);
    if (!frame)
      return;
    if (redirectedFrom)
      this._deleteRequest(redirectedFrom._id);

    // handle CORS preflight requests
    if (param.request.method === 'OPTIONS') {
      // TODO: we should detect preflight requests by looking at param.initiator.type, but the Bidi spec for
      // the initiator type is incomplete and browser implementations are inconsistent, so we check for an
      // Access-Control-Request-Method header instead. See https://github.com/w3c/webdriver-bidi/issues/698.
      const requestHeaders = Object.fromEntries(param.request.headers.map(h => [h.name.toLowerCase(), bidiBytesValueToString(h.value)]));
      if (param.initiator?.type === 'preflight' || requestHeaders['access-control-request-method']) {
        if (param.intercepts) {
          // If interception is enabled, we accept all CORS options, assuming that this was intended when setting the route.
          const responseHeaders: types.HeadersArray = [
            { name: 'Access-Control-Allow-Origin', value: requestHeaders['origin'] || '*' },
            { name: 'Access-Control-Allow-Methods', value: requestHeaders['access-control-request-method'] },
            { name: 'Access-Control-Allow-Credentials', value: 'true' }
          ];
          if (requestHeaders['access-control-request-headers'])
            responseHeaders.push({ name: 'Access-Control-Allow-Headers', value: requestHeaders['access-control-request-headers'] });
          this._session.sendMayFail('network.provideResponse', {
            request: param.request.request,
            statusCode: 204,
            headers: toBidiHeaders(responseHeaders),
          });
        }
        return;
      }
    }

    let route;
    let headersOverride: types.HeadersArray | undefined;