krakend-ce icon indicating copy to clipboard operation
krakend-ce copied to clipboard

krakend looses gzip encoding header when using plugin

Open hotlib opened this issue 4 years ago • 0 comments

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

hotlib avatar Jan 27 '21 09:01 hotlib