@multiplayer-app/session-recorder-react-native 1.3.14 → 1.3.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24,27 +24,87 @@ function _tryReadFetchBody({
24
24
  }
25
25
  return `[Fetch] Cannot read body of type ${Object.prototype.toString.call(body)}`;
26
26
  }
27
+
28
+ /**
29
+ * Detects if a response is a streaming response that should NOT have its body read.
30
+ * Reading the body of streaming responses (SSE, chunked streams, etc.) will either:
31
+ * - Block forever (SSE streams never end)
32
+ * - Corrupt the stream for the actual consumer
33
+ */
34
+ function _isStreamingResponse(response) {
35
+ const contentType = response.headers.get('content-type')?.toLowerCase() ?? '';
36
+
37
+ // SSE - Server-Sent Events (infinite stream)
38
+ if (contentType.includes('text/event-stream')) {
39
+ return true;
40
+ }
41
+
42
+ // Binary streams that are typically long-running
43
+ if (contentType.includes('application/octet-stream')) {
44
+ return true;
45
+ }
46
+
47
+ // NDJSON streaming (newline-delimited JSON, common in streaming APIs)
48
+ if (contentType.includes('application/x-ndjson') || contentType.includes('application/ndjson')) {
49
+ return true;
50
+ }
51
+
52
+ // gRPC-web streaming
53
+ if (contentType.includes('application/grpc')) {
54
+ return true;
55
+ }
56
+
57
+ // Check for chunked transfer encoding (often indicates streaming)
58
+ const transferEncoding = response.headers.get('transfer-encoding')?.toLowerCase();
59
+ if (transferEncoding?.includes('chunked')) {
60
+ // Chunked alone isn't definitive, but combined with no content-length = streaming
61
+ const contentLength = response.headers.get('content-length');
62
+ if (!contentLength) {
63
+ return true;
64
+ }
65
+ }
66
+ return false;
67
+ }
68
+
69
+ /**
70
+ * Safely reads response body for non-streaming responses.
71
+ * Returns null for streaming responses to avoid blocking/corruption.
72
+ */
27
73
  async function _tryReadResponseBody(response) {
74
+ // CRITICAL: Never attempt to read streaming response bodies
75
+ if (_isStreamingResponse(response)) {
76
+ return null;
77
+ }
28
78
  try {
29
79
  // Clone the response to avoid consuming the original stream.
30
80
  const clonedResponse = response.clone();
31
- const contentType = response.headers.get('content-type') || '';
81
+ const contentType = response.headers.get('content-type')?.toLowerCase() ?? '';
82
+
83
+ // Check content-length to avoid reading massive responses
84
+ const contentLength = response.headers.get('content-length');
85
+ if (contentLength) {
86
+ const length = parseInt(contentLength, 10);
87
+ if (!isNaN(length) && length > configs.maxCapturingHttpPayloadSize) {
88
+ return `[Fetch] Response too large (${length} bytes)`;
89
+ }
90
+ }
32
91
  if (contentType.includes('application/json')) {
33
92
  const json = await clonedResponse.json();
34
93
  return JSON.stringify(json);
35
- } else if (contentType.includes('text/')) {
94
+ }
95
+ if (contentType.includes('text/')) {
36
96
  return await clonedResponse.text();
37
- } else {
38
- // For other content types, try text first, fallback to arrayBuffer
97
+ }
98
+
99
+ // For unknown types, attempt text read
100
+ try {
101
+ return await clonedResponse.text();
102
+ } catch {
39
103
  try {
40
- return await clonedResponse.text();
104
+ const arrayBuffer = await clonedResponse.arrayBuffer();
105
+ return `[Fetch] Binary data (${arrayBuffer.byteLength} bytes)`;
41
106
  } catch {
42
- try {
43
- const arrayBuffer = await clonedResponse.arrayBuffer();
44
- return `[Fetch] Binary data (${arrayBuffer.byteLength} bytes)`;
45
- } catch {
46
- return '[Fetch] Unable to read response body';
47
- }
107
+ return '[Fetch] Unable to read response body';
48
108
  }
49
109
  }
50
110
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"names":["isFormData","isNullish","isObject","isString","formDataToQuery","configs","_tryReadFetchBody","body","JSON","stringify","Object","prototype","toString","call","_tryReadResponseBody","response","clonedResponse","clone","contentType","headers","get","includes","json","text","arrayBuffer","byteLength","error","Error","message","_headersToObject","result","forEach","value","key","_headersInitToObject","headersInit","Headers","Array","isArray","String","toLowerCase","entries","fetch","global","originalFetch","input","init","networkRequest","inputIsRequest","Request","recordRequestHeaders","requestHeaders","shouldRecordBody","candidateBody","requestBody","length","Blob","size","maxCapturingHttpPayloadSize","recordResponseHeaders","responseHeaders","responseBody","setPrototypeOf","defineProperty","console","warn","info"],"sourceRoot":"../../../src","sources":["patch/fetch.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["isFormData","isNullish","isObject","isString","formDataToQuery","configs","_tryReadFetchBody","body","JSON","stringify","Object","prototype","toString","call","_isStreamingResponse","response","contentType","headers","get","toLowerCase","includes","transferEncoding","contentLength","_tryReadResponseBody","clonedResponse","clone","length","parseInt","isNaN","maxCapturingHttpPayloadSize","json","text","arrayBuffer","byteLength","error","Error","message","_headersToObject","result","forEach","value","key","_headersInitToObject","headersInit","Headers","Array","isArray","String","entries","fetch","global","originalFetch","input","init","networkRequest","inputIsRequest","Request","recordRequestHeaders","requestHeaders","shouldRecordBody","candidateBody","requestBody","Blob","size","recordResponseHeaders","responseHeaders","responseBody","setPrototypeOf","defineProperty","console","warn","info"],"sourceRoot":"../../../src","sources":["patch/fetch.ts"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplayer-app/session-recorder-react-native",
3
- "version": "1.3.14",
3
+ "version": "1.3.16",
4
4
  "description": "Multiplayer Fullstack Session Recorder for React Native",
5
5
  "author": {
6
6
  "name": "Multiplayer Software, Inc.",
@@ -107,7 +107,7 @@
107
107
  "typescript": "^5.9.2"
108
108
  },
109
109
  "dependencies": {
110
- "@multiplayer-app/session-recorder-common": "1.3.14",
110
+ "@multiplayer-app/session-recorder-common": "1.3.16",
111
111
  "@opentelemetry/core": "2.0.1",
112
112
  "@opentelemetry/exporter-trace-otlp-http": "0.203.0",
113
113
  "@opentelemetry/instrumentation": "0.203.0",
@@ -35,28 +35,90 @@ function _tryReadFetchBody({
35
35
  return `[Fetch] Cannot read body of type ${Object.prototype.toString.call(body)}`
36
36
  }
37
37
 
38
+ /**
39
+ * Detects if a response is a streaming response that should NOT have its body read.
40
+ * Reading the body of streaming responses (SSE, chunked streams, etc.) will either:
41
+ * - Block forever (SSE streams never end)
42
+ * - Corrupt the stream for the actual consumer
43
+ */
44
+ function _isStreamingResponse(response: Response): boolean {
45
+ const contentType = response.headers.get('content-type')?.toLowerCase() ?? ''
46
+
47
+ // SSE - Server-Sent Events (infinite stream)
48
+ if (contentType.includes('text/event-stream')) {
49
+ return true
50
+ }
51
+
52
+ // Binary streams that are typically long-running
53
+ if (contentType.includes('application/octet-stream')) {
54
+ return true
55
+ }
56
+
57
+ // NDJSON streaming (newline-delimited JSON, common in streaming APIs)
58
+ if (contentType.includes('application/x-ndjson') || contentType.includes('application/ndjson')) {
59
+ return true
60
+ }
61
+
62
+ // gRPC-web streaming
63
+ if (contentType.includes('application/grpc')) {
64
+ return true
65
+ }
66
+
67
+ // Check for chunked transfer encoding (often indicates streaming)
68
+ const transferEncoding = response.headers.get('transfer-encoding')?.toLowerCase()
69
+ if (transferEncoding?.includes('chunked')) {
70
+ // Chunked alone isn't definitive, but combined with no content-length = streaming
71
+ const contentLength = response.headers.get('content-length')
72
+ if (!contentLength) {
73
+ return true
74
+ }
75
+ }
76
+
77
+ return false
78
+ }
79
+
80
+ /**
81
+ * Safely reads response body for non-streaming responses.
82
+ * Returns null for streaming responses to avoid blocking/corruption.
83
+ */
38
84
  async function _tryReadResponseBody(response: Response): Promise<string | null> {
85
+ // CRITICAL: Never attempt to read streaming response bodies
86
+ if (_isStreamingResponse(response)) {
87
+ return null
88
+ }
89
+
39
90
  try {
40
91
  // Clone the response to avoid consuming the original stream.
41
92
  const clonedResponse = response.clone()
93
+ const contentType = response.headers.get('content-type')?.toLowerCase() ?? ''
94
+
95
+ // Check content-length to avoid reading massive responses
96
+ const contentLength = response.headers.get('content-length')
97
+ if (contentLength) {
98
+ const length = parseInt(contentLength, 10)
99
+ if (!isNaN(length) && length > configs.maxCapturingHttpPayloadSize) {
100
+ return `[Fetch] Response too large (${length} bytes)`
101
+ }
102
+ }
42
103
 
43
- const contentType = response.headers.get('content-type') || ''
44
104
  if (contentType.includes('application/json')) {
45
105
  const json = await clonedResponse.json()
46
106
  return JSON.stringify(json)
47
- } else if (contentType.includes('text/')) {
107
+ }
108
+
109
+ if (contentType.includes('text/')) {
48
110
  return await clonedResponse.text()
49
- } else {
50
- // For other content types, try text first, fallback to arrayBuffer
111
+ }
112
+
113
+ // For unknown types, attempt text read
114
+ try {
115
+ return await clonedResponse.text()
116
+ } catch {
51
117
  try {
52
- return await clonedResponse.text()
118
+ const arrayBuffer = await clonedResponse.arrayBuffer()
119
+ return `[Fetch] Binary data (${arrayBuffer.byteLength} bytes)`
53
120
  } catch {
54
- try {
55
- const arrayBuffer = await clonedResponse.arrayBuffer()
56
- return `[Fetch] Binary data (${arrayBuffer.byteLength} bytes)`
57
- } catch {
58
- return '[Fetch] Unable to read response body'
59
- }
121
+ return '[Fetch] Unable to read response body'
60
122
  }
61
123
  }
62
124
  } catch (error) {