File size: 19,723 Bytes
d4b85c0
1
{"version":3,"sources":["../../src/interceptors/fetch/index.ts","../../src/utils/canParseUrl.ts","../../src/interceptors/fetch/utils/createNetworkError.ts","../../src/interceptors/fetch/utils/followRedirect.ts","../../src/interceptors/fetch/utils/brotli-decompress.ts","../../src/interceptors/fetch/utils/decompression.ts"],"sourcesContent":["import { invariant } from 'outvariant'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\nimport { HttpRequestEventMap, IS_PATCHED_MODULE } from '../../glossary'\nimport { Interceptor } from '../../Interceptor'\nimport { RequestController } from '../../RequestController'\nimport { emitAsync } from '../../utils/emitAsync'\nimport { handleRequest } from '../../utils/handleRequest'\nimport { canParseUrl } from '../../utils/canParseUrl'\nimport { createRequestId } from '../../createRequestId'\nimport { createNetworkError } from './utils/createNetworkError'\nimport { followFetchRedirect } from './utils/followRedirect'\nimport { decompressResponse } from './utils/decompression'\nimport { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'\nimport { FetchResponse } from '../../utils/fetchUtils'\n\nexport class FetchInterceptor extends Interceptor<HttpRequestEventMap> {\n  static symbol = Symbol('fetch')\n\n  constructor() {\n    super(FetchInterceptor.symbol)\n  }\n\n  protected checkEnvironment() {\n    return hasConfigurableGlobal('fetch')\n  }\n\n  protected async setup() {\n    const pureFetch = globalThis.fetch\n\n    invariant(\n      !(pureFetch as any)[IS_PATCHED_MODULE],\n      'Failed to patch the \"fetch\" module: already patched.'\n    )\n\n    globalThis.fetch = async (input, init) => {\n      const requestId = createRequestId()\n\n      /**\n       * @note Resolve potentially relative request URL\n       * against the present `location`. This is mainly\n       * for native `fetch` in JSDOM.\n       * @see https://github.com/mswjs/msw/issues/1625\n       */\n      const resolvedInput =\n        typeof input === 'string' &&\n        typeof location !== 'undefined' &&\n        !canParseUrl(input)\n          ? new URL(input, location.origin)\n          : input\n\n      const request = new Request(resolvedInput, init)\n      const responsePromise = new DeferredPromise<Response>()\n      const controller = new RequestController(request)\n\n      this.logger.info('[%s] %s', request.method, request.url)\n      this.logger.info('awaiting for the mocked response...')\n\n      this.logger.info(\n        'emitting the \"request\" event for %s listener(s)...',\n        this.emitter.listenerCount('request')\n      )\n\n      const isRequestHandled = await handleRequest({\n        request,\n        requestId,\n        emitter: this.emitter,\n        controller,\n        onResponse: async (rawResponse) => {\n          this.logger.info('received mocked response!', {\n            rawResponse,\n          })\n\n          // Decompress the mocked response body, if applicable.\n          const decompressedStream = decompressResponse(rawResponse)\n          const response =\n            decompressedStream === null\n              ? rawResponse\n              : new FetchResponse(decompressedStream, rawResponse)\n\n          FetchResponse.setUrl(request.url, response)\n\n          /**\n           * Undici's handling of following redirect responses.\n           * Treat the \"manual\" redirect mode as a regular mocked response.\n           * This way, the client can manually follow the redirect it receives.\n           * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1173\n           */\n          if (FetchResponse.isRedirectResponse(response.status)) {\n            // Reject the request promise if its `redirect` is set to `error`\n            // and it receives a mocked redirect response.\n            if (request.redirect === 'error') {\n              responsePromise.reject(createNetworkError('unexpected redirect'))\n              return\n            }\n\n            if (request.redirect === 'follow') {\n              followFetchRedirect(request, response).then(\n                (response) => {\n                  responsePromise.resolve(response)\n                },\n                (reason) => {\n                  responsePromise.reject(reason)\n                }\n              )\n              return\n            }\n          }\n\n          if (this.emitter.listenerCount('response') > 0) {\n            this.logger.info('emitting the \"response\" event...')\n\n            // Await the response listeners to finish before resolving\n            // the response promise. This ensures all your logic finishes\n            // before the interceptor resolves the pending response.\n            await emitAsync(this.emitter, 'response', {\n              // Clone the mocked response for the \"response\" event listener.\n              // This way, the listener can read the response and not lock its body\n              // for the actual fetch consumer.\n              response: response.clone(),\n              isMockedResponse: true,\n              request,\n              requestId,\n            })\n          }\n\n          responsePromise.resolve(response)\n        },\n        onRequestError: (response) => {\n          this.logger.info('request has errored!', { response })\n          responsePromise.reject(createNetworkError(response))\n        },\n        onError: (error) => {\n          this.logger.info('request has been aborted!', { error })\n          responsePromise.reject(error)\n        },\n      })\n\n      if (isRequestHandled) {\n        this.logger.info('request has been handled, returning mock promise...')\n        return responsePromise\n      }\n\n      this.logger.info(\n        'no mocked response received, performing request as-is...'\n      )\n\n      return pureFetch(request).then(async (response) => {\n        this.logger.info('original fetch performed', response)\n\n        if (this.emitter.listenerCount('response') > 0) {\n          this.logger.info('emitting the \"response\" event...')\n\n          const responseClone = response.clone()\n\n          await emitAsync(this.emitter, 'response', {\n            response: responseClone,\n            isMockedResponse: false,\n            request,\n            requestId,\n          })\n        }\n\n        return response\n      })\n    }\n\n    Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n      enumerable: true,\n      configurable: true,\n      value: true,\n    })\n\n    this.subscriptions.push(() => {\n      Object.defineProperty(globalThis.fetch, IS_PATCHED_MODULE, {\n        value: undefined,\n      })\n\n      globalThis.fetch = pureFetch\n\n      this.logger.info(\n        'restored native \"globalThis.fetch\"!',\n        globalThis.fetch.name\n      )\n    })\n  }\n}\n","/**\n * Returns a boolean indicating whether the given URL string\n * can be parsed into a `URL` instance.\n * A substitute for `URL.canParse()` for Node.js 18.\n */\nexport function canParseUrl(url: string): boolean {\n  try {\n    new URL(url)\n    return true\n  } catch (_error) {\n    return false\n  }\n}\n","export function createNetworkError(cause?: unknown) {\n  return Object.assign(new TypeError('Failed to fetch'), {\n    cause,\n  })\n}\n","import { createNetworkError } from './createNetworkError'\n\nconst REQUEST_BODY_HEADERS = [\n  'content-encoding',\n  'content-language',\n  'content-location',\n  'content-type',\n  'content-length',\n]\n\nconst kRedirectCount = Symbol('kRedirectCount')\n\n/**\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/index.js#L1210\n */\nexport async function followFetchRedirect(\n  request: Request,\n  response: Response\n): Promise<Response> {\n  if (response.status !== 303 && request.body != null) {\n    return Promise.reject(createNetworkError())\n  }\n\n  const requestUrl = new URL(request.url)\n\n  let locationUrl: URL\n  try {\n    // If the location is a relative URL, use the request URL as the base URL.\n    locationUrl = new URL(response.headers.get('location')!, request.url) \n  } catch (error) {\n    return Promise.reject(createNetworkError(error))\n  }\n\n  if (\n    !(locationUrl.protocol === 'http:' || locationUrl.protocol === 'https:')\n  ) {\n    return Promise.reject(\n      createNetworkError('URL scheme must be a HTTP(S) scheme')\n    )\n  }\n\n  if (Reflect.get(request, kRedirectCount) > 20) {\n    return Promise.reject(createNetworkError('redirect count exceeded'))\n  }\n\n  Object.defineProperty(request, kRedirectCount, {\n    value: (Reflect.get(request, kRedirectCount) || 0) + 1,\n  })\n\n  if (\n    request.mode === 'cors' &&\n    (locationUrl.username || locationUrl.password) &&\n    !sameOrigin(requestUrl, locationUrl)\n  ) {\n    return Promise.reject(\n      createNetworkError('cross origin not allowed for request mode \"cors\"')\n    )\n  }\n\n  const requestInit: RequestInit = {}\n\n  if (\n    ([301, 302].includes(response.status) && request.method === 'POST') ||\n    (response.status === 303 && !['HEAD', 'GET'].includes(request.method))\n  ) {\n    requestInit.method = 'GET'\n    requestInit.body = null\n\n    REQUEST_BODY_HEADERS.forEach((headerName) => {\n      request.headers.delete(headerName)\n    })\n  }\n\n  if (!sameOrigin(requestUrl, locationUrl)) {\n    request.headers.delete('authorization')\n    request.headers.delete('proxy-authorization')\n    request.headers.delete('cookie')\n    request.headers.delete('host')\n  }\n\n  /**\n   * @note Undici \"safely\" extracts the request body.\n   * I suspect we cannot dispatch this request again\n   * since its body has been read and the stream is locked.\n   */\n\n  requestInit.headers = request.headers\n  return fetch(new Request(locationUrl, requestInit))\n}\n\n/**\n * @see https://github.com/nodejs/undici/blob/a6dac3149c505b58d2e6d068b97f4dc993da55f0/lib/web/fetch/util.js#L761\n */\nfunction sameOrigin(left: URL, right: URL): boolean {\n  if (left.origin === right.origin && left.origin === 'null') {\n    return true\n  }\n\n  if (\n    left.protocol === right.protocol &&\n    left.hostname === right.hostname &&\n    left.port === right.port\n  ) {\n    return true\n  }\n\n  return false\n}\n","import zlib from 'node:zlib'\n\nexport class BrotliDecompressionStream extends TransformStream {\n  constructor() {\n    const decompress = zlib.createBrotliDecompress({\n      flush: zlib.constants.BROTLI_OPERATION_FLUSH,\n      finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH,\n    })\n\n    super({\n      async transform(chunk, controller) {\n        const buffer = Buffer.from(chunk)\n\n        const decompressed = await new Promise<Buffer>((resolve, reject) => {\n          decompress.write(buffer, (error) => {\n            if (error) reject(error)\n          })\n\n          decompress.flush()\n          decompress.once('data', (data) => resolve(data))\n          decompress.once('error', (error) => reject(error))\n          decompress.once('end', () => controller.terminate())\n        }).catch((error) => {\n          controller.error(error)\n        })\n\n        controller.enqueue(decompressed)\n      },\n    })\n  }\n}\n","// Import from an internal alias that resolves to different modules\n// depending on the environment. This way, we can keep the fetch interceptor\n// intact while using different strategies for Brotli decompression.\nimport { BrotliDecompressionStream } from 'internal:brotli-decompress'\n\nclass PipelineStream extends TransformStream {\n  constructor(\n    transformStreams: Array<TransformStream>,\n    ...strategies: Array<QueuingStrategy>\n  ) {\n    super({}, ...strategies)\n\n    const readable = [super.readable as any, ...transformStreams].reduce(\n      (readable, transform) => readable.pipeThrough(transform)\n    )\n\n    Object.defineProperty(this, 'readable', {\n      get() {\n        return readable\n      },\n    })\n  }\n}\n\nexport function parseContentEncoding(contentEncoding: string): Array<string> {\n  return contentEncoding\n    .toLowerCase()\n    .split(',')\n    .map((coding) => coding.trim())\n}\n\nfunction createDecompressionStream(\n  contentEncoding: string\n): TransformStream | null {\n  if (contentEncoding === '') {\n    return null\n  }\n\n  const codings = parseContentEncoding(contentEncoding)\n\n  if (codings.length === 0) {\n    return null\n  }\n\n  const transformers = codings.reduceRight<Array<TransformStream>>(\n    (transformers, coding) => {\n      if (coding === 'gzip' || coding === 'x-gzip') {\n        return transformers.concat(new DecompressionStream('gzip'))\n      } else if (coding === 'deflate') {\n        return transformers.concat(new DecompressionStream('deflate'))\n      } else if (coding === 'br') {\n        return transformers.concat(new BrotliDecompressionStream())\n      } else {\n        transformers.length = 0\n      }\n\n      return transformers\n    },\n    []\n  )\n\n  return new PipelineStream(transformers)\n}\n\nexport function decompressResponse(\n  response: Response\n): ReadableStream<any> | null {\n  if (response.body === null) {\n    return null\n  }\n\n  const decompressionStream = createDecompressionStream(\n    response.headers.get('content-encoding') || ''\n  )\n\n  if (!decompressionStream) {\n    return null\n  }\n\n  // Use `pipeTo` and return the decompression stream's readable\n  // instead of `pipeThrough` because that will lock the original\n  // response stream, making it unusable as the input to Response.\n  response.body.pipeTo(decompressionStream.writable)\n  return decompressionStream.readable\n}\n"],"mappings":"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","names":["readable","transformers","response"]}