Android GRPC客户端调用子目录服务遇404问题求助
Android gRPC客户端调用子目录API时404的解决方法
调用部署在子目录/subdirectory_path下的gRPC流式API时返回404,错误显示invalid content-type: text/html,说明请求未正确命中gRPC服务端点,而是被导向了错误页面。核心问题是当前Android客户端的通道配置未正确将子目录路径添加到gRPC请求的URL前缀中。
错误代码分析
你当前的代码将uri.host+uri.path作为目标传给ManagedChannelBuilder.forTarget,这是错误用法:
val uri = Uri.parse("https://examplegrpcserver.com/subdirectory_path") private val channel = let { val builder = ManagedChannelBuilder.forTarget(uri.host+uri.path) // 错误:forTarget应传入主机地址,而非带路径的字符串 // ... builder.build() }
forTarget的参数仅需主机地址(如examplegrpcserver.com),gRPC默认会将服务和方法名拼在根路径下,导致子目录路径被完全忽略,最终请求路径不符合服务端预期。
解决方案:添加路径前缀拦截器
通过自定义ClientInterceptor修改gRPC请求的完整方法路径,为其添加子目录前缀,实现和Web端SubdirectoryHandler相同的效果:
- 实现路径前缀拦截器:
class PathPrefixInterceptor(private val prefix: String) : ClientInterceptor { override fun <ReqT : Any?, RespT : Any?> interceptCall( method: MethodDescriptor<ReqT, RespT>, callOptions: CallOptions, next: Channel ): ClientCall<ReqT, RespT> { // 为gRPC方法路径添加子目录前缀 val prefixedMethod = method.toBuilder() .setFullMethodName("$prefix${method.fullMethodName}") .build() return next.newCall(prefixedMethod, callOptions) } }
- 修改通道配置,添加拦截器:
val uri = Uri.parse("https://examplegrpcserver.com/subdirectory_path") private val channel = let { val builder = ManagedChannelBuilder.forTarget(uri.host) .apply { if (uri.scheme == "https") { useTransportSecurity() } else { usePlaintext() } // 注册路径前缀拦截器,传入子目录路径 intercept(PathPrefixInterceptor(uri.path)) executor(Dispatchers.IO.asExecutor()) } builder.build() }
原理说明
gRPC请求的默认路径格式为/包名.服务名/方法名,通过拦截器修改MethodDescriptor的fullMethodName,将子目录路径/subdirectory_path拼接在前面,最终请求路径变为/subdirectory_path/包名.服务名/方法名,完全匹配服务端的部署路径,即可解决404问题。
内容的提问来源于stack exchange,提问作者FurElise
相关产品推荐
相关产品推荐

