feat(tracker-fetch): capture headers
This commit is contained in:
parent
577d15dab8
commit
d6914cc3c8
4 changed files with 68 additions and 17 deletions
|
|
@ -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' ]`.
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
"module": "es6",
|
||||
"moduleResolution": "node",
|
||||
"declaration": true,
|
||||
"outDir": "./lib"
|
||||
"outDir": "./lib",
|
||||
"lib": ["es6", "dom", "es2017"]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue