This repository was archived by the owner on Apr 20, 2023. It is now read-only.
Fix revalidation of gzipped JSON responses#86
Closed
victorges wants to merge 3 commits into
Closed
Conversation
e07a699 to
ca88c01
Compare
ca88c01 to
ee10211
Compare
On go:1.6 the error happens even on the original response from the server so the response is never added to the cache!
gregjones
reviewed
Nov 10, 2018
Owner
gregjones
left a comment
There was a problem hiding this comment.
Thanks for the thorough explanation! And the solution does seem nice - just a couple of things to double-check, please?
| resetTest() | ||
| { | ||
| req, err := http.NewRequest("GET", s.server.URL, nil) | ||
| req, err := http.NewRequest("GET", s.server.URL+"/method", nil) |
| return n, err | ||
| } | ||
|
|
||
| var dummyBuf = make([]byte, 1) |
Owner
There was a problem hiding this comment.
Can you help me be confident this is safe to be shared?
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
So investigating on a potential incompatibility between a server using https://github.com/NYTimes/gziphandler and a client using this middleware (or possibly more generically, with servers responding with some
Conten-Encoding) that lead to an increased latency in our infra, I came to a weird behavior for this very specific scenario described in the title. I am yet not sure this was the cause of the issue but I think the fix is worth doing anyway.The scenario is:
content-encoding: gzipand anETaghttpcachewrapper) already receives that response already uncompressed by thehttp.DefaultTransportin case that's the underlying transport.http.DefaultTransportalso removes anyContent-Lengththat has been set in the response, which results in a response with neitherContent-LengthorTransfer-Encoding. That scenarios is legal by HTTP definition as well so it's not inherently a bug (a response without either of those headers could arise directly from the server as well)Content-LengthorTransfer-Encodingis fully read fine on the first time and added to the cache.httputil.DumpResponseandhttp.ReadResponseare used in sequence though, the returned response has a different kind ofBodythat doesn't really return anio.EOFon the last byte from the response, but only after callingReadanother time only to get0bytes read. Not inherently a bug either.json.Decoderto read the JSON response, it will read from theio.Readeronly until the first JSON object is fully read and then stops the read. This means that the last call toReadthat would return0, io.EOFnever happens as all the bytes (that result in a valid JSON object) have already been read. Not inherently a bug either (probably desired behavior).cachingReadCloserto never call theOnEOFfunction for a response that had been fetched from the cache and revalidated with the server, which could lead of a continuous revalidation of a response that already had amax-agecombined with anETagfor example.TL;DR it's a combination of:
ETagorLastModifed) cached response.content-encodingwith anhttp.DefaultTransportfor automatic decompression (or apparently any response withoutContent-LengthnorTransfer-Encoding);json.Decoder(or anything that doesn't read fully untilio.EOF);This is a kind of specific scenario, but the fix to the actual code of the cache wrapper turned out pretty neat. It would seem fine for me to afford that small extra complexity to deal with the case.
The test feels a bit complex yet but I think that wouldn't be a problem, let me know of any other ideas to improve it!