Skip to content

Commit 393f451

Browse files
chore: add iOS obfuscation & request filtering RN handlers
1 parent 8efad38 commit 393f451

File tree

8 files changed

+345
-127
lines changed

8 files changed

+345
-127
lines changed

examples/default/src/App.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Instabug, {
88
InvocationEvent,
99
LogLevel,
1010
NetworkInterceptionMode,
11+
NetworkLogger,
1112
ReproStepsMode,
1213
} from 'instabug-reactnative';
1314
import { NativeBaseProvider } from 'native-base';
@@ -31,6 +32,13 @@ export const App: React.FC = () => {
3132
invocationEvents: [InvocationEvent.floatingButton],
3233
debugLogsLevel: LogLevel.verbose,
3334
networkInterceptionMode: NetworkInterceptionMode.native,
35+
}).then((_) => {
36+
NetworkLogger.setNetworkDataObfuscationHandler(async (networkData) => {
37+
networkData.url = networkData.url + '/iOS/obfuscated';
38+
return networkData;
39+
});
40+
41+
NetworkLogger.setRequestFilterExpression('false');
3442
});
3543
CrashReporting.setNDKCrashesEnabled(true);
3644

ios/RNInstabug/InstabugNetworkLoggerBridge.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
typedef void (^ IBGURLRequestAsyncObfuscationCompletedHandler)(NSURLRequest * _Nonnull request);
66
typedef void (^IBGURLRequestResponseAsyncFilteringCompletedHandler)(BOOL keep);
7+
8+
typedef NS_ENUM(NSInteger, NetworkListenerType) {
9+
NetworkListenerTypeFiltering,
10+
NetworkListenerTypeObfuscation,
11+
NetworkListenerTypeBoth
12+
};
13+
714
@interface InstabugNtworkLoggerBridge : RCTEventEmitter <RCTBridgeModule>
815

916
@property NSMutableDictionary<NSString *, IBGURLRequestAsyncObfuscationCompletedHandler> * _Nonnull requestObfuscationCompletionDictionary;
@@ -17,11 +24,13 @@ typedef void (^IBGURLRequestResponseAsyncFilteringCompletedHandler)(BOOL keep);
1724
+------------------------------------------------------------------------+
1825
*/
1926

20-
- (void)isNativeInterceptionEnabled:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject;
27+
- (void)isNativeInterceptionEnabled:(RCTPromiseResolveBlock _Nullable )resolve :(RCTPromiseRejectBlock _Nullable )reject;
28+
29+
- (void) registerNetworkLogsListener:(NetworkListenerType)listenerType;
2130

22-
- (void) registerNetworkLogsListener;
31+
//- (void) registerNetworkLogsListener;
2332

2433
- (void) updateNetworkLogSnapshot: (NSString * _Nonnull)jsonString;
2534

26-
- (void) setNetworkLoggingRequestFilterPredicateIOS:(BOOL)value;
35+
- (void) setNetworkLoggingRequestFilterPredicateIOS:(NSString * _Nonnull) callbackID : (BOOL)value;
2736
@end

ios/RNInstabug/InstabugNetworkLoggerBridge.m

Lines changed: 189 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,21 @@
77
#import "InstabugNetworkLoggerBridge.h"
88
#import "Util/IBGNetworkLogger+CP.h"
99

10+
#import <React/RCTLog.h>
11+
#import <React/RCTConvert.h>
12+
13+
// Extend RCTConvert to handle NetworkListenerType enum conversion
14+
@implementation RCTConvert (NetworkListenerType)
15+
16+
// The RCT_ENUM_CONVERTER macro handles the conversion between JS values (Int) and Objective-C enum values
17+
RCT_ENUM_CONVERTER(NetworkListenerType, (@{
18+
@"filtering": @(NetworkListenerTypeFiltering),
19+
@"obfuscation": @(NetworkListenerTypeObfuscation),
20+
@"both": @(NetworkListenerTypeBoth)
21+
}), NetworkListenerTypeFiltering, integerValue)
22+
23+
@end
24+
1025
@implementation InstabugNtworkLoggerBridge
1126

1227

@@ -58,69 +73,90 @@ -(void)stopObserving {
5873
resolve(@(IBGNetworkLogger.isNativeNetworkInterceptionFeatureEnabled));
5974
}
6075

61-
RCT_EXPORT_METHOD(registerNetworkLogsListener) {
62-
63-
[IBGNetworkLogger setRequestAsyncObfuscationHandler:^(NSURLRequest * _Nonnull requestToBeObfuscated,
64-
void (^ _Nonnull completion)(NSURLRequest * _Nonnull)) {
65-
NSString *tempId = [[[NSUUID alloc] init] UUIDString];
66-
self.requestObfuscationCompletionDictionary[tempId] = completion;
67-
68-
// Ensure the URL, HTTP body, and headers are in the correct format
69-
NSString *urlString = requestToBeObfuscated.URL.absoluteString ?: @"";
70-
NSString *bodyString = [[NSString alloc] initWithData:requestToBeObfuscated.HTTPBody encoding:NSUTF8StringEncoding] ?: @"";
71-
NSDictionary *headerDict = requestToBeObfuscated.allHTTPHeaderFields ?: @{};
72-
73-
// Create the dictionary to send
74-
NSDictionary *dict = @{
75-
@"tempId": tempId,
76-
@"url": urlString,
77-
@"requestBody": bodyString,
78-
@"requestHeader": headerDict
79-
};
80-
81-
// Send the event
82-
[self sendEventWithName:@"IBGNetworkLoggerHandler" body:dict];
83-
84-
}];
85-
86-
87-
[IBGNetworkLogger setResponseObfuscationHandler:^(NSData * _Nullable responseData, NSURLResponse * _Nonnull response, NetworkObfuscationCompletionBlock _Nonnull completion) {
88-
89-
NSString *tempId = [[[NSUUID alloc] init] UUIDString];
90-
self.responseObfuscationCompletionDictionary[tempId] = completion;
91-
92-
93-
// MARK: TODO: Convert Response To Dictionary & Pass it To React Native
94-
95-
}];
96-
97-
98-
99-
[IBGNetworkLogger setRequestFilteringHandler:^(NSURLRequest * _Nonnull request, void (^ _Nonnull completion)(BOOL)) {
100-
101-
NSString *tempId = [[[NSUUID alloc] init] UUIDString];
102-
self.requestFilteringCompletionDictionary[tempId] = completion;
103-
104-
105-
// MARK: TODO: Convert Request To Dictionary & Pass it To React Native
106-
107-
}];
108-
109-
110-
[IBGNetworkLogger setResponseFilteringHandler:^(NSURLResponse * _Nonnull request, void (^ _Nonnull completion)(BOOL)) {
111-
112-
NSString *tempId = [[[NSUUID alloc] init] UUIDString];
113-
self.responseFilteringCompletionDictionary[tempId] = completion;
114-
115-
116-
// MARK: TODO: Convert Request To Dictionary & Pass it To React Native
117-
118-
}];
119-
120-
121-
122-
76+
RCT_EXPORT_METHOD(registerNetworkLogsListener: (NetworkListenerType) listenerType) {
77+
switch (listenerType) {
78+
case NetworkListenerTypeFiltering:
79+
NSLog(@"Andrew: Network logs filtering enabled");
80+
[self setupRequestFilteringHandler];
81+
break;
82+
83+
case NetworkListenerTypeObfuscation:
84+
NSLog(@"Andrew: Network logs obfuscation enabled");
85+
[self setupRequestObfuscationHandler];
86+
break;
87+
88+
case NetworkListenerTypeBoth:
89+
NSLog(@"Andrew: Both filtering and obfuscation enabled");
90+
[self setupRequestFilteringAndObfuscationHandler];
91+
break;
92+
93+
default:
94+
NSLog(@"Andrew: Unknown NetworkListenerType");
95+
break;
96+
}
12397
}
98+
//RCT_EXPORT_METHOD(registerNetworkLogsListener) {
99+
// [IBGNetworkLogger setRequestAsyncObfuscationHandler:^(NSURLRequest * _Nonnull requestToBeObfuscated,
100+
// void (^ _Nonnull completion)(NSURLRequest * _Nonnull)) {
101+
// NSString *callbackID = [[[NSUUID alloc] init] UUIDString];
102+
// self.requestObfuscationCompletionDictionary[callbackID] = completion;
103+
//
104+
// // Ensure the URL, HTTP body, and headers are in the correct format
105+
// NSString *urlString = requestToBeObfuscated.URL.absoluteString ?: @"";
106+
// NSString *bodyString = [[NSString alloc] initWithData:requestToBeObfuscated.HTTPBody encoding:NSUTF8StringEncoding] ?: @"";
107+
// NSDictionary *headerDict = requestToBeObfuscated.allHTTPHeaderFields ?: @{};
108+
//
109+
// // Create the dictionary to send
110+
// NSDictionary *dict = @{
111+
// @"callbackID": callbackID,
112+
// @"url": urlString,
113+
// @"requestBody": bodyString,
114+
// @"requestHeader": headerDict
115+
// };
116+
//
117+
// // Send the event
118+
// [self sendEventWithName:@"IBGNetworkLoggerHandler" body:dict];
119+
//
120+
// }];
121+
//
122+
//
123+
// [IBGNetworkLogger setResponseObfuscationHandler:^(NSData * _Nullable responseData, NSURLResponse * _Nonnull response, NetworkObfuscationCompletionBlock _Nonnull completion) {
124+
//
125+
// NSString *callbackID = [[[NSUUID alloc] init] UUIDString];
126+
// self.responseObfuscationCompletionDictionary[callbackID] = completion;
127+
//
128+
//
129+
// // MARK: TODO: Convert Response To Dictionary & Pass it To React Native
130+
//
131+
// }];
132+
//
133+
//
134+
//
135+
// [IBGNetworkLogger setRequestFilteringHandler:^(NSURLRequest * _Nonnull request, void (^ _Nonnull completion)(BOOL)) {
136+
//
137+
// NSString *callbackID = [[[NSUUID alloc] init] UUIDString];
138+
// self.requestFilteringCompletionDictionary[callbackID] = completion;
139+
//
140+
//
141+
// // MARK: TODO: Convert Request To Dictionary & Pass it To React Native
142+
//
143+
// }];
144+
//
145+
//
146+
// [IBGNetworkLogger setResponseFilteringHandler:^(NSURLResponse * _Nonnull request, void (^ _Nonnull completion)(BOOL)) {
147+
//
148+
// NSString *callbackID = [[[NSUUID alloc] init] UUIDString];
149+
// self.responseFilteringCompletionDictionary[callbackID] = completion;
150+
//
151+
//
152+
// // MARK: TODO: Convert Request To Dictionary & Pass it To React Native
153+
//
154+
// }];
155+
//
156+
//
157+
//
158+
//
159+
//}
124160

125161

126162
RCT_EXPORT_METHOD(updateNetworkLogSnapshot:(NSString * _Nonnull)jsonString) {
@@ -153,47 +189,111 @@ -(void)stopObserving {
153189
}
154190

155191
// Ensure self.completion is not nil before calling it
156-
NSString *tempId = dict[@"tempId"];
157-
if ([tempId isKindOfClass:[NSString class]] && self.requestObfuscationCompletionDictionary[tempId] != nil) {
158-
((IBGURLRequestAsyncObfuscationCompletedHandler)self.requestObfuscationCompletionDictionary[tempId])(request);
159-
} else {
160-
NSLog(@"Not Available Completion");
161-
}
162-
163-
164-
// MARK: Might need to moved this into another method.
165-
NSURLResponse *response; // Must be initialized from React Native Objects
166-
NSData *responseData; // Must be initialized from React Native Objects
167-
if ([tempId isKindOfClass:[NSString class]] && self.responseObfuscationCompletionDictionary[tempId] != nil) {
168-
169-
((NetworkObfuscationCompletionBlock)self.responseObfuscationCompletionDictionary[tempId])(responseData, response);
192+
NSString *callbackID = dict[@"callbackID"];
193+
if ([callbackID isKindOfClass:[NSString class]] && self.requestObfuscationCompletionDictionary[callbackID] != nil) {
194+
((IBGURLRequestAsyncObfuscationCompletedHandler)self.requestObfuscationCompletionDictionary[callbackID])(request);
170195
} else {
171196
NSLog(@"Not Available Completion");
172197
}
198+
//
199+
//
200+
// // MARK: Might need to moved this into another method.
201+
// NSURLResponse *response; // Must be initialized from React Native Objects
202+
// NSData *responseData; // Must be initialized from React Native Objects
203+
// if ([callbackID isKindOfClass:[NSString class]] && self.responseObfuscationCompletionDictionary[callbackID] != nil) {
204+
//
205+
// ((NetworkObfuscationCompletionBlock)self.responseObfuscationCompletionDictionary[callbackID])(responseData, response);
206+
// } else {
207+
// NSLog(@"Not Available Completion");
208+
// }
209+
//
210+
//
211+
//
212+
// if ([callbackID isKindOfClass:[NSString class]] && self.responseFilteringCompletionDictionary[callbackID] != nil) {
213+
// // ⬇️ YES == Response will be saved, NO == will be ignored
214+
// ((IBGURLRequestResponseAsyncFilteringCompletedHandler)self.responseFilteringCompletionDictionary[callbackID])(YES);
215+
// } else {
216+
// NSLog(@"Not Available Completion");
217+
// }
218+
//
219+
// if ([callbackID isKindOfClass:[NSString class]] && self.requestFilteringCompletionDictionary[callbackID] != nil) {
220+
// // ⬇️ YES == Request will be saved, NO == will be ignored
221+
// ((IBGURLRequestResponseAsyncFilteringCompletedHandler)self.requestFilteringCompletionDictionary[callbackID])(YES);
222+
// } else {
223+
// NSLog(@"Not Available Completion");
224+
// }
173225

226+
}
227+
228+
RCT_EXPORT_METHOD(setNetworkLoggingRequestFilterPredicateIOS: (NSString * _Nonnull) callbackID : (BOOL)value ){
229+
230+
// NSPredicate *requestPredicate = [NSPredicate predicateWithValue:(value) ? YES : NO];
174231

175-
176-
if ([tempId isKindOfClass:[NSString class]] && self.responseFilteringCompletionDictionary[tempId] != nil) {
232+
if ([callbackID isKindOfClass:[NSString class]] && self.responseFilteringCompletionDictionary[callbackID] != nil) {
177233
// ⬇️ YES == Response will be saved, NO == will be ignored
178-
((IBGURLRequestResponseAsyncFilteringCompletedHandler)self.responseFilteringCompletionDictionary[tempId])(YES);
179-
} else {
180-
NSLog(@"Not Available Completion");
181-
}
182-
183-
if ([tempId isKindOfClass:[NSString class]] && self.requestFilteringCompletionDictionary[tempId] != nil) {
184-
// ⬇️ YES == Request will be saved, NO == will be ignored
185-
((IBGURLRequestResponseAsyncFilteringCompletedHandler)self.requestFilteringCompletionDictionary[tempId])(YES);
234+
((IBGURLRequestResponseAsyncFilteringCompletedHandler)self.responseFilteringCompletionDictionary[callbackID])(YES);
186235
} else {
187236
NSLog(@"Not Available Completion");
188237
}
189238

239+
240+
// [IBGNetworkLogger setNetworkLoggingRequetFilterPredicate:requestPredicate responseFilterPredicate:nil];
190241
}
191242

192-
RCT_EXPORT_METHOD(setNetworkLoggingRequestFilterPredicateIOS: (BOOL)value){
193243

194-
NSPredicate *requestPredicate = [NSPredicate predicateWithValue:(value) ? YES : NO];
244+
#pragma mark - Helper Methods
195245

196-
[IBGNetworkLogger setNetworkLoggingRequestFilterPredicate:requestPredicate responseFilterPredicate:nil];
246+
// Set up the filtering handler
247+
- (void)setupRequestFilteringHandler {
248+
[IBGNetworkLogger setRequestFilteringHandler:^(NSURLRequest * _Nonnull request, void (^ _Nonnull completion)(BOOL)) {
249+
NSString *callbackID = [[[NSUUID alloc] init] UUIDString];
250+
self.requestFilteringCompletionDictionary[callbackID] = completion;
251+
252+
NSDictionary *dict = [self createNetworkRequestDictForRequest:request callbackID:callbackID];
253+
[self sendEventWithName:@"IBGNetworkLoggerHandler" body:dict];
254+
}];
255+
}
256+
257+
// Set up the obfuscation handler
258+
- (void)setupRequestObfuscationHandler {
259+
[IBGNetworkLogger setRequestAsyncObfuscationHandler:^(NSURLRequest * _Nonnull request, void (^ _Nonnull completion)(NSURLRequest * _Nonnull)) {
260+
NSString *callbackID = [[[NSUUID alloc] init] UUIDString];
261+
self.requestObfuscationCompletionDictionary[callbackID] = completion;
262+
263+
264+
NSDictionary *dict = [self createNetworkRequestDictForRequest:request callbackID:callbackID];
265+
[self sendEventWithName:@"IBGNetworkLoggerHandler" body:dict];
266+
}];
267+
}
268+
269+
// Set up the obfuscation handler
270+
- (void)setupRequestFilteringAndObfuscationHandler {
271+
NSString *callbackID = [[[NSUUID alloc] init] UUIDString];
272+
273+
[IBGNetworkLogger setRequestAsyncObfuscationHandler:^(NSURLRequest * _Nonnull request, void (^ _Nonnull completion)(NSURLRequest * _Nonnull)) {
274+
self.requestObfuscationCompletionDictionary[callbackID] = completion;
275+
}];
276+
277+
[IBGNetworkLogger setRequestAsyncObfuscationHandler:^(NSURLRequest * _Nonnull request, void (^ _Nonnull completion)(NSURLRequest * _Nonnull)) {
278+
self.requestObfuscationCompletionDictionary[callbackID] = completion;
279+
280+
NSDictionary *dict = [self createNetworkRequestDictForRequest:request callbackID:callbackID];
281+
[self sendEventWithName:@"IBGNetworkLoggerHandler" body:dict];
282+
}];
283+
}
284+
285+
// Helper to create a dictionary from the request and callbackID
286+
- (NSDictionary *)createNetworkRequestDictForRequest:(NSURLRequest *)request callbackID:(NSString *)callbackID {
287+
NSString *urlString = request.URL.absoluteString ?: @"";
288+
NSString *bodyString = [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding] ?: @"";
289+
NSDictionary *headerDict = request.allHTTPHeaderFields ?: @{};
290+
291+
return @{
292+
@"callbackID": callbackID,
293+
@"url": urlString,
294+
@"requestBody": bodyString,
295+
@"requestHeader": headerDict
296+
};
197297
}
198298

199299
@end

src/modules/Instabug.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ const handleNetworkInterceptionMode = (config: InstabugConfig) => {
192192
} else if (Platform.OS === 'ios') {
193193
checkNativeInterceptionForIOS(config);
194194
}
195+
NetworkLogger.setNativeInterceptionEnabled(shouldEnableNativeInterception);
195196

196197
if (config.networkInterceptionMode === NetworkInterceptionMode.javascript) {
197198
NetworkLogger.setEnabled(true);

0 commit comments

Comments
 (0)