You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)
    }
}

问题现象


获取真实请求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、请求头、请求体、响应体在内的全链路请求信息,适合全局排查问题:

  1. 先引入和项目OkHttp版本匹配的日志拦截器依赖:
// app模块build.gradle的dependencies块中添加
implementation "com.squareup.okhttp3:logging-interceptor:4.10.0"
  1. 初始化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 14:48:34