Skip to content

feat: respect be network body limit #1397

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Jul 1, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -12,6 +12,8 @@

- Add support for network spans. ([#1394](https://github.com/Instabug/Instabug-React-Native/pull/1394))

- Add respect to backend network body limit. ([#1397](https://github.com/Instabug/Instabug-React-Native/pull/1397))

### Fixed

- Not sending the inComplete xhrRequest. ([#1365](https://github.com/Instabug/Instabug-React-Native/pull/1365))
2 changes: 1 addition & 1 deletion android/native.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
project.ext.instabug = [
version: '14.3.0'
version: '14.3.0.6760192-SNAPSHOT'
]

dependencies {
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ final class Constants {
final static String IBG_ON_FEATURES_UPDATED_CALLBACK = "IBGOnFeatureUpdatedCallback";
final static String IBG_NETWORK_LOGGER_HANDLER = "IBGNetworkLoggerHandler";

final static String IBG_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK = "IBGOnNewW3CFlagsUpdateReceivedCallback";
final static String IBG_ON_FEATURE_FLAGS_UPDATE_RECEIVED_CALLBACK = "IBGOnNewFeatureFlagsUpdateReceivedCallback";

final static String IBG_SESSION_REPLAY_ON_SYNC_CALLBACK_INVOCATION = "IBGSessionReplayOnSyncCallback";

Original file line number Diff line number Diff line change
@@ -1159,10 +1159,10 @@ public void run() {
}

/**
* Register a listener for W3C flags value change
* Register a listener for feature flags value change
*/
@ReactMethod
public void registerW3CFlagsChangeListener() {
public void registerFeatureFlagsChangeListener() {

MainThreadHandler.runOnMainThread(new Runnable() {
@Override
@@ -1175,8 +1175,9 @@ public void invoke(@NonNull CoreFeaturesState featuresState) {
params.putBoolean("isW3ExternalTraceIDEnabled", featuresState.isW3CExternalTraceIdEnabled());
params.putBoolean("isW3ExternalGeneratedHeaderEnabled", featuresState.isAttachingGeneratedHeaderEnabled());
params.putBoolean("isW3CaughtHeaderEnabled", featuresState.isAttachingCapturedHeaderEnabled());
params.putInt("networkBodyLimit",featuresState.getNetworkLogCharLimit());

sendEvent(Constants.IBG_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params);
sendEvent(Constants.IBG_ON_FEATURE_FLAGS_UPDATE_RECEIVED_CALLBACK, params);
}
});
} catch (Exception e) {
@@ -1306,7 +1307,7 @@ public void run() {
}
});
}
/**

/**
* Sets the auto mask screenshots types.
*
@@ -1331,4 +1332,23 @@ public void run() {

});
}

/**
* Get network body size limit
*/
@ReactMethod
public void getNetworkBodyMaxSize(Promise promise) {

MainThreadHandler.runOnMainThread(new Runnable() {
@Override
public void run() {
try {
promise.resolve(InternalCore.INSTANCE.get_networkLogCharLimit());
} catch (Exception e) {
e.printStackTrace();
promise.resolve(false);
}
}
});
}
}
Original file line number Diff line number Diff line change
@@ -686,9 +686,22 @@ public void testEnableAutoMasking(){
String maskTextInputs = "textInputs";
String maskMedia = "media";
String maskNone = "none";

rnModule.enableAutoMasking(JavaOnlyArray.of(maskLabel, maskMedia, maskTextInputs,maskNone));

mockInstabug.verify(() -> Instabug.setAutoMaskScreenshotsTypes(MaskingType.LABELS,MaskingType.MEDIA,MaskingType.TEXT_INPUTS,MaskingType.MASK_NOTHING));
}

@Test
public void testGetNetworkBodyMaxSize_resolvesPromiseWithExpectedValue() {
Promise promise = mock(Promise.class);
InternalCore internalAPM = mock(InternalCore.class);
int expected = 10240;
when(internalAPM.get_networkLogCharLimit()).thenReturn(expected);

rnModule.getNetworkBodyMaxSize(promise);

verify(promise).resolve(expected);
}

}
2 changes: 1 addition & 1 deletion examples/default/android/build.gradle
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ buildscript {
classpath("com.android.tools.build:gradle:8.1.0")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
classpath("com.instabug.library:instabug-plugin:14.1.0.6273967-SNAPSHOT")
classpath("com.instabug.library:instabug-plugin:14.3.0.6760192-SNAPSHOT")
}
}

19 changes: 19 additions & 0 deletions examples/default/ios/InstabugTests/InstabugSampleTests.m
Original file line number Diff line number Diff line change
@@ -634,4 +634,23 @@ - (void)testSetNetworkLogBodyEnabled {
OCMVerify([mock setLogBodyEnabled:isEnabled]);
}

- (void)testGetNetworkBodyMaxSize {
id mock = OCMClassMock([IBGNetworkLogger class]);
double expectedValue = 10240.0;

OCMStub([mock getNetworkBodyMaxSize]).andReturn(expectedValue);

XCTestExpectation *expectation = [self expectationWithDescription:@"Call resolve block"];
RCTPromiseResolveBlock resolve = ^(NSNumber *result) {
XCTAssertEqual(result.doubleValue, expectedValue);
[expectation fulfill];
};

[self.instabugBridge getNetworkBodyMaxSize:resolve :nil];
[self waitForExpectationsWithTimeout:1.0 handler:nil];

OCMVerify(ClassMethod([mock getNetworkBodyMaxSize]));
}


@end
2 changes: 1 addition & 1 deletion examples/default/ios/Podfile
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ target 'InstabugExample' do
rn_maps_path = '../node_modules/react-native-maps'
pod 'react-native-google-maps', :path => rn_maps_path
# add this line
pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/sanity/15.0.1/Instabug.podspec'
pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/feature-expose_network_limit-expose_body_limit/15.0.1/Instabug.podspec'
# Flags change depending on the env values.
flags = get_default_flags()

8 changes: 4 additions & 4 deletions examples/default/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1770,7 +1770,7 @@ DEPENDENCIES:
- fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
- Instabug (from `https://ios-releases.instabug.com/custom/sanity/15.0.1/Instabug.podspec`)
- Instabug (from `https://ios-releases.instabug.com/custom/feature-expose_network_limit-expose_body_limit/15.0.1/Instabug.podspec`)
- instabug-reactnative-ndk (from `../node_modules/instabug-reactnative-ndk`)
- OCMock
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
@@ -1869,7 +1869,7 @@ EXTERNAL SOURCES:
:podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec"
:tag: hermes-2024-08-15-RNv0.75.1-4b3bf912cc0f705b51b71ce1a5b8bd79b93a451b
Instabug:
:podspec: https://ios-releases.instabug.com/custom/sanity/15.0.1/Instabug.podspec
:podspec: https://ios-releases.instabug.com/custom/feature-expose_network_limit-expose_body_limit/15.0.1/Instabug.podspec
instabug-reactnative-ndk:
:path: "../node_modules/instabug-reactnative-ndk"
RCT-Folly:
@@ -2024,7 +2024,7 @@ SPEC CHECKSUMS:
Google-Maps-iOS-Utils: f77eab4c4326d7e6a277f8e23a0232402731913a
GoogleMaps: 032f676450ba0779bd8ce16840690915f84e57ac
hermes-engine: ea92f60f37dba025e293cbe4b4a548fd26b610a0
Instabug: 9e81b71be68626dafc74759f3458f7c5894dd2e1
Instabug: ba6587d15ad5e3ffa265afc8174ff83af4eed29d
instabug-reactnative-ndk: d765ac289d56e8896398d02760d9abf2562fc641
OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74
RCT-Folly: 4464f4d875961fce86008d45f4ecf6cef6de0740
@@ -2100,6 +2100,6 @@ SPEC CHECKSUMS:
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
Yoga: 055f92ad73f8c8600a93f0e25ac0b2344c3b07e6

PODFILE CHECKSUM: a1b532d67a1a86843e1f086101751ad55afa52da
PODFILE CHECKSUM: f7f8d2b03a0b566cb0f5b4b422469af0a1a278b1

COCOAPODS: 1.14.0
2 changes: 1 addition & 1 deletion examples/default/src/App.tsx
Original file line number Diff line number Diff line change
@@ -50,7 +50,7 @@ export const App: React.FC = () => {
token: 'deb1910a7342814af4e4c9210c786f35',
invocationEvents: [InvocationEvent.floatingButton],
debugLogsLevel: LogLevel.verbose,
networkInterceptionMode: NetworkInterceptionMode.native,
networkInterceptionMode: NetworkInterceptionMode.javascript,
});

CrashReporting.setNDKCrashesEnabled(true);
1 change: 1 addition & 0 deletions ios/RNInstabug/InstabugReactBridge.h
Original file line number Diff line number Diff line change
@@ -140,5 +140,6 @@ w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes;
- (void)removeAllFeatureFlags;
- (void)setNetworkLogBodyEnabled:(BOOL)isEnabled;
- (void)enableAutoMasking:(NSArray *)autoMaskingTypes;
- (void)getNetworkBodyMaxSize:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject;

@end
4 changes: 4 additions & 0 deletions ios/RNInstabug/InstabugReactBridge.m
Original file line number Diff line number Diff line change
@@ -452,6 +452,10 @@ + (BOOL)iOSVersionIsLessThan:(NSString *)iOSVersion {
[Instabug setAutoMaskScreenshots: autoMaskingOptions];
};

RCT_EXPORT_METHOD(getNetworkBodyMaxSize:(RCTPromiseResolveBlock)resolve :(RCTPromiseRejectBlock)reject) {
resolve(@(IBGNetworkLogger.getNetworkBodyMaxSize));
}

RCT_EXPORT_METHOD(setNetworkLogBodyEnabled:(BOOL)isEnabled) {
IBGNetworkLogger.logBodyEnabled = isEnabled;
}
1 change: 1 addition & 0 deletions ios/RNInstabug/Util/IBGNetworkLogger+CP.h
Original file line number Diff line number Diff line change
@@ -61,6 +61,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (void)setCPRequestAsyncObfuscationHandler:(void (^)(NSURLRequest * requestToBeObfuscated, void (^ completion)(NSURLRequest * obfuscatedRequest)))asyncObfuscationHandler;
+ (void)setCPRequestFilteringHandler:(void (^)(NSURLRequest * request, void (^completion)(BOOL keep)))requestFilteringHandler;
+ (void)setCPResponseFilteringHandler:(void (^)(NSURLResponse * response, void (^comppletion)(BOOL keep)))responseFilteringHandler;
+ (double)getNetworkBodyMaxSize;

@end

13 changes: 7 additions & 6 deletions src/modules/Instabug.ts
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ import type { NavigationAction, NavigationState as NavigationStateV4 } from 'rea
import type { InstabugConfig } from '../models/InstabugConfig';
import Report from '../models/Report';
import { emitter, NativeEvents, NativeInstabug } from '../native/NativeInstabug';
import { registerW3CFlagsListener } from '../utils/FeatureFlags';
import { registerFeatureFlagsListener } from '../utils/FeatureFlags';
import {
AutoMaskingType,
ColorTheme,
@@ -87,7 +87,7 @@ function reportCurrentViewForAndroid(screenName: string | null) {
export const init = async (config: InstabugConfig) => {
if (Platform.OS === 'android') {
// Add android feature flags listener for android
registerW3CFlagsListener();
registerFeatureFlagsListener();
addOnFeatureUpdatedListener(config);
} else {
isNativeInterceptionFeatureEnabled = await NativeNetworkLogger.isNativeInterceptionEnabled();
@@ -871,20 +871,21 @@ export const componentDidAppearListener = (event: ComponentDidAppearEvent) => {
};

/**
* Sets listener to W3ExternalTraceID flag changes
* Sets listener to feature flag changes
* @param handler A callback that gets the update value of the flag
*/
export const _registerW3CFlagsChangeListener = (
export const _registerFeatureFlagsChangeListener = (
handler: (payload: {
isW3ExternalTraceIDEnabled: boolean;
isW3ExternalGeneratedHeaderEnabled: boolean;
isW3CaughtHeaderEnabled: boolean;
networkBodyLimit: number;
}) => void,
) => {
emitter.addListener(NativeEvents.ON_W3C_FLAGS_CHANGE, (payload) => {
emitter.addListener(NativeEvents.ON_FEATURE_FLAGS_CHANGE, (payload) => {
handler(payload);
});
NativeInstabug.registerW3CFlagsChangeListener();
NativeInstabug.registerFeatureFlagsChangeListener();
};

/**
28 changes: 22 additions & 6 deletions src/modules/NetworkLogger.ts
Original file line number Diff line number Diff line change
@@ -45,7 +45,9 @@ export const setEnabled = (isEnabled: boolean) => {
xhr.setOnDoneCallback(async (network) => {
// eslint-disable-next-line no-new-func
const predicate = Function('network', 'return ' + _requestFilterExpression);

if (!predicate(network)) {
const MAX_NETWORK_BODY_SIZE_IN_BYTES = await NativeInstabug.getNetworkBodyMaxSize();
try {
if (_networkDataObfuscationHandler) {
network = await _networkDataObfuscationHandler(network);
@@ -57,14 +59,28 @@ export const setEnabled = (isEnabled: boolean) => {
return;
}
}
if (network.requestBodySize > InstabugConstants.MAX_NETWORK_BODY_SIZE_IN_BYTES) {
network.requestBody = InstabugConstants.MAX_REQUEST_BODY_SIZE_EXCEEDED_MESSAGE;
Logger.warn('IBG-RN:', InstabugConstants.MAX_REQUEST_BODY_SIZE_EXCEEDED_MESSAGE);
if (network.requestBodySize > MAX_NETWORK_BODY_SIZE_IN_BYTES) {
network.requestBody = `${InstabugConstants.MAX_REQUEST_BODY_SIZE_EXCEEDED_MESSAGE}${
MAX_NETWORK_BODY_SIZE_IN_BYTES / 1024
} Kb`;
Logger.warn(
'IBG-RN:',
`${InstabugConstants.MAX_REQUEST_BODY_SIZE_EXCEEDED_MESSAGE}${
MAX_NETWORK_BODY_SIZE_IN_BYTES / 1024
} Kb`,
);
}

if (network.responseBodySize > InstabugConstants.MAX_NETWORK_BODY_SIZE_IN_BYTES) {
network.responseBody = InstabugConstants.MAX_RESPONSE_BODY_SIZE_EXCEEDED_MESSAGE;
Logger.warn('IBG-RN:', InstabugConstants.MAX_RESPONSE_BODY_SIZE_EXCEEDED_MESSAGE);
if (network.responseBodySize > MAX_NETWORK_BODY_SIZE_IN_BYTES) {
network.responseBody = `${InstabugConstants.MAX_RESPONSE_BODY_SIZE_EXCEEDED_MESSAGE}${
MAX_NETWORK_BODY_SIZE_IN_BYTES / 1024
} Kb`;
Logger.warn(
'IBG-RN:',
`${InstabugConstants.MAX_RESPONSE_BODY_SIZE_EXCEEDED_MESSAGE}${
MAX_NETWORK_BODY_SIZE_IN_BYTES / 1024
} Kb`,
);
}

if (network.requestBody && isContentTypeNotAllowed(network.requestContentType)) {
7 changes: 4 additions & 3 deletions src/native/NativeInstabug.ts
Original file line number Diff line number Diff line change
@@ -152,19 +152,20 @@ export interface InstabugNativeModule extends NativeModule {

isW3CaughtHeaderEnabled(): Promise<boolean>;

// W3C Feature Flags Listener for Android
registerW3CFlagsChangeListener(): void;
// Feature Flags Listener for Android
registerFeatureFlagsChangeListener(): void;

setOnFeaturesUpdatedListener(handler?: (params: any) => void): void; // android only
enableAutoMasking(autoMaskingTypes: AutoMaskingType[]): void;
getNetworkBodyMaxSize(): Promise<number>;
}

export const NativeInstabug = NativeModules.Instabug;

export enum NativeEvents {
PRESENDING_HANDLER = 'IBGpreSendingHandler',
IBG_ON_FEATURES_UPDATED_CALLBACK = 'IBGOnFeatureUpdatedCallback',
ON_W3C_FLAGS_CHANGE = 'IBGOnNewW3CFlagsUpdateReceivedCallback',
ON_FEATURE_FLAGS_CHANGE = 'IBGOnNewFeatureFlagsUpdateReceivedCallback',
}

export const emitter = new NativeEventEmitter(NativeInstabug);
11 changes: 8 additions & 3 deletions src/utils/FeatureFlags.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { NativeInstabug } from '../native/NativeInstabug';
import { _registerW3CFlagsChangeListener } from '../modules/Instabug';
import { _registerFeatureFlagsChangeListener } from '../modules/Instabug';

export const FeatureFlags = {
isW3ExternalTraceID: () => NativeInstabug.isW3ExternalTraceIDEnabled(),
isW3ExternalGeneratedHeader: () => NativeInstabug.isW3ExternalGeneratedHeaderEnabled(),
isW3CaughtHeader: () => NativeInstabug.isW3CaughtHeaderEnabled(),
networkLogLimit: () => NativeInstabug.getNetworkBodyMaxSize(),
};

export const registerW3CFlagsListener = () => {
_registerW3CFlagsChangeListener(
export const registerFeatureFlagsListener = () => {
_registerFeatureFlagsChangeListener(
(res: {
isW3ExternalTraceIDEnabled: boolean;
isW3ExternalGeneratedHeaderEnabled: boolean;
isW3CaughtHeaderEnabled: boolean;
networkBodyLimit: number;
}) => {
FeatureFlags.isW3ExternalTraceID = async () => {
return res.isW3ExternalTraceIDEnabled;
@@ -23,6 +25,9 @@ export const registerW3CFlagsListener = () => {
FeatureFlags.isW3CaughtHeader = async () => {
return res.isW3CaughtHeaderEnabled;
};
FeatureFlags.networkLogLimit = async () => {
return res.networkBodyLimit;
};
},
);
};
4 changes: 2 additions & 2 deletions src/utils/InstabugConstants.ts
Original file line number Diff line number Diff line change
@@ -4,9 +4,9 @@ const InstabugConstants = {
// TODO: dyanmically get the max size from the native SDK and update the error message to reflect the dynamic size.
MAX_NETWORK_BODY_SIZE_IN_BYTES: 1024 * 10, // 10 KB
MAX_RESPONSE_BODY_SIZE_EXCEEDED_MESSAGE:
'The response body has not been logged because it exceeds the maximum size of 10 Kb',
'The response body has not been logged because it exceeds the maximum size of ',
MAX_REQUEST_BODY_SIZE_EXCEEDED_MESSAGE:
'The request body has not been logged because it exceeds the maximum size of 10 Kb',
'The request body has not been logged because it exceeds the maximum size of ',
SET_USER_ATTRIBUTES_ERROR_TYPE_MESSAGE:
'IBG-RN: Expected key and value passed to setUserAttribute to be of type string',
REMOVE_USER_ATTRIBUTES_ERROR_TYPE_MESSAGE:
3 changes: 2 additions & 1 deletion test/mocks/mockInstabug.ts
Original file line number Diff line number Diff line change
@@ -72,10 +72,11 @@ const mockInstabug: InstabugNativeModule = {
isW3ExternalTraceIDEnabled: jest.fn(),
isW3ExternalGeneratedHeaderEnabled: jest.fn(),
isW3CaughtHeaderEnabled: jest.fn(),
registerW3CFlagsChangeListener: jest.fn(),
registerFeatureFlagsChangeListener: jest.fn(),
setNetworkLogBodyEnabled: jest.fn(),
setOnFeaturesUpdatedListener: jest.fn(),
enableAutoMasking: jest.fn(),
getNetworkBodyMaxSize: jest.fn().mockResolvedValue(10240), // 10 KB
};

export default mockInstabug;
Loading