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 74 75 76 77 78 79 80 81 82 83 84 85 86 | 20x 20x 19x 19x 1x 18x 18x 18x 18x 18x 2x 2x 18x 18x 18x 18x 18x 2x 2x | import { PatcherContext } from '../context'
import { FingerprintContextSymbol, XHRFingerprintMetadata, XHRContext, XHRWithFingerprintContext } from './types'
import { collectSignalsForProtectedUrl } from '../signalsInjection'
import { createPatcherRequest } from './patcherRequest'
import { logger } from '../../../shared/logger'
/**
* Creates a patched version of the `XMLHttpRequest.prototype.open` method to capture request metadata,
* apply signal handling, and provide additional context for fingerprinting.
*
* @param {PatcherContext} ctx - The context object used for configuring and managing the patching process
* and interacting with signal handling mechanisms.
* @return {function} Returns a new function that wraps the original `XMLHttpRequest.open` method and includes
* additional behavior for metadata collection and signal injection.
*/
export function createPatchedOpen(ctx: PatcherContext): typeof XMLHttpRequest.prototype.open {
const originalOpen = XMLHttpRequest.prototype.open
return function patchedOpen(
this: XHRWithFingerprintContext,
method: string,
url: string,
async: boolean = true,
username?: string | null,
password?: string | null
) {
const callOpen = () => originalOpen.call(this, method, url, async, username, password)
if (!async) {
// Sync requests are not supported for now
return callOpen()
}
let metadata: XHRFingerprintMetadata
try {
metadata = {
method: method?.toUpperCase?.(),
// Resolve relative URLs against the current location
url: new URL(url, location.origin).toString(),
}
} catch (e) {
// If URL cannot be resolved (very unlikely)
logger.warn('Failed to resolve XHR URL for patching:', e)
metadata = {
method: method?.toUpperCase?.(),
url,
}
}
try {
const request = createPatcherRequest(this, metadata)
// Start gathering signals as soon as possible.
const signalsCollectionPromise = collectSignalsForProtectedUrl({
request,
ctx,
}).catch((error) => {
logger.error('Error injecting signals:', error)
return undefined
})
const nextFingerprintContext: XHRContext = {
preservedWithCredentials: this[FingerprintContextSymbol]?.preservedWithCredentials,
signalsCollectionPromise,
request,
}
Object.assign(this, {
[FingerprintContextSymbol]: nextFingerprintContext,
})
} catch (e) {
logger.error('Error setting XHR fingerprint context:', e)
}
callOpen()
// Restore the original withCredentials setting. This can only be changed before the initial send
// or after the XHR instance is reinitialized by calling open after a send.
const fingerprintContext = this[FingerprintContextSymbol]
if (fingerprintContext?.preservedWithCredentials !== undefined) {
this.withCredentials = fingerprintContext.preservedWithCredentials
fingerprintContext.preservedWithCredentials = undefined
}
}
}
|