Skip to content

Commit 0e30c7c

Browse files
committed
always include headers
1 parent 150460e commit 0e30c7c

File tree

3 files changed

+49
-17
lines changed

3 files changed

+49
-17
lines changed

.changeset/dull-monkeys-matter.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@segment/analytics-signals': patch
3+
---
4+
5+
Always include headers in network interceptor, even if empty

packages/signals/signals/src/core/signal-generators/network-gen/__tests__/network-interceptor.test.ts

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { NetworkInterceptor } from '../network-interceptor'
1+
import {
2+
NetworkInterceptor,
3+
NetworkRequestHandler,
4+
NetworkResponseHandler,
5+
} from '../network-interceptor'
26
import { Response } from 'node-fetch'
37
import { EventEmitter } from 'events'
48

@@ -9,10 +13,11 @@ describe(NetworkInterceptor, () => {
913
interceptor.cleanup()
1014
})
1115

16+
const mockRequestHandler: jest.MockedFn<NetworkRequestHandler> = jest.fn()
17+
const mockResponseHandler: jest.MockedFn<NetworkResponseHandler> = jest.fn()
18+
1219
it('should intercept fetch requests and responses', async () => {
1320
interceptor = new NetworkInterceptor()
14-
const mockRequestHandler = jest.fn()
15-
const mockResponseHandler = jest.fn()
1621
const mockResponse = new Response(JSON.stringify({ data: 'test' }), {
1722
headers: { 'Content-Type': 'application/json' },
1823
})
@@ -51,10 +56,16 @@ describe(NetworkInterceptor, () => {
5156

5257
// Very primitive mock for XMLHttpRequest -- better tests are at the integration level
5358
it('should intercept XHR requests and responses', async () => {
54-
const mockRequestHandler = jest.fn()
55-
const mockResponseHandler = jest.fn()
59+
interface XMLHttpRequestMock {
60+
open: XMLHttpRequest['open']
61+
send: XMLHttpRequest['send']
62+
setRequestHeader: XMLHttpRequest['setRequestHeader']
63+
getAllResponseHeaders: XMLHttpRequest['getAllResponseHeaders']
64+
addEventListener: XMLHttpRequest['addEventListener']
65+
onreadystatechange: XMLHttpRequest['onreadystatechange']
66+
}
5667

57-
class MockXMLHttpRequest {
68+
class MockXMLHttpRequest implements XMLHttpRequestMock {
5869
UNSENT = 0
5970
OPENED = 1
6071
HEADERS_RECEIVED = 2
@@ -66,17 +77,15 @@ describe(NetworkInterceptor, () => {
6677
public status = 0
6778
public responseText = ''
6879
public responseURL = ''
69-
public _responseMethod = ''
70-
public _responseHeaders = ''
71-
public onreadystatechange = () => undefined
80+
private _responseHeaders = ''
81+
public onreadystatechange: () => void = () => undefined
7282
constructor() {
7383
this._emitter = new EventEmitter().on('readystatechange', () => {
7484
this.onreadystatechange()
7585
})
7686
}
7787

78-
open(method: string, url: string) {
79-
this._responseMethod = method
88+
open(_method: string, url: string) {
8089
this.responseURL = url
8190
}
8291

@@ -96,14 +105,23 @@ describe(NetworkInterceptor, () => {
96105
this.status = 200
97106
this.responseText = JSON.stringify({ data: 'test' })
98107
this.responseURL = 'http://example.com'
99-
this._responseHeaders = 'Content-Type: application/json'
108+
this._responseHeaders =
109+
[
110+
'content-type: application/json; charset=utf-8',
111+
'cache-control: max-age=3600',
112+
'x-content-type-options: nosniff',
113+
'date: Mon, 18 Nov 2000 12:00:00 GMT',
114+
].join('\r\n') + '\r\n' // trailing CRLF to be realistic
115+
100116
this._emitter.emit('readystatechange')
101117
}, 40)
102118
}
103119

104-
setRequestHeader = jest.fn()
120+
setRequestHeader() {
121+
// no-op
122+
}
105123

106-
addEventListener(event: string, listener: () => void) {
124+
addEventListener(event: string, listener: (ev: any) => void) {
107125
this._emitter.on(event, listener)
108126
}
109127

@@ -123,15 +141,24 @@ describe(NetworkInterceptor, () => {
123141

124142
const xhr = new XMLHttpRequest()
125143
xhr.open('POST', 'http://example.com')
144+
xhr.setRequestHeader('accept', 'application/json')
145+
xhr.setRequestHeader('x-something-else', 'foo')
126146
xhr.send()
127147

128148
await new Promise((resolve) => setTimeout(resolve, 100))
129149

130150
expect(mockRequestHandler).toHaveBeenCalled()
151+
const request = mockRequestHandler.mock.calls[0][0]
152+
expect(request.headers).toBeInstanceOf(Headers)
153+
expect(request.headers!.get('accept')).toBe('application/json')
154+
expect(request.headers!.get('x-something-else')).toBe('foo')
131155
expect(mockResponseHandler).toHaveBeenCalled()
132156
const response = mockResponseHandler.mock.calls[0][0]
133157
expect(response.headers).toBeInstanceOf(Headers)
134-
expect(response.headers.get('content-type')).toBe('application/json')
158+
expect(response.headers.get('content-type')).toBe(
159+
'application/json; charset=utf-8'
160+
)
161+
expect(response.headers.get('date')).toBe('Mon, 18 Nov 2000 12:00:00 GMT')
135162
expect(response.url).toBe('http://example.com')
136163
expect(response.status).toBe(200)
137164
})

packages/signals/signals/src/core/signal-generators/network-gen/network-interceptor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export interface NetworkInterceptorRequest {
2828
method: HTTPMethod
2929
contentType: string | undefined
3030
body: string | undefined
31-
headers: Headers | undefined
31+
headers: Headers
3232
id: string
3333
}
3434

@@ -61,7 +61,7 @@ const createInterceptorRequest = ({
6161
}): NetworkInterceptorRequest => ({
6262
url: url.toString(),
6363
method: method,
64-
headers,
64+
headers: headers ?? new Headers(),
6565
contentType: headers?.get('content-type') ?? undefined,
6666
body: typeof body == 'string' ? body : undefined,
6767
id,

0 commit comments

Comments
 (0)