Skip to content

Commit 6fff411

Browse files
authored
Remove content type restriction for signals requests (#1181)
1 parent 75ed6a8 commit 6fff411

File tree

10 files changed

+85
-65
lines changed

10 files changed

+85
-65
lines changed

.changeset/spotty-apes-matter.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@segment/analytics-signals': minor
3+
'@segment/analytics-signals-runtime': minor
4+
---
5+
6+
Add HTTPMethods. Do not gate requests based on content-type.

packages/signals/signals-integration-tests/src/tests/signals-vanilla/network-signals-fetch.test.ts

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ test.describe('network signals - fetch', () => {
1010
indexPage = await new IndexPage().loadAndWait(page, basicEdgeFn)
1111
})
1212

13-
test('should not emit non-json requests', async () => {
13+
test('should emit non-json requests but not include the data object', async () => {
1414
await indexPage.network.mockTestRoute('http://localhost/upload', {
1515
body: JSON.stringify({ foo: 'test' }),
1616
})
@@ -26,10 +26,16 @@ test.describe('network signals - fetch', () => {
2626
(el) => el.properties!.data.action === 'request'
2727
)
2828

29-
expect(requests).toHaveLength(0)
29+
expect(requests[0].properties!.data).toMatchObject({
30+
action: 'request',
31+
contentType: 'multipart/form-data',
32+
data: null,
33+
method: 'POST',
34+
url: 'http://localhost/upload',
35+
})
3036
})
3137

32-
test('should try to parse the body of text/plain requests', async () => {
38+
test('should try to parse the body of any requests with string in the body', async () => {
3339
await indexPage.network.mockTestRoute('http://localhost/test', {
3440
body: JSON.stringify({ foo: 'test' }),
3541
contentType: 'application/json',
@@ -251,19 +257,4 @@ test.describe('network signals - fetch', () => {
251257
expect(responses).toHaveLength(1)
252258
})
253259
})
254-
255-
test('not emit response errors if there is no corresponding request, even if correct content type', async () => {
256-
await indexPage.network.mockTestRoute('http://localhost/test', {
257-
body: JSON.stringify({ foo: 'test' }),
258-
contentType: 'application/json',
259-
status: 400,
260-
})
261-
262-
await indexPage.network.makeFileUploadRequest('http://localhost/test')
263-
264-
await indexPage.waitForSignalsApiFlush()
265-
266-
const networkEvents = indexPage.signalsAPI.getEvents('network')
267-
expect(networkEvents).toHaveLength(0)
268-
})
269260
})

packages/signals/signals-runtime/src/web/web-signals-types.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ interface BaseNetworkData {
7575
interface NetworkRequestData extends BaseNetworkData {
7676
action: 'request'
7777
url: string
78-
method: string
78+
method: HTTPMethod
7979
}
8080

8181
interface NetworkResponseData extends BaseNetworkData {
@@ -85,6 +85,15 @@ interface NetworkResponseData extends BaseNetworkData {
8585
ok: boolean
8686
}
8787

88+
export type HTTPMethod =
89+
| 'GET'
90+
| 'POST'
91+
| 'PUT'
92+
| 'DELETE'
93+
| 'PATCH'
94+
| 'HEAD'
95+
| 'OPTIONS'
96+
8897
export type NetworkData = NetworkRequestData | NetworkResponseData
8998

9099
export type NetworkSignal = RawSignal<'network', NetworkData>

packages/signals/signals/src/core/client/__tests__/client.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ describe(SignalsIngestClient, () => {
4949
data: {
5050
hello: 'how are you',
5151
},
52-
method: 'post',
52+
method: 'POST',
5353
url: 'http://foo.com',
5454
},
5555
})
@@ -63,7 +63,7 @@ describe(SignalsIngestClient, () => {
6363
"data": {
6464
"hello": "XXX",
6565
},
66-
"method": "post",
66+
"method": "POST",
6767
"url": "http://foo.com",
6868
}
6969
`)

packages/signals/signals/src/core/client/__tests__/redact.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ describe(redactSignalData, () => {
9393
{
9494
contentType: 'application/json',
9595
action: 'request',
96-
method: 'post',
96+
method: 'POST',
9797
url: 'http://foo.com',
9898
data: { name: 'John Doe', age: 30 },
9999
},
@@ -103,7 +103,7 @@ describe(redactSignalData, () => {
103103
{
104104
contentType: 'application/json',
105105
action: 'request',
106-
method: 'post',
106+
method: 'POST',
107107
url: 'http://foo.com',
108108
data: { name: 'XXX', age: 999 },
109109
},

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

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { SignalEmitter } from '../../../emitter'
77
import { Response } from 'node-fetch'
88
import { sleep } from '@internal/test-helpers'
99
import { setLocation } from '../../../../test-helpers/set-location'
10+
import { NetworkSignal } from '@segment/analytics-signals-runtime'
1011

1112
// xhr tests are in integration tests
1213
describe(NetworkGenerator, () => {
@@ -126,43 +127,54 @@ describe(NetworkGenerator, () => {
126127
unregister()
127128
})
128129

129-
it('should emit response signal but not request signal if content-type for request is not recognized ', async () => {
130+
it('should emit response signal and request signal, regardless of content type', async () => {
130131
const mockEmitter = { emit: jest.fn() }
131132
const networkGenerator = new TestNetworkGenerator()
132133
const unregister = networkGenerator.register(
133134
mockEmitter as unknown as SignalEmitter
134135
)
135136

136137
await window.fetch(`/api`, {
137-
method: 'GET',
138+
method: 'POST',
138139
headers: { 'content-type': 'text/html' },
139140
body: 'hello world',
140141
})
141142

142143
await sleep(100)
143-
expect(mockEmitter.emit.mock.calls).toMatchInlineSnapshot(`
144+
expect(
145+
mockEmitter.emit.mock.calls.flatMap((call) =>
146+
call.map((s: NetworkSignal) => s.data.action)
147+
)
148+
).toMatchInlineSnapshot(`
144149
[
145-
[
146-
{
147-
"data": {
148-
"action": "response",
149-
"contentType": "application/json",
150-
"data": {
151-
"data": "test",
152-
},
153-
"ok": true,
154-
"status": 200,
155-
"url": "http://localhost/api",
156-
},
157-
"metadata": {
158-
"filters": {
159-
"allowed": [],
160-
"disallowed": [],
161-
},
162-
},
163-
"type": "network",
164-
},
165-
],
150+
"request",
151+
"response",
152+
]
153+
`)
154+
155+
unregister()
156+
})
157+
158+
it('should emit response signal and request signal if no content-type', async () => {
159+
const mockEmitter = { emit: jest.fn() }
160+
const networkGenerator = new TestNetworkGenerator()
161+
const unregister = networkGenerator.register(
162+
mockEmitter as unknown as SignalEmitter
163+
)
164+
165+
await window.fetch(`/some-data?foo=123`, {
166+
method: 'GET',
167+
})
168+
169+
await sleep(100)
170+
expect(
171+
mockEmitter.emit.mock.calls.flatMap((call) =>
172+
call.map((s: NetworkSignal) => s.data.action)
173+
)
174+
).toMatchInlineSnapshot(`
175+
[
176+
"request",
177+
"response",
166178
]
167179
`)
168180

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

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@ import {
1212
NetworkRequestHandler,
1313
NetworkResponseHandler,
1414
} from './network-interceptor'
15-
import {
16-
containsJSONContentType,
17-
containsJSONParseableContentType,
18-
tryJSONParse,
19-
} from './helpers'
15+
import { containsJSONContentType, tryJSONParse } from './helpers'
2016

2117
export type NetworkSettingsConfigSettings = Pick<
2218
SignalsSettingsConfig,
@@ -58,10 +54,6 @@ export class NetworkGenerator implements SignalGenerator {
5854
})
5955

6056
const handleRequest: NetworkRequestHandler = (rq) => {
61-
if (!containsJSONParseableContentType(rq.headers)) {
62-
return
63-
}
64-
6557
if (!rq.url || !this.filter.isAllowed(rq.url)) {
6658
return
6759
}

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

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,22 @@ import {
1010
let origFetch: typeof window.fetch
1111
let origXMLHttpRequest: typeof XMLHttpRequest
1212

13+
export type HTTPMethod =
14+
| 'GET'
15+
| 'POST'
16+
| 'PUT'
17+
| 'DELETE'
18+
| 'PATCH'
19+
| 'HEAD'
20+
| 'OPTIONS'
21+
22+
const toHTTPMethod = (method: string): HTTPMethod => {
23+
return method.toUpperCase() as HTTPMethod
24+
}
25+
1326
export interface NetworkInterceptorRequest {
1427
url: string
15-
method: string
28+
method: HTTPMethod
1629
contentType: string | undefined
1730
body: string | undefined
1831
headers: Headers | undefined
@@ -42,7 +55,7 @@ const createInterceptorRequest = ({
4255
}: {
4356
url: URL | string
4457
body: string | undefined
45-
method: string
58+
method: HTTPMethod
4659
headers: Headers | undefined
4760
id: string
4861
}): NetworkInterceptorRequest => ({
@@ -130,7 +143,7 @@ export class NetworkInterceptor {
130143
createInterceptorRequest({
131144
url: normalizedURL,
132145
body: typeof options?.body == 'string' ? options.body : undefined,
133-
method: options?.method ?? 'GET',
146+
method: options?.method ? toHTTPMethod(options.method) : 'GET',
134147
headers,
135148
id,
136149
})
@@ -185,7 +198,7 @@ export class NetworkInterceptor {
185198
const OrigXMLHttpRequest = window.XMLHttpRequest
186199
class InterceptedXMLHttpRequest extends OrigXMLHttpRequest {
187200
_reqURL?: string
188-
_reqMethod?: string
201+
_reqMethod?: HTTPMethod
189202
_reqBody?: XMLHttpRequestBodyInit
190203
_reqHeaders?: Headers
191204
_reqId = createRequestId()
@@ -263,7 +276,7 @@ export class NetworkInterceptor {
263276
const [method, url] = args
264277
try {
265278
this._reqURL = url.toString()
266-
this._reqMethod = method
279+
this._reqMethod = toHTTPMethod(method)
267280
} catch (err) {
268281
console.log('Error handling request (open)', err)
269282
}

packages/signals/signals/src/types/__tests__/create-network-signal.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe(createNetworkSignal, () => {
2121
const data: NetworkData = {
2222
action: 'request',
2323
url: 'http://example.com',
24-
method: 'post',
24+
method: 'POST',
2525
data: { key: 'value' },
2626
contentType: 'application/json',
2727
}

packages/signals/signals/src/types/factories.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ export const createNetworkSignal = (
6565
data: {
6666
...data,
6767
url: normalizeUrl(data.url),
68-
...(data.action === 'request'
69-
? { method: data.method.toUpperCase() }
70-
: {}),
7168
},
7269
metadata: metadata,
7370
}

0 commit comments

Comments
 (0)