feat(tracker): track network requests in iframes
This commit is contained in:
parent
c1568b0929
commit
5ddb0bbad4
3 changed files with 60 additions and 13 deletions
|
|
@ -14,6 +14,8 @@ import type { Options as ObserverOptions } from './observer/top_observer.js'
|
|||
import type { Options as SanitizerOptions } from './sanitizer.js'
|
||||
import type { Options as LoggerOptions } from './logger.js'
|
||||
import type { Options as SessOptions } from './session.js'
|
||||
import type { Options as NetworkOptions } from '../modules/network.js'
|
||||
|
||||
import type {
|
||||
Options as WebworkerOptions,
|
||||
ToWorkerData,
|
||||
|
|
@ -75,6 +77,7 @@ type AppOptions = {
|
|||
|
||||
// @deprecated
|
||||
onStart?: StartCallback
|
||||
network?: NetworkOptions
|
||||
} & WebworkerOptions &
|
||||
SessOptions
|
||||
|
||||
|
|
@ -99,6 +102,7 @@ export default class App {
|
|||
private readonly stopCallbacks: Array<() => any> = []
|
||||
private readonly commitCallbacks: Array<CommitCallback> = []
|
||||
private readonly options: AppOptions
|
||||
public readonly networkOptions?: NetworkOptions
|
||||
private readonly revID: string
|
||||
private activityState: ActivityState = ActivityState.NotActive
|
||||
private readonly version = 'TRACKER_VERSION' // TODO: version compatability check inside each plugin.
|
||||
|
|
@ -109,6 +113,7 @@ export default class App {
|
|||
// } ?? maybe onStart is good
|
||||
|
||||
this.projectKey = projectKey
|
||||
this.networkOptions = options.network
|
||||
this.options = Object.assign(
|
||||
{
|
||||
revID: '',
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import Observer from './observer.js'
|
||||
import { CreateIFrameDocument } from '../messages.gen.js'
|
||||
import Network from '../../modules/network.js'
|
||||
|
||||
export default class IFrameObserver extends Observer {
|
||||
observe(iframe: HTMLIFrameElement) {
|
||||
const doc = iframe.contentDocument
|
||||
const iWindow = iframe.contentWindow
|
||||
const hostID = this.app.nodes.getID(iframe)
|
||||
console.log(iframe)
|
||||
if (!doc || hostID === undefined) {
|
||||
return
|
||||
} //log TODO common app.logger
|
||||
|
|
@ -16,6 +19,7 @@ export default class IFrameObserver extends Observer {
|
|||
return
|
||||
}
|
||||
this.app.send(CreateIFrameDocument(hostID, docID))
|
||||
Network(this.app, this.app.networkOptions, iWindow!)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ export interface Options {
|
|||
sanitizer?: Sanitizer
|
||||
}
|
||||
|
||||
export default function (app: App, opts: Partial<Options> = {}) {
|
||||
export default function (app: App, opts: Partial<Options> = {}, customEnv?: Record<string, any>) {
|
||||
const options: Options = Object.assign(
|
||||
{
|
||||
failuresOnly: false,
|
||||
|
|
@ -150,8 +150,11 @@ export default function (app: App, opts: Partial<Options> = {}) {
|
|||
}
|
||||
|
||||
/* ====== Fetch ====== */
|
||||
const origFetch = window.fetch.bind(window) as WindowFetch
|
||||
window.fetch = (input, init = {}) => {
|
||||
const origFetch = customEnv
|
||||
? (customEnv.fetch.bind(customEnv) as WindowFetch)
|
||||
: (window.fetch.bind(window) as WindowFetch)
|
||||
|
||||
const trackFetch = (input: RequestInfo | URL, init: RequestInit = {}) => {
|
||||
if (!(typeof input === 'string' || input instanceof URL) || app.isServiceURL(String(input))) {
|
||||
return origFetch(input, init)
|
||||
}
|
||||
|
|
@ -237,12 +240,23 @@ export default function (app: App, opts: Partial<Options> = {}) {
|
|||
return response
|
||||
})
|
||||
}
|
||||
|
||||
if (customEnv) {
|
||||
customEnv.fetch = trackFetch
|
||||
} else {
|
||||
window.fetch = trackFetch
|
||||
}
|
||||
/* ====== <> ====== */
|
||||
|
||||
/* ====== XHR ====== */
|
||||
const nativeOpen = XMLHttpRequest.prototype.open
|
||||
XMLHttpRequest.prototype.open = function (initMethod, url) {
|
||||
const xhr = this
|
||||
|
||||
const nativeOpen = customEnv
|
||||
? customEnv.XMLHttpRequest.prototype.open
|
||||
: XMLHttpRequest.prototype.open
|
||||
|
||||
function trackXMLHttpReqOpen(initMethod: string, url: string | URL) {
|
||||
// @ts-ignore ??? this -> XMLHttpRequest
|
||||
const xhr = this as XMLHttpRequest
|
||||
setSessionTokenHeader((name, value) => xhr.setRequestHeader(name, value))
|
||||
|
||||
let startTime = 0
|
||||
|
|
@ -302,23 +316,47 @@ export default function (app: App, opts: Partial<Options> = {}) {
|
|||
|
||||
//TODO: handle error (though it has no Error API nor any useful information)
|
||||
//xhr.addEventListener('error', (e) => {})
|
||||
return nativeOpen.apply(this, arguments)
|
||||
// @ts-ignore ??? this -> XMLHttpRequest
|
||||
return nativeOpen.apply(this as XMLHttpRequest, arguments)
|
||||
}
|
||||
if (customEnv) {
|
||||
customEnv.XMLHttpRequest.prototype.open = trackXMLHttpReqOpen.bind(customEnv)
|
||||
} else {
|
||||
XMLHttpRequest.prototype.open = trackXMLHttpReqOpen
|
||||
}
|
||||
|
||||
const nativeSend = XMLHttpRequest.prototype.send
|
||||
XMLHttpRequest.prototype.send = function (body) {
|
||||
const rdo = getXHRRequestDataObject(this)
|
||||
function trackXHRSend(body: Document | XMLHttpRequestBodyInit | null | undefined) {
|
||||
// @ts-ignore ??? this -> XMLHttpRequest
|
||||
const rdo = getXHRRequestDataObject(this as XMLHttpRequest)
|
||||
rdo.body = body
|
||||
|
||||
return nativeSend.apply(this, arguments)
|
||||
// @ts-ignore ??? this -> XMLHttpRequest
|
||||
return nativeSend.apply(this as XMLHttpRequest, arguments)
|
||||
}
|
||||
|
||||
if (customEnv) {
|
||||
customEnv.XMLHttpRequest.prototype.send = trackXHRSend.bind(customEnv)
|
||||
} else {
|
||||
XMLHttpRequest.prototype.send = trackXHRSend
|
||||
}
|
||||
|
||||
const nativeSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader
|
||||
XMLHttpRequest.prototype.setRequestHeader = function (name, value) {
|
||||
|
||||
function trackSetReqHeader(name: string, value: string) {
|
||||
if (!isHIgnored(name)) {
|
||||
const rdo = getXHRRequestDataObject(this)
|
||||
// @ts-ignore ??? this -> XMLHttpRequest
|
||||
const rdo = getXHRRequestDataObject(this as XMLHttpRequest)
|
||||
rdo.headers[name] = value
|
||||
}
|
||||
// @ts-ignore ??? this -> XMLHttpRequest
|
||||
return nativeSetRequestHeader.apply(this as XMLHttpRequest, arguments)
|
||||
}
|
||||
|
||||
return nativeSetRequestHeader.apply(this, arguments)
|
||||
if (customEnv) {
|
||||
customEnv.XMLHttpRequest.prototype.setRequestHeader = trackSetReqHeader.bind(customEnv)
|
||||
} else {
|
||||
XMLHttpRequest.prototype.setRequestHeader = trackSetReqHeader
|
||||
}
|
||||
/* ====== <> ====== */
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue