Skip to content

Commit fedb54c

Browse files
committed
feat(evlog): allow to configure request credentials in browser drain
1 parent 633ace7 commit fedb54c

3 files changed

Lines changed: 15 additions & 3 deletions

File tree

apps/docs/content/4.adapters/11.browser.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ const drain = pipeline(transport)
9090
| `headers` | - | Custom headers sent with each `fetch` request (e.g. `Authorization`, `X-API-Key`) |
9191
| `timeout` | `5000` | Request timeout in milliseconds |
9292
| `useBeacon` | `true` | Use `sendBeacon` when the page is hidden |
93+
| `credentials` | `'same-origin'` | Fetch credentials mode (`'omit'`, `'same-origin'`, `'include'`). Set to `'include'` for cross-origin endpoints |
9394

9495
### `BrowserLogDrainOptions`
9596

@@ -123,7 +124,7 @@ const drain = createBrowserLogDrain({
123124
```
124125

125126
::callout{icon="i-lucide-shield-alert" color="warning"}
126-
`headers` are applied to `fetch` requests only. The `sendBeacon` API does not support custom headers, so when the page is hidden and `sendBeacon` is used, headers are not sent. If your endpoint requires authentication, consider validating via a session cookie (`credentials: 'same-origin'` is set by default) or disable `sendBeacon` with `useBeacon: false`.
127+
`headers` are applied to `fetch` requests only. The `sendBeacon` API does not support custom headers, so when the page is hidden and `sendBeacon` is used, headers are not sent. If your endpoint requires authentication, consider validating via a session cookie (set `credentials: 'include'` for cross-origin endpoints, defaults to `'same-origin'`) or disable `sendBeacon` with `useBeacon: false`.
127128
::
128129

129130
## Server Endpoint

packages/evlog/src/browser.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ export interface BrowserDrainConfig {
1111
timeout?: number
1212
/** Use sendBeacon when the page is hidden. @default true */
1313
useBeacon?: boolean
14+
/** Fetch credentials mode. @default 'same-origin' */
15+
credentials?: RequestCredentials
1416
}
1517

1618
export interface BrowserLogDrainOptions {
@@ -39,7 +41,7 @@ export interface BrowserLogDrainOptions {
3941
* ```
4042
*/
4143
export function createBrowserDrain(config: BrowserDrainConfig): (batch: DrainContext[]) => Promise<void> {
42-
const { endpoint, headers: customHeaders, timeout = 5000, useBeacon = true } = config
44+
const { endpoint, headers: customHeaders, timeout = 5000, useBeacon = true, credentials = 'same-origin' } = config
4345

4446
return async (batch: DrainContext[]): Promise<void> => {
4547
if (batch.length === 0) return
@@ -70,7 +72,7 @@ export function createBrowserDrain(config: BrowserDrainConfig): (batch: DrainCon
7072
body,
7173
signal: controller.signal,
7274
keepalive: true,
73-
credentials: 'same-origin',
75+
credentials,
7476
})
7577

7678
if (!response.ok) {

packages/evlog/test/browser.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ describe('createBrowserDrain', () => {
5858
})
5959
})
6060

61+
it('uses custom credentials mode', async () => {
62+
const drain = createBrowserDrain({ endpoint: '/api/logs', credentials: 'include' })
63+
64+
await drain([createTestContext(1)])
65+
66+
const [, options] = vi.mocked(fetch).mock.calls[0]!
67+
expect(options?.credentials).toBe('include')
68+
})
69+
6170
it('skips empty batches', async () => {
6271
const drain = createBrowserDrain({ endpoint: '/api/logs' })
6372

0 commit comments

Comments
 (0)