【问题标题】:Issues trying to use If-None-Match with Etag in Android尝试在 Android 中将 If-None-Match 与 Etag 一起使用时出现问题
【发布时间】:2021-01-10 01:34:24
【问题描述】:

当它应该是 304 时总是返回代码 200(响应正常)。

这是我的示例代码。

import okhttp3.ResponseBody
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Streaming
import retrofit2.http.Url

interface DownloadService {
    @Streaming
    @GET
    suspend fun downloadResourceIfNoneMatch(
        @Url url: String,
        @Header("If-None-Match") vararg eTags: String
    ): Response<ResponseBody?>
}

这是我正在使用的 OkHttpClient:

val cacheSize: Long = 10 * 1024 * 1024 // 100 MB
val cache = Cache(context.cacheDir, cacheSize)
val cacheControlInterceptor = CacheControlInterceptor(context)
return OkHttpClient.Builder()
    .cache(cache)
    .addInterceptor(cacheControlInterceptor)
    .addNetworkInterceptor(cacheControlInterceptor)
    .addNetworkInterceptor(loggingInterceptor)
    .build()

这是我的 CacheControlInterceptor 类:

import android.content.Context
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
import timber.log.Timber
import java.io.IOException

class CacheControlInterceptor constructor(val context: Context) : Interceptor {
    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        Timber.d("cache control interceptor")
        var request: Request = chain.request()
        if (request.method == "GET") {
            request = request.newBuilder()
                .build()
        }
        val originalResponse: Response = chain.proceed(request)
        return originalResponse.newBuilder()
            .header("Cache-Control", "private, must-revalidate")
            .build()
    }
}

这是我提出请求的方式:

val response: Response<ResponseBody?> = downloadService.downloadResourceIfNoneMatch(downloadUrl, "2377a02e14b7df5100ee9ffebbb8443a")

我正在使用硬编码的 ETag 进行测试。当请求发出两次时,它不会显示预期的行为(即响应代码 304)。重复请求导致空缓存响应和响应代码 200。

我看到了预期的调试日志输出,所以看起来 CacheControlInceptor 正在正确实例化。我在回复中收到了 ETag。响应在上下文的缓存目录中正确缓存。我不知道出了什么问题。

【问题讨论】:

    标签: android caching retrofit2 okhttp etag


    【解决方案1】:

    除非您完全阅读,否则 OkHttp 不会将响应保存到缓存中。它写入缓存作为读取响应正文的副作用。

    如果在响应正文完成之前停止读取,OkHttp 没有完整的响应来存储,缓存条目将不可用。

    【讨论】:

    • 我看到一个类似问题的类似答案。这并没有真正帮助我,因为我相信我正在发布阅读整个响应正文(尽管我可能是错的)。我正在阅读完整的回复并在完成后关闭流。有没有办法检查响应是否已被完整阅读?您是否碰巧知道 OkHttp 缓存在设备文件中的位置,也许我可以仔细检查一下?我假设它将存储在内部应用程序文件中用户指定的缓存文件夹中。
    • 您可以使用事件侦听器 API 查看所有事件,包括缓存 square.github.io/okhttp/caching。它可以提供进一步的解释。
    猜你喜欢
    • 1970-01-01
    • 2016-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-27
    • 1970-01-01
    • 2020-05-05
    • 1970-01-01
    相关资源
    最近更新 更多