Looking at the code in CacheInterceptor
I see that response with the code 204 are not cached. Yet I believe 204 are cacheable as discussed here
We use 204
as a response to GET don't indicate an empty response and just recently noticed those are not cached.
There are a number of reasons why.
Technically, 204s are skipped because the intercept
method will only cache responses if promisesBody
returns true
:
if (response.promisesBody() && CacheStrategy.isCacheable(response, networkRequest)) {
// Offer this request to the cache.
As you might expect, promisesBody
returns false
for 204 responses, unless they have a Content-length
header, or chunked
transfer encoding:
/**
* Returns true if the response headers and status indicate that this response has a (possibly
* 0-length) body. See RFC 7231.
*/
...
val responseCode = code
if ((responseCode < HTTP_CONTINUE || responseCode >= 200) &&
responseCode != HTTP_NO_CONTENT &&
responseCode != HTTP_NOT_MODIFIED) {
return true
}
// If the Content-Length or Transfer-Encoding headers disagree with the response code, the
// response is malformed. For best compatibility, we honor the headers.
if (headersContentLength() != -1L ||
"chunked".equals(header("Transfer-Encoding"), ignoreCase = true)) {
return true
}
return false
To justify this decision, it's possible that OkHttp's general use case for a cache is to save re-sending large payloads, rather than keeping round-trips to the absolute minimum. In addition, 204 is valid as a response to a GET
, but more often used as a response to a POST
; it's possible that the design reflects knowledge of this heuristic.
Looking through relevant issues, there is one related to changing the default behaviour for certain status codes: OkHttp cache-by-default status codes out of date:
The spec wants these: 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501
which resulted in a test:
assertCached(true, 204);
However, due to the configuration of the mock server, the response used to test is:
HTTP/1.1 204 OK
...
Content-Length: 0
with exactly the unnecessary Content-Length
that its own detection requires, and which a valid response should not include.
It's a bug, which nobody who's run into this case has reported.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With