RocketChat / RocketChat/Rocket.Chat.ReactNative
Android: add User-Agent interceptor to shared OkHttp client
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 2.4k
- Forks
- 1.5k
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 90
Description
Context
Follow-up to #7330 / #7339 (avatar fetch in push notifications was missing the RC Mobile User-Agent on Android).
That PR fixed the avatar surface specifically, in the NotificationHelper.avatarLoadModel helper. The broader problem is that other native HTTP call sites on Android can still leak the default Dalvik UA, because they go through the shared OkHttp client without explicit headers.
What's affected
Confirmed sites still missing the RC Mobile UA:
android/app/src/main/java/chat/rocket/reactnative/voip/MediaCallsAnswerRequest.kt— VoIP accept/decline REST call (/api/v1/media-calls.answer). Setsx-user-id/x-auth-token, noUser-Agent.android/app/src/main/java/chat/rocket/reactnative/networking/ExpoImageClient.java— Expo Image (in-app image loads) usesSSLPinningTurboModule.getSharedOkHttpClient(), which has no UA configured.
Already correctly set today:
LoadNotification.java(push.get)ReplyBroadcast.java(chat.sendMessage)NotificationHelper.fetchAvatarBitmap(via the #7339 fix)
Proposed fix
Add a User-Agent interceptor to SSLPinningTurboModule.getSharedOkHttpClient() so every native HTTP call inherits the RC Mobile; android <ver>; v<x> (<n>) UA by default — only the sites that need to override it would have to opt out. Mirrors what iOS already does (URLSession + Bundle.userAgent is applied at every call site, but the centralised analogue on Android is the shared OkHttp client).
Sketch:
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.addInterceptor(chain -> {
Request original = chain.request();
if (original.header("User-Agent") != null) {
return chain.proceed(original); // respect explicit override
}
return chain.proceed(
original.newBuilder()
.header("User-Agent", NotificationHelper.getUserAgent())
.build()
);
});
(Helper move: getUserAgent probably wants to live somewhere more general than NotificationHelper once it's used app-wide.)
Test plan
- Verify with a debug build against a Rocket.Chat workspace that logs UA: VoIP accept/decline, Expo Image loads (avatars in
RoomView, file previews) all reportRC Mobile; android .... - Unit test on the interceptor: explicit
User-Agentis preserved; default is injected when none provided.
Out of scope
- iOS — already correct.
- JS-side fetches — already use the wrapper in
app/lib/methods/helpers/fetch.ts.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with android/app/src/main/java/chat/rocket/reactnative/networking/ExpoImageClient.java and the shared client returned by SSLPinningTurboModule.getSharedOkHttpClient(), then compare the existing UA handling in LoadNotification.java, ReplyBroadcast.java, and NotificationHelper. Add centralized default-UA behavior while preserving explicit User-Agent headers, and verify the interceptor with unit tests plus the listed VoIP and Expo Image flows.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, java, kotlin, react-native
- Domain
- mobile, networking, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 64/100