All files / src/scripts/instrumentor/patcher/fetch fetch.ts

86.95% Statements 20/23
87.5% Branches 7/8
100% Functions 2/2
86.95% Lines 20/23

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73                                                      28x           28x   28x 27x   27x 27x   27x   27x 24x 24x     1x     27x   26x 26x 14x   14x 2x   12x             26x     28x    
import { PatcherContext } from '../context'
import { ProtectedApi } from '../../../../shared/types'
import { handleSignalsInjection } from '../signalsInjection'
import { resolvePatcherRequest } from './patcherRequest'
import { AGENT_DATA_HEADER } from '../../../../shared/const'
import { logger } from '../../../shared/logger'
 
/**
 * Parameters required for patching the fetch API.
 */
export type PatchFetchParams = {
  /** Array of protected APIs that should have signals attached to their requests */
  protectedApis: ProtectedApi[]
  /** Context object providing access to signals and other patcher functionality */
  ctx: PatcherContext
}
 
/**
 * Patches the global fetch API to automatically add Fingerprint signals to requests made to protected APIs.
 *
 * This function intercepts all fetch requests and checks if they target protected URLs. For protected
 * requests, it adds a signals' header before forwarding the request.
 *
 * @param ctx - Patcher context providing access to signals and other functionality
 *
 */
export function patchFetch(ctx: PatcherContext) {
  Iif (typeof window.fetch !== 'function') {
    logger.warn('window.fetch is not available.')
 
    return
  }
 
  const originalFetch = window.fetch
 
  window.fetch = async (...params) => {
    let didInjectSignals = false
 
    try {
      logger.debug('Incoming fetch request', params)
 
      const request = resolvePatcherRequest(params)
 
      if (request) {
        logger.debug('Resolved fetch request:', request)
        didInjectSignals = await handleSignalsInjection({ request, ctx })
      }
    } catch (error) {
      logger.error('Patched fetch error:', error)
    }
 
    const response = await originalFetch(...params)
 
    try {
      if (didInjectSignals) {
        const agentData = response.headers.get(AGENT_DATA_HEADER)
 
        if (agentData) {
          ctx.processAgentData(agentData)
        } else {
          logger.warn('Agent data not found in response')
        }
      }
    } catch (e) {
      logger.error('Error processing agent data:', e)
    }
 
    return response
  }
 
  logger.debug('Fetch patched successfully.')
}