krakend-ce
krakend-ce copied to clipboard
krakend looses gzip encoding header when using plugin
Describe the bug
I am experiencing strange behaviour. My setup is:
client ---> KrakenD + plugin (http/client/executor) ----> backend
When I request a gzip-ed response via the request header:
Accept-Encoding: gzip
The response does not contain the needed header:
Content-Encoding: gzip
which instructs the client to decode the gzip. Instead the response contains the header:
Content-Type: application/x-gzip
The plugin does nothing but forward the request as-is without changes and copies the response back. Among the copied response headers in the plugin I see:
Content-Encoding: gzip
so the plugin behaves correctly, but when the response is returned from KrakenD this needed header "Content-Encoding: gzip" is gone and is replaced with:
Content-Type: application/x-gzip
which is incorrect.
When I remove the plugin, KrakenD works and the needed header "Content-Encoding: gzip" is present.
Configuration
In the endpoint section I set:
"output_encoding": "no-op"
and in the backend section I set:
"encoding": "no-op"
and the backend service is responsible for setting the headers which it does correctly (i.e. "Content-Encoding: gzip" is present and the plugin copies this header to into the response). Unfortunately when the response leaves KrakenD the header "Content-Encoding: gzip" is no longer present and is replaced by the (incorrect) header "Content-Type: application/x-gzip" I can even hard-code the response header "Content-Encoding: gzip" via krakend-martian and then it works fine (which of course is a bad solution)
plugin snippet
response, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: unable to connect to backend, error: %v \n", err)
w.WriteHeader(500)
return
}
defer response.Body.Close()
bytes, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: unable to process response from backend, error: %v \n", err)
}
w.WriteHeader(response.StatusCode)
bytesWritten, err := w.Write(bytes)
if bytesWritten != len(bytes) || err != nil {
fmt.Fprintf(os.Stderr, "ERROR: unable to read the response from backend, error: %v bytes from backend %d bytes written %d \n", err, len(bytes), bytesWritten)
}
for key, vals := range response.Header {
for _, val := range vals {
w.Header().Add(key, val)
}
}
Expected behavior
KrakenD should not replace the correct header:
Content-Encoding: gzip
with the incorrect header:
Content-Type: application/x-gzip
Workaround
So far I am using a workaround which turns off gzip for responses (this solution works), but is not optimal. The configuration for turning off gzip at the endpoint is:
{
"header.Modifier": {
"scope": ["request"],
"name": "Accept-Encoding",
"value": "identity"
}
}