@openreplay/tracker 9.0.4 → 9.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/cjs/app/index.js +9 -2
- package/cjs/index.js +1 -1
- package/cjs/modules/Network/fetchProxy.d.ts +3 -2
- package/cjs/modules/Network/fetchProxy.js +13 -4
- package/cjs/modules/Network/index.d.ts +1 -1
- package/cjs/modules/Network/index.js +3 -3
- package/cjs/modules/Network/xhrProxy.d.ts +3 -2
- package/cjs/modules/Network/xhrProxy.js +9 -3
- package/cjs/modules/network.d.ts +1 -0
- package/cjs/modules/network.js +1 -1
- package/lib/app/index.js +9 -2
- package/lib/index.js +1 -1
- package/lib/modules/Network/fetchProxy.d.ts +3 -2
- package/lib/modules/Network/fetchProxy.js +13 -4
- package/lib/modules/Network/index.d.ts +1 -1
- package/lib/modules/Network/index.js +3 -3
- package/lib/modules/Network/xhrProxy.d.ts +3 -2
- package/lib/modules/Network/xhrProxy.js +9 -3
- package/lib/modules/network.d.ts +1 -0
- package/lib/modules/network.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/cjs/app/index.js
CHANGED
|
@@ -24,6 +24,13 @@ var ActivityState;
|
|
|
24
24
|
})(ActivityState || (ActivityState = {}));
|
|
25
25
|
// TODO: use backendHost only
|
|
26
26
|
exports.DEFAULT_INGEST_POINT = 'https://api.openreplay.com/ingest';
|
|
27
|
+
function getTimezone() {
|
|
28
|
+
const offset = new Date().getTimezoneOffset() * -1;
|
|
29
|
+
const sign = offset >= 0 ? '+' : '-';
|
|
30
|
+
const hours = Math.floor(Math.abs(offset) / 60);
|
|
31
|
+
const minutes = Math.abs(offset) % 60;
|
|
32
|
+
return `UTC${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
|
|
33
|
+
}
|
|
27
34
|
class App {
|
|
28
35
|
constructor(projectKey, sessionToken, options) {
|
|
29
36
|
// if (options.onStart !== undefined) {
|
|
@@ -35,7 +42,7 @@ class App {
|
|
|
35
42
|
this.stopCallbacks = [];
|
|
36
43
|
this.commitCallbacks = [];
|
|
37
44
|
this.activityState = ActivityState.NotActive;
|
|
38
|
-
this.version = '9.0.
|
|
45
|
+
this.version = '9.0.6'; // TODO: version compatability check inside each plugin.
|
|
39
46
|
this.compressionThreshold = 24 * 1000;
|
|
40
47
|
this.restartAttempts = 0;
|
|
41
48
|
this.bc = null;
|
|
@@ -394,7 +401,7 @@ class App {
|
|
|
394
401
|
'Content-Type': 'application/json',
|
|
395
402
|
},
|
|
396
403
|
body: JSON.stringify(Object.assign(Object.assign({}, this.getTrackerInfo()), { timestamp, userID: this.session.getInfo().userID, token: isNewSession ? undefined : sessionToken, deviceMemory: performance_js_1.deviceMemory,
|
|
397
|
-
jsHeapSizeLimit: performance_js_1.jsHeapSizeLimit })),
|
|
404
|
+
jsHeapSizeLimit: performance_js_1.jsHeapSizeLimit, timezone: getTimezone() })),
|
|
398
405
|
})
|
|
399
406
|
.then((r) => {
|
|
400
407
|
if (r.status === 200) {
|
package/cjs/index.js
CHANGED
|
@@ -153,7 +153,7 @@ class API {
|
|
|
153
153
|
// no-cors issue only with text/plain or not-set Content-Type
|
|
154
154
|
// req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
|
155
155
|
req.send(JSON.stringify({
|
|
156
|
-
trackerVersion: '9.0.
|
|
156
|
+
trackerVersion: '9.0.6',
|
|
157
157
|
projectKey: options.projectKey,
|
|
158
158
|
doNotTrack,
|
|
159
159
|
// TODO: add precise reason (an exact API missing)
|
|
@@ -22,7 +22,8 @@ export declare class FetchProxyHandler<T extends typeof fetch> implements ProxyH
|
|
|
22
22
|
private readonly sanitize;
|
|
23
23
|
private readonly sendMessage;
|
|
24
24
|
private readonly isServiceUrl;
|
|
25
|
-
|
|
25
|
+
private readonly tokenUrlMatcher?;
|
|
26
|
+
constructor(ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (item: NetworkRequest) => void, isServiceUrl: (url: string) => boolean, tokenUrlMatcher?: ((url: string) => boolean) | undefined);
|
|
26
27
|
apply(target: T, _: typeof window, argsList: [RequestInfo | URL, RequestInit]): any;
|
|
27
28
|
protected beforeFetch(item: NetworkMessage, input: RequestInfo, init?: RequestInit): void;
|
|
28
29
|
protected afterFetch(item: NetworkMessage): (resp: Response) => Response;
|
|
@@ -30,5 +31,5 @@ export declare class FetchProxyHandler<T extends typeof fetch> implements ProxyH
|
|
|
30
31
|
}
|
|
31
32
|
export default class FetchProxy {
|
|
32
33
|
static origFetch: typeof fetch;
|
|
33
|
-
static create(ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (item: NetworkRequest) => void, isServiceUrl: (url: string) => boolean): typeof fetch;
|
|
34
|
+
static create(ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (item: NetworkRequest) => void, isServiceUrl: (url: string) => boolean, tokenUrlMatcher?: (url: string) => boolean): typeof fetch;
|
|
34
35
|
}
|
|
@@ -106,12 +106,13 @@ class ResponseProxyHandler {
|
|
|
106
106
|
}
|
|
107
107
|
exports.ResponseProxyHandler = ResponseProxyHandler;
|
|
108
108
|
class FetchProxyHandler {
|
|
109
|
-
constructor(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl) {
|
|
109
|
+
constructor(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher) {
|
|
110
110
|
this.ignoredHeaders = ignoredHeaders;
|
|
111
111
|
this.setSessionTokenHeader = setSessionTokenHeader;
|
|
112
112
|
this.sanitize = sanitize;
|
|
113
113
|
this.sendMessage = sendMessage;
|
|
114
114
|
this.isServiceUrl = isServiceUrl;
|
|
115
|
+
this.tokenUrlMatcher = tokenUrlMatcher;
|
|
115
116
|
}
|
|
116
117
|
apply(target, _, argsList) {
|
|
117
118
|
const input = argsList[0];
|
|
@@ -125,12 +126,19 @@ class FetchProxyHandler {
|
|
|
125
126
|
const item = new networkMessage_js_1.default(this.ignoredHeaders, this.setSessionTokenHeader, this.sanitize);
|
|
126
127
|
this.beforeFetch(item, input, init);
|
|
127
128
|
this.setSessionTokenHeader((name, value) => {
|
|
129
|
+
if (this.tokenUrlMatcher !== undefined) {
|
|
130
|
+
if (!this.tokenUrlMatcher(item.url)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
128
134
|
if (argsList[1] === undefined && argsList[0] instanceof Request) {
|
|
129
135
|
return argsList[0].headers.append(name, value);
|
|
130
136
|
}
|
|
131
137
|
else {
|
|
138
|
+
if (!argsList[1])
|
|
139
|
+
argsList[1] = {};
|
|
132
140
|
if (argsList[1].headers === undefined) {
|
|
133
|
-
argsList[1]
|
|
141
|
+
argsList[1] = Object.assign(Object.assign({}, argsList[1]), { headers: {} });
|
|
134
142
|
}
|
|
135
143
|
if (argsList[1].headers instanceof Headers) {
|
|
136
144
|
argsList[1].headers.append(name, value);
|
|
@@ -139,6 +147,7 @@ class FetchProxyHandler {
|
|
|
139
147
|
argsList[1].headers.push([name, value]);
|
|
140
148
|
}
|
|
141
149
|
else {
|
|
150
|
+
// @ts-ignore
|
|
142
151
|
argsList[1].headers[name] = value;
|
|
143
152
|
}
|
|
144
153
|
}
|
|
@@ -253,8 +262,8 @@ class FetchProxyHandler {
|
|
|
253
262
|
}
|
|
254
263
|
exports.FetchProxyHandler = FetchProxyHandler;
|
|
255
264
|
class FetchProxy {
|
|
256
|
-
static create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl) {
|
|
257
|
-
return new Proxy(fetch, new FetchProxyHandler(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl));
|
|
265
|
+
static create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher) {
|
|
266
|
+
return new Proxy(fetch, new FetchProxyHandler(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher));
|
|
258
267
|
}
|
|
259
268
|
}
|
|
260
269
|
exports.default = FetchProxy;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { RequestResponseData } from './types.js';
|
|
2
2
|
import { NetworkRequest } from '../../common/messages.gen.js';
|
|
3
|
-
export default function setProxy(context: typeof globalThis, ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (message: NetworkRequest) => void, isServiceUrl: (url: string) => boolean): void;
|
|
3
|
+
export default function setProxy(context: typeof globalThis, ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (message: NetworkRequest) => void, isServiceUrl: (url: string) => boolean, tokenUrlMatcher?: (url: string) => boolean): void;
|
|
@@ -4,15 +4,15 @@ const fetchProxy_js_1 = require("./fetchProxy.js");
|
|
|
4
4
|
const xhrProxy_js_1 = require("./xhrProxy.js");
|
|
5
5
|
const getWarning = (api) => console.warn(`Openreplay: Can't find ${api} in global context.
|
|
6
6
|
If you're using serverside rendering in your app, make sure that tracker is loaded dynamically, otherwise ${api} won't be tracked.`);
|
|
7
|
-
function setProxy(context, ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl) {
|
|
7
|
+
function setProxy(context, ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher) {
|
|
8
8
|
if (context.XMLHttpRequest) {
|
|
9
|
-
context.XMLHttpRequest = xhrProxy_js_1.default.create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl);
|
|
9
|
+
context.XMLHttpRequest = xhrProxy_js_1.default.create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher);
|
|
10
10
|
}
|
|
11
11
|
else {
|
|
12
12
|
getWarning('XMLHttpRequest');
|
|
13
13
|
}
|
|
14
14
|
if (context.fetch) {
|
|
15
|
-
context.fetch = fetchProxy_js_1.default.create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl);
|
|
15
|
+
context.fetch = fetchProxy_js_1.default.create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher);
|
|
16
16
|
}
|
|
17
17
|
else {
|
|
18
18
|
getWarning('fetch');
|
|
@@ -14,9 +14,10 @@ export declare class XHRProxyHandler<T extends XMLHttpRequest> implements ProxyH
|
|
|
14
14
|
private readonly sanitize;
|
|
15
15
|
private readonly sendMessage;
|
|
16
16
|
private readonly isServiceUrl;
|
|
17
|
+
private readonly tokenUrlMatcher?;
|
|
17
18
|
XMLReq: XMLHttpRequest;
|
|
18
19
|
item: NetworkMessage;
|
|
19
|
-
constructor(XMLReq: XMLHttpRequest, ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (message: NetworkRequest) => void, isServiceUrl: (url: string) => boolean);
|
|
20
|
+
constructor(XMLReq: XMLHttpRequest, ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (message: NetworkRequest) => void, isServiceUrl: (url: string) => boolean, tokenUrlMatcher?: ((url: string) => boolean) | undefined);
|
|
20
21
|
get(target: T, key: string): any;
|
|
21
22
|
set(target: T, key: string, value: (args: any[]) => any): boolean;
|
|
22
23
|
onReadyStateChange(): void;
|
|
@@ -43,5 +44,5 @@ export default class XHRProxy {
|
|
|
43
44
|
readonly OPENED: number;
|
|
44
45
|
readonly UNSENT: number;
|
|
45
46
|
};
|
|
46
|
-
static create(ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (data: NetworkRequest) => void, isServiceUrl: (url: string) => boolean): any;
|
|
47
|
+
static create(ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (data: NetworkRequest) => void, isServiceUrl: (url: string) => boolean, tokenUrlMatcher?: (url: string) => boolean): any;
|
|
47
48
|
}
|
|
@@ -11,12 +11,13 @@ exports.XHRProxyHandler = void 0;
|
|
|
11
11
|
const networkMessage_js_1 = require("./networkMessage.js");
|
|
12
12
|
const utils_js_1 = require("./utils.js");
|
|
13
13
|
class XHRProxyHandler {
|
|
14
|
-
constructor(XMLReq, ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl) {
|
|
14
|
+
constructor(XMLReq, ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher) {
|
|
15
15
|
this.ignoredHeaders = ignoredHeaders;
|
|
16
16
|
this.setSessionTokenHeader = setSessionTokenHeader;
|
|
17
17
|
this.sanitize = sanitize;
|
|
18
18
|
this.sendMessage = sendMessage;
|
|
19
19
|
this.isServiceUrl = isServiceUrl;
|
|
20
|
+
this.tokenUrlMatcher = tokenUrlMatcher;
|
|
20
21
|
this.XMLReq = XMLReq;
|
|
21
22
|
this.XMLReq.onreadystatechange = () => {
|
|
22
23
|
this.onReadyStateChange();
|
|
@@ -36,6 +37,11 @@ class XHRProxyHandler {
|
|
|
36
37
|
return this.getOpen(target);
|
|
37
38
|
case 'send':
|
|
38
39
|
this.setSessionTokenHeader((name, value) => {
|
|
40
|
+
if (this.tokenUrlMatcher !== undefined) {
|
|
41
|
+
if (!this.tokenUrlMatcher(this.item.url)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
39
45
|
target.setRequestHeader(name, value);
|
|
40
46
|
});
|
|
41
47
|
return this.getSend(target);
|
|
@@ -199,11 +205,11 @@ class XHRProxyHandler {
|
|
|
199
205
|
}
|
|
200
206
|
exports.XHRProxyHandler = XHRProxyHandler;
|
|
201
207
|
class XHRProxy {
|
|
202
|
-
static create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl) {
|
|
208
|
+
static create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher) {
|
|
203
209
|
return new Proxy(XMLHttpRequest, {
|
|
204
210
|
construct(original) {
|
|
205
211
|
const XMLReq = new original();
|
|
206
|
-
return new Proxy(XMLReq, new XHRProxyHandler(XMLReq, ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl));
|
|
212
|
+
return new Proxy(XMLReq, new XHRProxyHandler(XMLReq, ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher));
|
|
207
213
|
},
|
|
208
214
|
});
|
|
209
215
|
}
|
package/cjs/modules/network.d.ts
CHANGED
package/cjs/modules/network.js
CHANGED
|
@@ -76,7 +76,7 @@ function default_1(app, opts = {}) {
|
|
|
76
76
|
const patchWindow = (context) => {
|
|
77
77
|
/* ====== modern way ====== */
|
|
78
78
|
if (options.useProxy) {
|
|
79
|
-
return (0, index_js_1.default)(context, options.ignoreHeaders, setSessionTokenHeader, sanitize, (message) => app.send(message), (url) => app.isServiceURL(url));
|
|
79
|
+
return (0, index_js_1.default)(context, options.ignoreHeaders, setSessionTokenHeader, sanitize, (message) => app.send(message), (url) => app.isServiceURL(url), options.tokenUrlMatcher);
|
|
80
80
|
}
|
|
81
81
|
/* ====== Fetch ====== */
|
|
82
82
|
const origFetch = context.fetch.bind(context);
|
package/lib/app/index.js
CHANGED
|
@@ -21,6 +21,13 @@ var ActivityState;
|
|
|
21
21
|
})(ActivityState || (ActivityState = {}));
|
|
22
22
|
// TODO: use backendHost only
|
|
23
23
|
export const DEFAULT_INGEST_POINT = 'https://api.openreplay.com/ingest';
|
|
24
|
+
function getTimezone() {
|
|
25
|
+
const offset = new Date().getTimezoneOffset() * -1;
|
|
26
|
+
const sign = offset >= 0 ? '+' : '-';
|
|
27
|
+
const hours = Math.floor(Math.abs(offset) / 60);
|
|
28
|
+
const minutes = Math.abs(offset) % 60;
|
|
29
|
+
return `UTC${sign}${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
|
|
30
|
+
}
|
|
24
31
|
export default class App {
|
|
25
32
|
constructor(projectKey, sessionToken, options) {
|
|
26
33
|
// if (options.onStart !== undefined) {
|
|
@@ -32,7 +39,7 @@ export default class App {
|
|
|
32
39
|
this.stopCallbacks = [];
|
|
33
40
|
this.commitCallbacks = [];
|
|
34
41
|
this.activityState = ActivityState.NotActive;
|
|
35
|
-
this.version = '9.0.
|
|
42
|
+
this.version = '9.0.6'; // TODO: version compatability check inside each plugin.
|
|
36
43
|
this.compressionThreshold = 24 * 1000;
|
|
37
44
|
this.restartAttempts = 0;
|
|
38
45
|
this.bc = null;
|
|
@@ -391,7 +398,7 @@ export default class App {
|
|
|
391
398
|
'Content-Type': 'application/json',
|
|
392
399
|
},
|
|
393
400
|
body: JSON.stringify(Object.assign(Object.assign({}, this.getTrackerInfo()), { timestamp, userID: this.session.getInfo().userID, token: isNewSession ? undefined : sessionToken, deviceMemory,
|
|
394
|
-
jsHeapSizeLimit })),
|
|
401
|
+
jsHeapSizeLimit, timezone: getTimezone() })),
|
|
395
402
|
})
|
|
396
403
|
.then((r) => {
|
|
397
404
|
if (r.status === 200) {
|
package/lib/index.js
CHANGED
|
@@ -148,7 +148,7 @@ export default class API {
|
|
|
148
148
|
// no-cors issue only with text/plain or not-set Content-Type
|
|
149
149
|
// req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
|
150
150
|
req.send(JSON.stringify({
|
|
151
|
-
trackerVersion: '9.0.
|
|
151
|
+
trackerVersion: '9.0.6',
|
|
152
152
|
projectKey: options.projectKey,
|
|
153
153
|
doNotTrack,
|
|
154
154
|
// TODO: add precise reason (an exact API missing)
|
|
@@ -22,7 +22,8 @@ export declare class FetchProxyHandler<T extends typeof fetch> implements ProxyH
|
|
|
22
22
|
private readonly sanitize;
|
|
23
23
|
private readonly sendMessage;
|
|
24
24
|
private readonly isServiceUrl;
|
|
25
|
-
|
|
25
|
+
private readonly tokenUrlMatcher?;
|
|
26
|
+
constructor(ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (item: NetworkRequest) => void, isServiceUrl: (url: string) => boolean, tokenUrlMatcher?: ((url: string) => boolean) | undefined);
|
|
26
27
|
apply(target: T, _: typeof window, argsList: [RequestInfo | URL, RequestInit]): any;
|
|
27
28
|
protected beforeFetch(item: NetworkMessage, input: RequestInfo, init?: RequestInit): void;
|
|
28
29
|
protected afterFetch(item: NetworkMessage): (resp: Response) => Response;
|
|
@@ -30,5 +31,5 @@ export declare class FetchProxyHandler<T extends typeof fetch> implements ProxyH
|
|
|
30
31
|
}
|
|
31
32
|
export default class FetchProxy {
|
|
32
33
|
static origFetch: typeof fetch;
|
|
33
|
-
static create(ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (item: NetworkRequest) => void, isServiceUrl: (url: string) => boolean): typeof fetch;
|
|
34
|
+
static create(ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (item: NetworkRequest) => void, isServiceUrl: (url: string) => boolean, tokenUrlMatcher?: (url: string) => boolean): typeof fetch;
|
|
34
35
|
}
|
|
@@ -102,12 +102,13 @@ export class ResponseProxyHandler {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
export class FetchProxyHandler {
|
|
105
|
-
constructor(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl) {
|
|
105
|
+
constructor(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher) {
|
|
106
106
|
this.ignoredHeaders = ignoredHeaders;
|
|
107
107
|
this.setSessionTokenHeader = setSessionTokenHeader;
|
|
108
108
|
this.sanitize = sanitize;
|
|
109
109
|
this.sendMessage = sendMessage;
|
|
110
110
|
this.isServiceUrl = isServiceUrl;
|
|
111
|
+
this.tokenUrlMatcher = tokenUrlMatcher;
|
|
111
112
|
}
|
|
112
113
|
apply(target, _, argsList) {
|
|
113
114
|
const input = argsList[0];
|
|
@@ -121,12 +122,19 @@ export class FetchProxyHandler {
|
|
|
121
122
|
const item = new NetworkMessage(this.ignoredHeaders, this.setSessionTokenHeader, this.sanitize);
|
|
122
123
|
this.beforeFetch(item, input, init);
|
|
123
124
|
this.setSessionTokenHeader((name, value) => {
|
|
125
|
+
if (this.tokenUrlMatcher !== undefined) {
|
|
126
|
+
if (!this.tokenUrlMatcher(item.url)) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
124
130
|
if (argsList[1] === undefined && argsList[0] instanceof Request) {
|
|
125
131
|
return argsList[0].headers.append(name, value);
|
|
126
132
|
}
|
|
127
133
|
else {
|
|
134
|
+
if (!argsList[1])
|
|
135
|
+
argsList[1] = {};
|
|
128
136
|
if (argsList[1].headers === undefined) {
|
|
129
|
-
argsList[1]
|
|
137
|
+
argsList[1] = Object.assign(Object.assign({}, argsList[1]), { headers: {} });
|
|
130
138
|
}
|
|
131
139
|
if (argsList[1].headers instanceof Headers) {
|
|
132
140
|
argsList[1].headers.append(name, value);
|
|
@@ -135,6 +143,7 @@ export class FetchProxyHandler {
|
|
|
135
143
|
argsList[1].headers.push([name, value]);
|
|
136
144
|
}
|
|
137
145
|
else {
|
|
146
|
+
// @ts-ignore
|
|
138
147
|
argsList[1].headers[name] = value;
|
|
139
148
|
}
|
|
140
149
|
}
|
|
@@ -248,8 +257,8 @@ export class FetchProxyHandler {
|
|
|
248
257
|
}
|
|
249
258
|
}
|
|
250
259
|
export default class FetchProxy {
|
|
251
|
-
static create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl) {
|
|
252
|
-
return new Proxy(fetch, new FetchProxyHandler(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl));
|
|
260
|
+
static create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher) {
|
|
261
|
+
return new Proxy(fetch, new FetchProxyHandler(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher));
|
|
253
262
|
}
|
|
254
263
|
}
|
|
255
264
|
FetchProxy.origFetch = fetch;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { RequestResponseData } from './types.js';
|
|
2
2
|
import { NetworkRequest } from '../../common/messages.gen.js';
|
|
3
|
-
export default function setProxy(context: typeof globalThis, ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (message: NetworkRequest) => void, isServiceUrl: (url: string) => boolean): void;
|
|
3
|
+
export default function setProxy(context: typeof globalThis, ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (message: NetworkRequest) => void, isServiceUrl: (url: string) => boolean, tokenUrlMatcher?: (url: string) => boolean): void;
|
|
@@ -2,15 +2,15 @@ import FetchProxy from './fetchProxy.js';
|
|
|
2
2
|
import XHRProxy from './xhrProxy.js';
|
|
3
3
|
const getWarning = (api) => console.warn(`Openreplay: Can't find ${api} in global context.
|
|
4
4
|
If you're using serverside rendering in your app, make sure that tracker is loaded dynamically, otherwise ${api} won't be tracked.`);
|
|
5
|
-
export default function setProxy(context, ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl) {
|
|
5
|
+
export default function setProxy(context, ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher) {
|
|
6
6
|
if (context.XMLHttpRequest) {
|
|
7
|
-
context.XMLHttpRequest = XHRProxy.create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl);
|
|
7
|
+
context.XMLHttpRequest = XHRProxy.create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher);
|
|
8
8
|
}
|
|
9
9
|
else {
|
|
10
10
|
getWarning('XMLHttpRequest');
|
|
11
11
|
}
|
|
12
12
|
if (context.fetch) {
|
|
13
|
-
context.fetch = FetchProxy.create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl);
|
|
13
|
+
context.fetch = FetchProxy.create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher);
|
|
14
14
|
}
|
|
15
15
|
else {
|
|
16
16
|
getWarning('fetch');
|
|
@@ -14,9 +14,10 @@ export declare class XHRProxyHandler<T extends XMLHttpRequest> implements ProxyH
|
|
|
14
14
|
private readonly sanitize;
|
|
15
15
|
private readonly sendMessage;
|
|
16
16
|
private readonly isServiceUrl;
|
|
17
|
+
private readonly tokenUrlMatcher?;
|
|
17
18
|
XMLReq: XMLHttpRequest;
|
|
18
19
|
item: NetworkMessage;
|
|
19
|
-
constructor(XMLReq: XMLHttpRequest, ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (message: NetworkRequest) => void, isServiceUrl: (url: string) => boolean);
|
|
20
|
+
constructor(XMLReq: XMLHttpRequest, ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (message: NetworkRequest) => void, isServiceUrl: (url: string) => boolean, tokenUrlMatcher?: ((url: string) => boolean) | undefined);
|
|
20
21
|
get(target: T, key: string): any;
|
|
21
22
|
set(target: T, key: string, value: (args: any[]) => any): boolean;
|
|
22
23
|
onReadyStateChange(): void;
|
|
@@ -43,5 +44,5 @@ export default class XHRProxy {
|
|
|
43
44
|
readonly OPENED: number;
|
|
44
45
|
readonly UNSENT: number;
|
|
45
46
|
};
|
|
46
|
-
static create(ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (data: NetworkRequest) => void, isServiceUrl: (url: string) => boolean): any;
|
|
47
|
+
static create(ignoredHeaders: boolean | string[], setSessionTokenHeader: (cb: (name: string, value: string) => void) => void, sanitize: (data: RequestResponseData) => RequestResponseData, sendMessage: (data: NetworkRequest) => void, isServiceUrl: (url: string) => boolean, tokenUrlMatcher?: (url: string) => boolean): any;
|
|
47
48
|
}
|
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
import NetworkMessage, { RequestState } from './networkMessage.js';
|
|
9
9
|
import { genGetDataByUrl, formatByteSize, genStringBody, getStringResponseByType } from './utils.js';
|
|
10
10
|
export class XHRProxyHandler {
|
|
11
|
-
constructor(XMLReq, ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl) {
|
|
11
|
+
constructor(XMLReq, ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher) {
|
|
12
12
|
this.ignoredHeaders = ignoredHeaders;
|
|
13
13
|
this.setSessionTokenHeader = setSessionTokenHeader;
|
|
14
14
|
this.sanitize = sanitize;
|
|
15
15
|
this.sendMessage = sendMessage;
|
|
16
16
|
this.isServiceUrl = isServiceUrl;
|
|
17
|
+
this.tokenUrlMatcher = tokenUrlMatcher;
|
|
17
18
|
this.XMLReq = XMLReq;
|
|
18
19
|
this.XMLReq.onreadystatechange = () => {
|
|
19
20
|
this.onReadyStateChange();
|
|
@@ -33,6 +34,11 @@ export class XHRProxyHandler {
|
|
|
33
34
|
return this.getOpen(target);
|
|
34
35
|
case 'send':
|
|
35
36
|
this.setSessionTokenHeader((name, value) => {
|
|
37
|
+
if (this.tokenUrlMatcher !== undefined) {
|
|
38
|
+
if (!this.tokenUrlMatcher(this.item.url)) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
36
42
|
target.setRequestHeader(name, value);
|
|
37
43
|
});
|
|
38
44
|
return this.getSend(target);
|
|
@@ -195,11 +201,11 @@ export class XHRProxyHandler {
|
|
|
195
201
|
}
|
|
196
202
|
}
|
|
197
203
|
export default class XHRProxy {
|
|
198
|
-
static create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl) {
|
|
204
|
+
static create(ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher) {
|
|
199
205
|
return new Proxy(XMLHttpRequest, {
|
|
200
206
|
construct(original) {
|
|
201
207
|
const XMLReq = new original();
|
|
202
|
-
return new Proxy(XMLReq, new XHRProxyHandler(XMLReq, ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl));
|
|
208
|
+
return new Proxy(XMLReq, new XHRProxyHandler(XMLReq, ignoredHeaders, setSessionTokenHeader, sanitize, sendMessage, isServiceUrl, tokenUrlMatcher));
|
|
203
209
|
},
|
|
204
210
|
});
|
|
205
211
|
}
|
package/lib/modules/network.d.ts
CHANGED
package/lib/modules/network.js
CHANGED
|
@@ -74,7 +74,7 @@ export default function (app, opts = {}) {
|
|
|
74
74
|
const patchWindow = (context) => {
|
|
75
75
|
/* ====== modern way ====== */
|
|
76
76
|
if (options.useProxy) {
|
|
77
|
-
return setProxy(context, options.ignoreHeaders, setSessionTokenHeader, sanitize, (message) => app.send(message), (url) => app.isServiceURL(url));
|
|
77
|
+
return setProxy(context, options.ignoreHeaders, setSessionTokenHeader, sanitize, (message) => app.send(message), (url) => app.isServiceURL(url), options.tokenUrlMatcher);
|
|
78
78
|
}
|
|
79
79
|
/* ====== Fetch ====== */
|
|
80
80
|
const origFetch = context.fetch.bind(context);
|