Skip to content

Commit 6dd503d

Browse files
apply: PR comments
1 parent a099eff commit 6dd503d

File tree

8 files changed

+119
-112
lines changed

8 files changed

+119
-112
lines changed

android/src/main/java/com/instabug/reactlibrary/RNInstabugNetworkLoggerModule.java

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
import static com.instabug.apm.configuration.cp.APMFeature.APM_NETWORK_PLUGIN_INSTALLED;
55
import static com.instabug.apm.configuration.cp.APMFeature.CP_NATIVE_INTERCEPTION_ENABLED;
66

7+
import android.util.Log;
8+
79
import androidx.annotation.NonNull;
810

911
import com.facebook.react.bridge.Arguments;
1012
import com.facebook.react.bridge.Promise;
1113
import com.facebook.react.bridge.ReactApplicationContext;
1214
import com.facebook.react.bridge.ReactMethod;
15+
import com.facebook.react.bridge.ReadableMap;
16+
import com.facebook.react.bridge.ReadableMapKeySetIterator;
1317
import com.facebook.react.bridge.WritableMap;
1418
import com.facebook.react.bridge.WritableNativeMap;
1519
import com.instabug.apm.InternalAPM;
@@ -21,6 +25,7 @@
2125
import org.json.JSONException;
2226
import org.json.JSONObject;
2327

28+
import java.util.HashMap;
2429
import java.util.Map;
2530
import java.util.concurrent.ConcurrentHashMap;
2631

@@ -55,16 +60,27 @@ private boolean getFlagValue(String key) {
5560
return InternalAPM._isFeatureEnabledCP(key, "");
5661
}
5762

58-
private WritableMap convertFromMapToWriteableMap(Map map) {
63+
private WritableMap convertFromMapToWritableMap(Map<String, Object> map) {
5964
WritableMap writableMap = new WritableNativeMap();
60-
for (int i = 0; i < map.size(); i++) {
61-
Object key = map.keySet().toArray()[i];
65+
for (Object key : map.keySet().toArray()) {
6266
Object value = map.get(key);
6367
writableMap.putString((String) key, (String) value);
6468
}
6569
return writableMap;
6670
}
6771

72+
private Map<String, Object> convertReadableMapToMap(ReadableMap readableMap) {
73+
Map<String, Object> map = new HashMap<>();
74+
if (readableMap != null) {
75+
ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
76+
while (iterator.hasNextKey()) {
77+
String key = iterator.nextKey();
78+
map.put(key, readableMap.getString(key));
79+
}
80+
}
81+
return map;
82+
}
83+
6884
/**
6985
* Get first time Value of [cp_native_interception_enabled] flag
7086
*/
@@ -123,11 +139,11 @@ public void run() {
123139
networkSnapshotParams.putString("response", networkLogSnapshot.getResponse());
124140
final Map<String, Object> requestHeaders = networkLogSnapshot.getRequestHeaders();
125141
if (requestHeaders != null) {
126-
networkSnapshotParams.putMap("requestHeader", convertFromMapToWriteableMap(networkLogSnapshot.getRequestHeaders()));
142+
networkSnapshotParams.putMap("requestHeader", convertFromMapToWritableMap(requestHeaders));
127143
}
128144
final Map<String, Object> responseHeaders = networkLogSnapshot.getResponseHeaders();
129145
if (responseHeaders != null) {
130-
networkSnapshotParams.putMap("responseHeader", convertFromMapToWriteableMap(networkLogSnapshot.getResponseHeaders()));
146+
networkSnapshotParams.putMap("responseHeader", convertFromMapToWritableMap(responseHeaders));
131147
}
132148

133149
sendEvent(Constants.IBG_NETWORK_LOGGER_HANDLER, networkSnapshotParams);
@@ -147,27 +163,33 @@ public void run() {
147163
}
148164

149165
@ReactMethod
150-
protected void updateNetworkLogSnapshot(String jsonString) {
151-
152-
JSONObject newJSONObject;
153-
String url;
154-
NetworkLogSnapshot modifiedSnapshot = null;
166+
public void updateNetworkLogSnapshot(
167+
String url,
168+
String callbackID,
169+
String requestBody,
170+
String responseBody,
171+
int responseCode,
172+
ReadableMap requestHeaders,
173+
ReadableMap responseHeaders
174+
) {
155175
try {
156-
newJSONObject = new JSONObject(jsonString);
157-
url = newJSONObject.optString("url");
158-
} catch (JSONException e) {
159-
throw new RuntimeException(e);
160-
}
161-
final String ID = newJSONObject.optString("id");
176+
// Convert ReadableMap to a Java Map for easier handling
177+
Map<String, Object> requestHeadersMap = convertReadableMapToMap(requestHeaders);
178+
Map<String, Object> responseHeadersMap = convertReadableMapToMap(responseHeaders);
162179

163-
if (!url.isEmpty()) {
164-
modifiedSnapshot = new NetworkLogSnapshot(url, null, null, null, null, newJSONObject.optInt("responseCode"));
165-
}
180+
NetworkLogSnapshot modifiedSnapshot = null;
181+
if (!url.isEmpty()) {
182+
modifiedSnapshot = new NetworkLogSnapshot(url, requestHeadersMap, requestBody, responseHeadersMap, responseBody, responseCode);
183+
}
166184

167-
final OnCompleteCallback<NetworkLogSnapshot> callback = callbackMap.get(ID);
168-
if (callback != null) {
169-
callback.onComplete(modifiedSnapshot);
170-
callbackMap.remove(ID);
185+
final OnCompleteCallback<NetworkLogSnapshot> callback = callbackMap.get(callbackID);
186+
if (callback != null) {
187+
callback.onComplete(modifiedSnapshot);
188+
callbackMap.remove(callbackID);
189+
}
190+
} catch (Exception e) {
191+
// Reject the promise to indicate an error occurred
192+
Log.e("IB-CP-Bridge", "InstabugNetworkLogger.updateNetworkLogSnapshot failed to parse the network snapshot object.");
171193
}
172194
}
173195
}

android/src/test/java/com/instabug/reactlibrary/RNInstabugNetworkLoggerModuleTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,10 @@ public void testRegisterNetworkLogsListenerCalled() {
206206
}
207207

208208

209-
@Test
210-
public void testUpdateNetworkLogSnapshotInvalidJson() {
211-
String invalidJsonString = "{\"id\":\"testId\"";
212-
213-
assertThrows(RuntimeException.class, () -> rnInstabugNetworkLoggerModule.updateNetworkLogSnapshot(invalidJsonString));
214-
}
209+
// @Test
210+
// public void testUpdateNetworkLogSnapshotInvalidJson() {
211+
// String invalidJsonString = "{\"id\":\"testId\"";
212+
//
213+
// assertThrows(RuntimeException.class, () -> rnInstabugNetworkLoggerModule.updateNetworkLogSnapshot(invalidJsonString));
214+
// }
215215
}

ios/RNInstabug/InstabugNetworkLoggerBridge.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,13 @@ typedef NS_ENUM(NSInteger, NetworkListenerType) {
2828

2929
- (void) registerNetworkLogsListener:(NetworkListenerType)listenerType;
3030

31-
- (void) updateNetworkLogSnapshot: (NSString * _Nonnull)jsonString;
31+
- (void)updateNetworkLogSnapshot:(NSString * _Nonnull)url
32+
callbackID:(NSString * _Nonnull)callbackID
33+
requestBody:(NSString * _Nullable)requestBody
34+
responseBody:(NSString * _Nullable)responseBody
35+
responseCode:(double)responseCode
36+
requestHeaders:(NSDictionary * _Nullable)requestHeaders
37+
responseHeaders:(NSDictionary * _Nullable)responseHeaders;
3238

3339
- (void) setNetworkLoggingRequestFilterPredicateIOS:(NSString * _Nonnull) callbackID : (BOOL)value;
3440

ios/RNInstabug/InstabugNetworkLoggerBridge.m

Lines changed: 34 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -76,69 +76,68 @@ -(void)stopObserving {
7676
RCT_EXPORT_METHOD(registerNetworkLogsListener: (NetworkListenerType) listenerType) {
7777
switch (listenerType) {
7878
case NetworkListenerTypeFiltering:
79-
NSLog(@"Andrew: Network logs filtering enabled");
8079
[self setupRequestFilteringHandler];
8180
break;
8281

8382
case NetworkListenerTypeObfuscation:
84-
NSLog(@"Andrew: Network logs obfuscation enabled");
8583
[self setupRequestObfuscationHandler];
8684
break;
8785

8886
case NetworkListenerTypeBoth:
89-
NSLog(@"Andrew: Both filtering and obfuscation enabled");
90-
[self setupRequestFilteringAndObfuscationHandler];
87+
// The obfuscation handler sends additional data to the JavaScript side. If filtering is applied, the request will be ignored; otherwise, it will be obfuscated and saved in the database.
88+
[self setupRequestObfuscationHandler];
9189
break;
9290

9391
default:
94-
NSLog(@"Andrew: Unknown NetworkListenerType");
92+
NSLog(@"Unknown NetworkListenerType");
9593
break;
9694
}
9795
}
9896

9997

100-
RCT_EXPORT_METHOD(updateNetworkLogSnapshot:(NSString * _Nonnull)jsonString) {
101-
// Properly initialize the NSMutableURLRequest
102-
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
103-
104-
// Convert jsonString to NSData
105-
NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
106-
107-
// Parse the JSON into a dictionary
108-
NSError *error = nil;
109-
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
110-
111-
// Check for JSON parsing errors
112-
if (error) {
113-
NSLog(@"Failed to parse JSON: %@", error);
98+
RCT_EXPORT_METHOD(updateNetworkLogSnapshot:(NSString * _Nonnull)url
99+
callbackID:(NSString * _Nonnull)callbackID
100+
requestBody:(NSString * _Nullable)requestBody
101+
responseBody:(NSString * _Nullable)responseBody
102+
responseCode:(double)responseCode
103+
requestHeaders:(NSDictionary * _Nullable)requestHeaders
104+
responseHeaders:(NSDictionary * _Nullable)responseHeaders)
105+
{
106+
// Validate and construct the URL
107+
NSURL *requestURL = [NSURL URLWithString:url];
108+
if (!requestURL) {
109+
NSLog(@"Invalid URL: %@", url);
114110
return;
115111
}
116112

117-
// Set the URL, HTTP body, and headers
118-
request.URL = [NSURL URLWithString:dict[@"url"]];
119-
request.HTTPBody = [dict[@"requestBody"] dataUsingEncoding:NSUTF8StringEncoding];
113+
// Initialize the NSMutableURLRequest
114+
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:requestURL];
115+
116+
// Set the HTTP body if provided
117+
if (requestBody && [requestBody isKindOfClass:[NSString class]]) {
118+
request.HTTPBody = [requestBody dataUsingEncoding:NSUTF8StringEncoding];
119+
}
120120

121-
// Ensure requestHeader is a dictionary
122-
if ([dict[@"requestHeader"] isKindOfClass:[NSDictionary class]]) {
123-
request.allHTTPHeaderFields = dict[@"requestHeader"];
121+
// Ensure requestHeaders is a valid dictionary before setting it
122+
if (requestHeaders && [requestHeaders isKindOfClass:[NSDictionary class]]) {
123+
request.allHTTPHeaderFields = requestHeaders;
124124
} else {
125-
NSLog(@"Invalid requestHeader format");
126-
// return;
125+
NSLog(@"Invalid requestHeaders format, expected NSDictionary.");
127126
}
128127

129-
// Ensure self.completion is not nil before calling it
130-
NSString *callbackID = dict[@"id"];
131-
if ([callbackID isKindOfClass:[NSString class]] && self.requestObfuscationCompletionDictionary[callbackID] != nil) {
132-
((IBGURLRequestAsyncObfuscationCompletedHandler)self.requestObfuscationCompletionDictionary[callbackID])(request);
128+
// Ensure callbackID is valid and the completion handler exists
129+
IBGURLRequestAsyncObfuscationCompletedHandler completionHandler = self.requestObfuscationCompletionDictionary[callbackID];
130+
if (callbackID && [callbackID isKindOfClass:[NSString class]] && completionHandler) {
131+
// Call the completion handler with the constructed request
132+
completionHandler(request);
133133
} else {
134-
NSLog(@"Not Available Completion");
134+
NSLog(@"CallbackID not found or completion handler is unavailable for CallbackID: %@", callbackID);
135135
}
136-
137136
}
138137

139138
RCT_EXPORT_METHOD(setNetworkLoggingRequestFilterPredicateIOS: (NSString * _Nonnull) callbackID : (BOOL)value ){
140139

141-
if ([callbackID isKindOfClass:[NSString class]] && self.requestFilteringCompletionDictionary[callbackID] != nil) {
140+
if (self.requestFilteringCompletionDictionary[callbackID] != nil) {
142141
// ⬇️ YES == Request will be saved, NO == will be ignored
143142
((IBGURLRequestResponseAsyncFilteringCompletedHandler)self.requestFilteringCompletionDictionary[callbackID])(value);
144143
} else {
@@ -178,28 +177,8 @@ - (void)setupRequestObfuscationHandler {
178177
}];
179178
}
180179

181-
// Set up the obfuscation handler
182-
- (void)setupRequestFilteringAndObfuscationHandler {
183-
184-
NSString *callbackID = [[[NSUUID alloc] init] UUIDString];
185-
186-
[IBGNetworkLogger setCPRequestAsyncObfuscationHandler:^(NSURLRequest * _Nonnull request, void (^ _Nonnull completion)(NSURLRequest * _Nonnull)) {
187-
self.requestObfuscationCompletionDictionary[callbackID] = completion;
188-
}];
189-
190-
[IBGNetworkLogger setCPRequestAsyncObfuscationHandler:^(NSURLRequest * _Nonnull request, void (^ _Nonnull completion)(NSURLRequest * _Nonnull)) {
191-
self.requestObfuscationCompletionDictionary[callbackID] = completion;
192-
193-
NSDictionary *dict = [self createNetworkRequestDictForRequest:request callbackID:callbackID];
194-
if(hasListeners){
195-
[self sendEventWithName:@"IBGNetworkLoggerHandler" body:dict];
196-
}
197-
198-
}];
199-
}
200-
201180
// Helper to create a dictionary from the request and callbackID
202-
- (NSDictionary *)createNetworkRequestDictForRequest:(NSURLRequest *)request callbackID:(NSString *)callbackID {
181+
- (NSDictionary *)createNetworkRequestDictForRequest:(NSURLRequest *)request callbackID:(NSString *)callbackID {
203182
NSString *urlString = request.URL.absoluteString ?: @"";
204183
NSString *bodyString = [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding] ?: @"";
205184
NSDictionary *headerDict = request.allHTTPHeaderFields ?: @{};

src/modules/NetworkLogger.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ export const apolloLinkRequestHandler: RequestHandler = (operation, forward) =>
169169
export const resetNetworkListener = () => {
170170
if (process.env.NODE_ENV === 'test') {
171171
_networkListener = null;
172+
NativeNetworkLogger.resetNetworkLogsListener();
172173
} else {
173174
console.error(
174175
`${InstabugConstants.IBG_APM_TAG}: The \`resetNetworkListener()\` method is intended solely for testing purposes.`,
@@ -186,11 +187,7 @@ export const registerNetworkLogsListener = (
186187
) => {
187188
if (Platform.OS === 'ios') {
188189
console.log('Andrew: registerNetworkLogsListener called');
189-
// ignore repetitive calls
190-
if (_networkListener === type || _networkListener === NetworkListenerType.both) {
191-
console.log('Andrew: _registerNetworkLogsListener called on the same type');
192-
return;
193-
}
190+
194191
// remove old listeners
195192
if (NetworkLoggerEmitter.listenerCount(NativeNetworkLoggerEvent.NETWORK_LOGGER_HANDLER) > 0) {
196193
console.log('Andrew: removeAllListeners called');
@@ -214,7 +211,6 @@ export const registerNetworkLogsListener = (
214211
const { id, url, requestHeader, requestBody, responseHeader, response, responseCode } =
215212
networkSnapshot;
216213

217-
// console.log(`Andrew: new snapshot ${url}`);
218214
const networkSnapshotObj: NetworkData = {
219215
id: id,
220216
url: url,

src/native/NativeNetworkLogger.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,15 @@ export interface NetworkLoggerNativeModule extends NativeModule {
1212

1313
registerNetworkLogsListener(type?: NetworkListenerType): void;
1414

15-
updateNetworkLogSnapshot(networkData: string): void;
15+
updateNetworkLogSnapshot(
16+
url: string,
17+
callbackID: string,
18+
requestBody: string | null,
19+
responseBody: string | null,
20+
responseCode: number,
21+
requestHeaders: Record<string, string>,
22+
responseHeaders: Record<string, string>,
23+
): void;
1624

1725
hasAPMNetworkPlugin(): Promise<boolean>; // Android only
1826

src/utils/InstabugUtils.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ export function registerObfuscationListener() {
253253
if (_networkDataObfuscationHandler) {
254254
networkSnapshot = await _networkDataObfuscationHandler(networkSnapshot);
255255
}
256-
NativeNetworkLogger.updateNetworkLogSnapshot(JSON.stringify(networkSnapshot));
256+
updateNetworkLogSnapshot(networkSnapshot);
257257
},
258258
);
259259
}
@@ -272,7 +272,7 @@ export function registerFilteringListener(filterExpression: string) {
272272
// For Android Setting the [url] to an empty string will ignore the request;
273273
if (value) {
274274
networkSnapshot.url = '';
275-
NativeNetworkLogger.updateNetworkLogSnapshot(JSON.stringify(networkSnapshot));
275+
updateNetworkLogSnapshot(networkSnapshot);
276276
}
277277
}
278278
},
@@ -291,15 +291,15 @@ export function registerFilteringAndObfuscationListener(filterExpression: string
291291
// For Android Setting the [url] to an empty string will ignore the request;
292292
if (value) {
293293
networkSnapshot.url = '';
294-
NativeNetworkLogger.updateNetworkLogSnapshot(JSON.stringify(networkSnapshot));
294+
updateNetworkLogSnapshot(networkSnapshot);
295295
}
296296
}
297297
if (!value) {
298298
const _networkDataObfuscationHandler = NetworkLogger.getNetworkDataObfuscationHandler();
299299
if (_networkDataObfuscationHandler) {
300300
networkSnapshot = await _networkDataObfuscationHandler(networkSnapshot);
301301
}
302-
NativeNetworkLogger.updateNetworkLogSnapshot(JSON.stringify(networkSnapshot));
302+
updateNetworkLogSnapshot(networkSnapshot);
303303
}
304304
});
305305
}
@@ -330,13 +330,24 @@ export function checkNetworkRequestHandlers() {
330330
}
331331
}
332332
export function resetNativeObfuscationListener() {
333-
console.log('Andrew: refreshAPMNetworkConfigs -> Remove all (NETWORK_LOGGER_HANDLER) listeners');
334333
if (Platform.OS === 'android') {
335334
NativeNetworkLogger.resetNetworkLogsListener();
336335
}
337336
NetworkLoggerEmitter.removeAllListeners(NativeNetworkLoggerEvent.NETWORK_LOGGER_HANDLER);
338337
}
339338

339+
function updateNetworkLogSnapshot(networkSnapshot: NetworkData) {
340+
NativeNetworkLogger.updateNetworkLogSnapshot(
341+
networkSnapshot.url,
342+
networkSnapshot.id,
343+
networkSnapshot.requestBody,
344+
networkSnapshot.responseBody,
345+
networkSnapshot.responseCode ?? 200,
346+
networkSnapshot.requestHeaders,
347+
networkSnapshot.responseHeaders,
348+
);
349+
}
350+
340351
export default {
341352
parseErrorStack,
342353
captureJsErrors,

0 commit comments

Comments
 (0)