Better network sanitizer (#2969)

* tracker: improve network sanitization

* ui: fix hl image gen

* tracker: rm sanitizer thing
This commit is contained in:
Delirium 2025-01-24 14:06:34 +01:00 committed by GitHub
parent c2878bacd4
commit 6882c62a32
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 52 additions and 16 deletions

View file

@ -111,7 +111,7 @@ function HighlightPanel({ onClose }: { onClose: () => void }) {
const onSave = async () => { const onSave = async () => {
try { try {
notesStore.setSaving(true) notesStore.setSaving(true)
const playerContainer = document.querySelector('iframe')?.contentWindow?.document.body; const playerContainer = document.querySelector('iframe')?.contentWindow?.document;
let thumbnail; let thumbnail;
if (playerContainer) { if (playerContainer) {
thumbnail = await elementToImage(playerContainer); thumbnail = await elementToImage(playerContainer);
@ -125,8 +125,8 @@ function HighlightPanel({ onClose }: { onClose: () => void }) {
endAt: parseInt(uiPlayerStore.highlightSelection.endTs, 10), endAt: parseInt(uiPlayerStore.highlightSelection.endTs, 10),
thumbnail, thumbnail,
} }
if (editNoteId) { if (editNote) {
await notesStore.updateNote(editNoteId, note); await notesStore.updateNote(editNote.noteId, note);
toast.success('Highlight updated'); toast.success('Highlight updated');
} else { } else {
const sessionId = sessionStore.current.sessionId; const sessionId = sessionStore.current.sessionId;
@ -239,16 +239,21 @@ window.__debugElementToImage = (el) => elementToImage(el).then(img => {
a.click(); a.click();
}); });
function elementToImage(el) { function elementToImage(doc: Document) {
const el = doc.body;
return import('html2canvas').then(({ default: html2canvas }) => { return import('html2canvas').then(({ default: html2canvas }) => {
const images = doc.querySelectorAll('img');
images.forEach((img) => {
img.setAttribute('crossorigin', 'Anonymous');
})
return html2canvas( return html2canvas(
el, el,
{ {
scale: 1, scale: 1,
allowTaint: true, allowTaint: true,
useCORS: false, foreignObjectRendering: true,
useCORS: true,
logging: true, logging: true,
foreignObjectRendering: false,
height: 900, height: 900,
width: 1200, width: 1200,
x: 0, x: 0,
@ -263,4 +268,36 @@ function elementToImage(el) {
}) })
} }
const convertAllImagesToBase64 = (proxyURL, cloned) => {
const pendingImagesPromises = [];
const pendingPromisesData = [];
const images = cloned.getElementsByTagName('img');
for (let i = 0; i < images.length; i += 1) {
const promise = new Promise((resolve, reject) => {
pendingPromisesData.push({
index: i, resolve, reject,
});
});
pendingImagesPromises.push(promise);
}
for (let i = 0; i < images.length; i += 1) {
fetch(`${proxyURL}?url=${images[i].src}`)
.then((response) => response.json())
.then((data) => {
const pending = pendingPromisesData.find((p) => p.index === i);
images[i].src = data;
pending.resolve(data);
})
.catch((e) => {
const pending = pendingPromisesData.find((p) => p.index === i);
pending.reject(e);
});
}
return Promise.all(pendingImagesPromises);
};
export default observer(HighlightPanel); export default observer(HighlightPanel);

View file

@ -55,5 +55,5 @@
"eslint --fix --quiet" "eslint --fix --quiet"
] ]
}, },
"packageManager": "yarn@4.5.1" "packageManager": "yarn@4.6.0"
} }

View file

@ -1,7 +1,7 @@
{ {
"name": "@openreplay/tracker", "name": "@openreplay/tracker",
"description": "The OpenReplay tracker main package", "description": "The OpenReplay tracker main package",
"version": "15.0.5", "version": "15.0.6",
"keywords": [ "keywords": [
"logging", "logging",
"replay" "replay"
@ -80,5 +80,5 @@
"engines": { "engines": {
"node": ">=14.0" "node": ">=14.0"
}, },
"packageManager": "yarn@4.5.1" "packageManager": "yarn@4.6.0"
} }

View file

@ -10,8 +10,7 @@ function _getSelector(target: Element, document: Document, options?: MouseHandle
root: document.body, root: document.body,
seedMinLength: 3, seedMinLength: 3,
optimizedMinLength: options?.minSelectorDepth || 2, optimizedMinLength: options?.minSelectorDepth || 2,
threshold: options?.nthThreshold || 1000, maxNumberOfPathChecks: options?.maxOptimiseTries || 10_000,
maxNumberOfTries: options?.maxOptimiseTries || 10_000,
}) })
return selector return selector

View file

@ -81,8 +81,8 @@ export default function (app: App, opts: Partial<Options> = {}) {
const ignoreHeaders = options.ignoreHeaders const ignoreHeaders = options.ignoreHeaders
const isHIgnored = Array.isArray(ignoreHeaders) const isHIgnored = Array.isArray(ignoreHeaders)
? (name: string) => ignoreHeaders.includes(name) ? (name: string) => ignoreHeaders.includes(name)
: () => ignoreHeaders : () => ignoreHeaders
const stHeader = const stHeader =
options.sessionTokenHeader === true ? 'X-OpenReplay-SessionToken' : options.sessionTokenHeader options.sessionTokenHeader === true ? 'X-OpenReplay-SessionToken' : options.sessionTokenHeader
@ -361,4 +361,4 @@ export default function (app: App, opts: Partial<Options> = {}) {
if (options.captureInIframes) { if (options.captureInIframes) {
app.observer.attachContextCallback(app.safe(patchWindow)) app.observer.attachContextCallback(app.safe(patchWindow))
} }
} }

View file

@ -2,7 +2,7 @@
"extends": "../../tsconfig-base.json", "extends": "../../tsconfig-base.json",
"compilerOptions": { "compilerOptions": {
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"lib": ["es2020", "dom"], "lib": ["es2022", "dom"],
"declaration": true, "declaration": true,
"declarationDir": "../../dist/types", "declarationDir": "../../dist/types",
} }

View file

@ -6,7 +6,7 @@
"strictNullChecks": true, "strictNullChecks": true,
"alwaysStrict": false, "alwaysStrict": false,
"target": "es2020", "target": "es2020",
"lib": ["DOM", "ES2020"], "lib": ["DOM", "ES2022"],
"module": "ES2022", "module": "ES2022",
"moduleResolution": "node", "moduleResolution": "node",
"esModuleInterop": true, "esModuleInterop": true,