From 394b865676457181c1e3d346ee6516ec51ede94a Mon Sep 17 00:00:00 2001 From: John Pham Date: Mon, 24 Jan 2022 16:53:48 -0800 Subject: [PATCH] Support loading CORS fonts through our proxy (#59) --- package.json | 2 +- src/snapshot/rebuild.ts | 43 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 23c2ccbd..2322557a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@highlight-run/rrweb", - "version": "1.1.5", + "version": "1.1.6", "description": "record and replay the web", "scripts": { "test": "npm run bundle:browser && cross-env TS_NODE_CACHE=false TS_NODE_FILES=true mocha -r ts-node/register -r ignore-styles -r jsdom-global/register test/**.test.ts", diff --git a/src/snapshot/rebuild.ts b/src/snapshot/rebuild.ts index 74a1e4d8..bf484dd9 100644 --- a/src/snapshot/rebuild.ts +++ b/src/snapshot/rebuild.ts @@ -165,7 +165,50 @@ function buildNode( tagName === 'style' && name === '_cssText'; if (isRemoteOrDynamicCss && hackCss) { value = addHoverClass(value, cache); + + /** Start of Highlight */ + /** + * Find all remote fonts in the style tag. + * We need to find and replace the URLs with a proxy URL so we can bypass CORS. + */ + if (typeof value === 'string') { + const regex = /url\(\"https:\/\/\S*(.eot|.woff2|.ttf|.woff)\S*\"\)/gm; + let m; + const fontUrls: { originalUrl: string; proxyUrl: string }[] = []; + + const PROXY_URL = 'https://replay-cors-proxy.highlightrun.workers.dev' as const; + while ((m = regex.exec(value)) !== null) { + // This is necessary to avoid infinite loops with zero-width matches + if (m.index === regex.lastIndex) { + regex.lastIndex++; + } + + // The result can be accessed through the `m`-variable. + m.forEach((match, groupIndex) => { + if (groupIndex === 0) { + // Trim the start and end + // example: url("https://app.boardgent.com/fonts/MaterialIcons-Regular.53354891.woff2") + // gets trimmed to https://app.boardgent.com/fonts/MaterialIcons-Regular.53354891.woff2 + const url = match.slice(5, match.length - 2); + + fontUrls.push({ + originalUrl: url, + proxyUrl: url.replace(url, `${PROXY_URL}?url=${url}`), + }); + } + }); + } + + // Replace all references to the old URL to our proxy URL in the stylesheet. + fontUrls.forEach((urlPair) => { + value = (value as string).replace( + urlPair.originalUrl, + urlPair.proxyUrl, + ); + }); + } } + /** End of Highlight */ if (isTextarea || isRemoteOrDynamicCss) { const child = doc.createTextNode(value); // https://github.com/rrweb-io/rrweb/issues/112