Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enable automatic gzip compression of responses #731

Merged
merged 1 commit into from
Oct 5, 2018

Conversation

yob
Copy link
Contributor

@yob yob commented Oct 4, 2018

This unconditionally enables envoys gzip http_filter, which will compress responses if the request indicates it can handle it (via a "accept-encoding: gzip" request header).

I've enabled it with no options, which means it gets the defaults, as
listed here. In envoy 1.7.0, they're:

    {
      "memory_level": 5,
      "content_length": 30",
      "compression_level": "DEFAULT",
      "compression_strategy": "DEFAULT",
      "content_type": [“application/javascript”, “application/json”, “application/xhtml+xml”, “image/svg+xml”, “text/css”, “text/html”, “text/plain”, “text/xml”],
      "disable_on_etag_header": false,
      "remove_accept_encoding_header": false,
      "window_bits": 12
    }

Note the list of content types that will be compressed. It's possible some users will want to customise this list, but for now I haven't exposed that option.

Fixes #310

Signed-off-by: James Healy james@yob.id.au

This unconditionally enables envoys gzip http_filter[1], which will
compress responses if the request indicates it can handle it (via a
"accept-encoding: gzip" request header).

I've enabled it with no options, which means it gets the defaults, as
listed at [2]. In envoy 1.7.0, they're:

    {
      "memory_level": 5,
      "content_length": 30",
      "compression_level": "DEFAULT",
      "compression_strategy": "DEFAULT",
      "content_type": [“application/javascript”, “application/json”, “application/xhtml+xml”, “image/svg+xml”, “text/css”, “text/html”, “text/plain”, “text/xml”],
      "disable_on_etag_header": false,
      "remove_accept_encoding_header": false,
      "window_bits": 12
    }

Note the list of content types that will be compressed. It's possible
some users will want to customise this list, but for now I haven't
exposed that option.

Fixes projectcontour#310

[1] https://www.envoyproxy.io/docs/envoy/latest/configuration/http_filters/gzip_filter
[2] https://www.envoyproxy.io/docs/envoy/latest/api-v2/config/filter/http/gzip/v2/gzip.proto

Signed-off-by: James Healy <james@yob.id.au>
@yob
Copy link
Contributor Author

yob commented Oct 4, 2018

To test this, I built a docker image with this branch and pushed it to a test cluster on GKE. Behind contour was a mini nginx server that returned a plain text debugging response.

Unfortunately, compressed responses make curl unhappy and I'm not sure why.

A request with curl that doesn't opt-in to compression:

$ curl -v http://echo.yob.id.au
* Rebuilt URL to: http://echo.yob.id.au/
*   Trying 35.197.162.175...         
* TCP_NODELAY set         
* Connected to echo.yob.id.au (35.197.162.175) port 80 (#0)
> GET / HTTP/1.1         
> Host: echo.yob.id.au            
> User-Agent: curl/7.61.0
> Accept: */*           
>                           
< HTTP/1.1 200 OK            
< server: envoy                   
< date: Thu, 04 Oct 2018 15:16:20 GMT
< content-type: text/plain
< content-length: 150                       
< expires: Thu, 04 Oct 2018 15:16:20 GMT                                                    
< cache-control: no-cache
< x-envoy-upstream-service-time: 0
<                                    
Server address: 10.60.0.28:80
Server name: echo-5b6df77c7c-p4vnt
Date: 04/Oct/2018:15:16:21 +0000        
URI: /                   
Request ID: 4b1b93a6a6cd1d89d51ccd667aee4f2a

A request from curl that opts-in to compression:

$ curl -sH 'Accept-encoding: gzip' -vv http://echo.yob.id.au
* Rebuilt URL to: http://echo.yob.id.au/
*   Trying 35.197.162.175...         
* TCP_NODELAY set         
* Connected to echo.yob.id.au (35.197.162.175) port 80 (#0)
> GET / HTTP/1.1         
> Host: echo.yob.id.au            
> User-Agent: curl/7.61.0
> Accept: */*           
> Accept-encoding: gzip     
>                               
< HTTP/1.1 200 OK       
< server: envoy
< date: Thu, 04 Oct 2018 15:15:43 GMT                                                                                                                                                                                < content-type: text/plain  
< expires: Thu, 04 Oct 2018 15:15:43 GMT
< cache-control: no-cache       
< x-envoy-upstream-service-time: 0
< vary: Accept-Encoding                     
< content-encoding: gzip                                                                                                                                                                                            
< transfer-encoding: chunked
<                                                         
* Failed writing body (0 != 155)
* Failed writing data                                                                                    
* stopped the pause stream!                     
* Closing connection 0

With wget, compression not opted in to:

$ wget -O /dev/stdout -S --quiet http://echo.yob.id.au                                                                                                                        
  HTTP/1.1 200 OK
  server: envoy
  date: Thu, 04 Oct 2018 15:17:49 GMT
  content-type: text/plain
  content-length: 150
  expires: Thu, 04 Oct 2018 15:17:48 GMT
  cache-control: no-cache
  x-envoy-upstream-service-time: 0
Server address: 10.60.0.28:80
Server name: echo-5b6df77c7c-p4vnt
Date: 04/Oct/2018:15:17:49 +0000
URI: /
Request ID: 919cb84beda14c1fc21b7fb850792afe

With wget, compression opted in to:

$ wget -O /dev/stdout -S --compression=gzip --quiet http://echo.yob.id.au                                                                                                     
  HTTP/1.1 200 OK
  server: envoy
  date: Thu, 04 Oct 2018 15:17:12 GMT
  content-type: text/plain
  expires: Thu, 04 Oct 2018 15:17:11 GMT
  cache-control: no-cache
  x-envoy-upstream-service-time: 0
  vary: Accept-Encoding
  content-encoding: gzip
  transfer-encoding: chunked
Server address: 10.60.0.28:80
Server name: echo-5b6df77c7c-p4vnt
Date: 04/Oct/2018:15:17:12 +0000
URI: /

@davecheney
Copy link
Contributor

Thank you very much for this. I'm glad this was a simple change :)

@davecheney davecheney added this to the 0.7.0 milestone Oct 4, 2018
@yob
Copy link
Contributor Author

yob commented Oct 4, 2018

No worries, it was mostly out of self interest. We're migrating to contour, and had noticed a performance regression compared to our older infrastructure.

The error from curl is a worry though. I'd like to know why it's unhappy with gzipped responses.

@davecheney
Copy link
Contributor

@yob this looks fine to me. the curl error is caused, i think, by manually forcing the Accept-encoding header. This causes the remote to send back compressed data which causes curl to freak out because it doesn't want to write binary data to a file.

% curl -H "accept-encoding: gzip" https://httpbin.davecheney.com/encoding/utf8 > /tmp/t && file /tmp/t
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  7128    0  7128    0     0  30724      0 --:--:-- --:--:-- --:--:-- 30724
/tmp/t: gzip compressed data, max speed, from Unix

works fine.

My version of curl also supports a --compressed flag which handles compression transparently.

@davecheney davecheney merged commit 7321a9a into projectcontour:master Oct 5, 2018
@yob yob deleted the gzip-filter branch October 5, 2018 03:09
@bourquep
Copy link
Contributor

If I wanted to enable compression for another content type, how should I proceed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants