feat(tracker-fetch): capture headers

This commit is contained in:
ShiKhu 2021-10-01 19:42:08 +02:00
parent 577d15dab8
commit d6914cc3c8
4 changed files with 68 additions and 17 deletions

View file

@ -1,7 +1,7 @@
# OpenReplay Tracker Fetch plugin
Tracker plugin to support tracking of the `fetch` requests payload.
Additionally it populates the requests with `sessionID` header for backend logging.
Additionally it populates the requests with `sessionToken` header for backend logging.
## Installation
@ -23,13 +23,24 @@ const tracker = new Tracker({
});
tracker.start();
export const fetch = tracker.use(trackerFetch({
sessionTokenHeader: 'X-Session-ID', // optional
failuresOnly: true //optional
}));
export const fetch = tracker.use(trackerFetch({ /* options here*/ }));
fetch('https://my.api.io/resource').then(response => response.json()).then(body => console.log(body));
```
In case you use OpenReplay integrations (sentry, bugsnag or others), you can use `sessionTokenHeader` option to specify the header name. This header will be appended automatically to the each fetch request and will contain OpenReplay session identificator value.
Set `failuresOnly` option to `true` if you want to record only requests with the status code >= 400.
Options:
```ts
{
failuresOnly: boolean, // default false
sessionTokenHeader: string | undefined, // default undefined
ingoreHeaders: Array<string> | boolean, // default [ 'Cookie', 'Set-Cookie', 'Authorization' ]
}
```
Set `failuresOnly` option to `true` if you want to record only requests with the status code >= 400.
In case you use [OpenReplay integrations (sentry, bugsnag or others)](https://docs.openreplay.com/integrations), you can use `sessionTokenHeader` option to specify the header name. This header will be appended automatically to the each fetch request and will contain OpenReplay session identificator value.
You can define list of headers that you don't want to capture with the `ingoreHeaders` options. Set its value to `false` if you want to catch them all (`true` if opposite). By default plugin ignores the list of headers that might be sensetive such as `[ 'Cookie', 'Set-Cookie', 'Authorization' ]`.

View file

@ -1,7 +1,7 @@
{
"name": "@openreplay/tracker-fetch",
"description": "Tracker plugin for fetch requests recording ",
"version": "3.0.0",
"version": "3.4.0",
"keywords": [
"fetch",
"logging",

View file

@ -2,13 +2,17 @@ import { App, Messages } from '@openreplay/tracker';
export interface Options {
sessionTokenHeader?: string;
failuresOnly?: boolean;
replaceDefault: boolean; // overrideDefault ?
failuresOnly: boolean;
ingoreHeaders: Array<string> | boolean;
}
export default function(opts: Partial<Options> = {}) {
const options: Options = Object.assign(
{
replaceDefault: false,
failuresOnly: false,
ingoreHeaders: [ 'Cookie', 'Set-Cookie', 'Authorization' ],
},
opts,
);
@ -18,7 +22,12 @@ export default function(opts: Partial<Options> = {}) {
return window.fetch;
}
return async (input: RequestInfo, init: RequestInit = {}) => {
const ihOpt = options.ingoreHeaders
const isHIgnoring = Array.isArray(ihOpt)
? name => ihOpt.includes(name)
: () => ihOpt
const fetch = async (input: RequestInfo, init: RequestInit = {}) => {
if (typeof input !== 'string') {
return window.fetch(input, init);
}
@ -44,20 +53,50 @@ export default function(opts: Partial<Options> = {}) {
return response
}
const r = response.clone();
r.text().then(text =>
r.text().then(text => {
const reqHs: Record<string, string> = {}
const resHs: Record<string, string> = {}
if (ihOpt !== true) {
function writeReqHeader([n, v]) {
if (!isHIgnoring(n)) { reqHs[n] = v }
}
if (init.headers instanceof Headers) {
init.headers.forEach((v, n) => writeReqHeader([n, v]))
} else if (Array.isArray(init.headers)) {
init.headers.forEach(writeReqHeader);
} else if (typeof init.headers === 'object') {
Object.entries(init.headers).forEach(writeReqHeader)
}
r.headers.forEach((v, n) => { if (!isHIgnoring(n)) resHs[n] = v })
}
const req = JSON.stringify({
headers: reqHs,
body: typeof init.body === 'string' ? init.body : '',
})
const res = JSON.stringify({
headers: resHs,
body: text,
})
app.send(
Messages.Fetch(
typeof init.method === 'string' ? init.method : 'GET',
typeof init.method === 'string' ? init.method.toUpperCase() : 'GET',
input,
typeof init.body === 'string' ? init.body : '',
text,
req,
res,
r.status,
startTime + performance.timing.navigationStart,
duration,
),
),
);
)
});
return response;
};
if (options.replaceDefault) {
window.fetch = fetch
}
return fetch;
};
}

View file

@ -7,6 +7,7 @@
"module": "es6",
"moduleResolution": "node",
"declaration": true,
"outDir": "./lib"
"outDir": "./lib",
"lib": ["es6", "dom", "es2017"]
}
}