Android使用Retrofit2发GET请求报500 如何获取其生成的完整请求URL
Retrofit获取真实请求URL排查500错误方案
问题相关代码
Retrofit接口定义
interface ApiChatService { @GET("ncs-chat-web/rest/v1/message") suspend fun getChatMessages( @Header("Authorization") jwtToken: String, @Query("page") page: Long, @Query("count") count: Int ): Response<List<ChatMessageApi>> }
接口调用实现
override suspend fun getChatMessages( jwtToken: String, page: Long ): OperationResult<List<ChatMessageApi>> { return try { val response: Response<List<ChatMessageApi>> = apiChatService.getChatMessages(normalizeJwtToken(jwtToken), page = page, count = MESSAGE_PAGE_SIZE) if (response.isSuccessful) { OperationResult(operationResult = Result.OK, resultObject = response.body()) } else { Log.d("ApiDatasourceImpl.getChatMessages", response.errorBody()?.string()?: "Empty error message") OperationResult( operationResult = Result.ERROR, operationInfo = response.errorBody()?.string() ) } } catch (e: Exception) { Log.d("ApiDatasourceImpl.getChatMessages", e.localizedMessage ?: "Empty error message") OperationResult(operationResult = Result.ERROR, operationInfo = e.localizedMessage) } }
问题现象
- Android端发起请求返回500状态码,提示
Internal server error - Postman请求https://my-server.com/ncs-chat-web/rest/v1/message?count=10&page=1可正常返回200状态码与预期响应数据
- 需求:获取Retrofit生成的实际请求URL,对比两端请求差异定位问题
获取真实请求URL的方法
方法1:从响应对象直接读取(零额外依赖)
不需要新增任何依赖,直接从Retrofit返回的Response对象中就能拿到最终发起请求的全量信息,在你现有代码的失败分支加日志即可:
if (response.isSuccessful) { OperationResult(operationResult = Result.OK, resultObject = response.body()) } else { // 读取真实请求URL和请求头 val realRequestUrl = response.raw().request.url.toString() val realRequestHeaders = response.raw().request.headers.toMultimap() Log.d("RetrofitDebug", "实际请求URL: $realRequestUrl") Log.d("RetrofitDebug", "实际请求头: $realRequestHeaders") // 注意:errorBody()的string()只能读取一次,先存到变量避免第二次读为空 val errorMsg = response.errorBody()?.string()?: "Empty error message" Log.d("ApiDatasourceImpl.getChatMessages", errorMsg) OperationResult( operationResult = Result.ERROR, operationInfo = errorMsg ) }
这个方式拿到的URL是Retrofit拼接完baseUrl、路径参数、Query参数后的最终请求地址,和实际发出去的完全一致。
方法2:添加OkHttp日志拦截器打印全量请求信息
Retrofit底层基于OkHttp发送请求,添加官方日志拦截器可以打印包括URL、请求头、请求体、响应体在内的全链路请求信息,适合全局排查问题:
- 先引入和项目OkHttp版本匹配的日志拦截器依赖:
// app模块build.gradle的dependencies块中添加 implementation "com.squareup.okhttp3:logging-interceptor:4.10.0"
- 初始化OkHttpClient时添加拦截器,配置日志级别为BODY即可打印完整信息:
val httpLoggingInterceptor = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY } val okHttpClient = OkHttpClient.Builder() .addInterceptor(httpLoggingInterceptor) // 保留原有配置:超时时间、证书配置、其他公共拦截器等 .build() // 把配置好的client传入Retrofit实例 val retrofit = Retrofit.Builder() .client(okHttpClient) // 保留原有配置:baseUrl、数据转换器等 .build()
配置完成后,所有Retrofit发起的请求都会在Logcat中以OkHttp为TAG打印完整日志,直接搜索即可看到真实请求信息。
常见问题排查点
拿到请求信息后优先对比以下差异,这类Postman正常端上500的问题大多由以下原因导致:
- 检查Retrofit的baseUrl配置,确认路径拼接正确,有没有多/少斜杠、重复拼接路径片段的问题
- 检查
normalizeJwtToken(jwtToken)返回的token值是否正确,有没有拼错Bearer前缀、多带空格、内容截断的问题,不少服务端token解析异常会返回500而非401 - 对比请求头差异,检查端上有没有自动添加Postman不存在的头,或者缺少Postman携带的必要头,比如
Accept、Content-Type等 - 检查传入的page、count参数值是否和Postman一致,有没有传异常值的情况
内容的提问来源于stack exchange,提问作者Alex Zhulin
相关产品推荐
相关产品推荐

