From 4445ec9d3e2d2348cb5a637e36cc6399cd529e95 Mon Sep 17 00:00:00 2001 From: Raul Riera Date: Sat, 21 Feb 2026 12:56:11 -0500 Subject: [PATCH] fix: set User-Agent product based on gRPC path --- .../Interceptors/UserAgentInterceptor.swift | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/FlipcashCore/Sources/FlipcashCore/Clients/Payments API/Utilities/Interceptors/UserAgentInterceptor.swift b/FlipcashCore/Sources/FlipcashCore/Clients/Payments API/Utilities/Interceptors/UserAgentInterceptor.swift index 36e13f8c..2126fa7c 100644 --- a/FlipcashCore/Sources/FlipcashCore/Clients/Payments API/Utilities/Interceptors/UserAgentInterceptor.swift +++ b/FlipcashCore/Sources/FlipcashCore/Clients/Payments API/Utilities/Interceptors/UserAgentInterceptor.swift @@ -11,18 +11,34 @@ import GRPC import NIO import NIOHPACK +/// Attaches a `User-Agent` header to every outgoing gRPC request. +/// +/// The product name is derived from the RPC method path so that each +/// backend receives the user agent it expects: +/// - OCP server (`/ocp.*`) → `OpenCodeProtocol/iOS/{version}` +/// - Flipcash server → `Flipcash/iOS/{version}` class UserAgentInterceptor: ClientInterceptor, @unchecked Sendable { override func send(_ part: GRPCClientRequestPart, promise: EventLoopPromise?, context: ClientInterceptorContext) { var modifiedPart = part switch modifiedPart { case .metadata(var headers): - headers.add(.userAgent, value: "Flipcash/iOS/\(AppMeta.version)") + let product = Self.productName(for: context.path) + headers.add(.userAgent, value: "\(product)/iOS/\(AppMeta.version)") modifiedPart = .metadata(headers) default: break } context.send(modifiedPart, promise: promise) } + + /// Returns the product name for the `User-Agent` header based on + /// the gRPC method path (e.g. `/ocp.transaction.v1.Transaction/SubmitIntent`). + private static func productName(for path: String) -> String { + if path.hasPrefix("/ocp.") { + return "OpenCodeProtocol" + } + return "Flipcash" + } } // MARK: - App -