Gzip + HTTPs on Heroku?

Has anybody gotten gzip + HTTPS working on Heroku?

Jose showed that we can get Cowboy to gzip responses by setting compress: true under the endpoint config:

config :my_app, MyApp.Endpoint,
  http: [compress: true, ...],
  https: [compress: true, ...]

Setting http: [compress: true] works for me in development, but does not affect anything on Heroku, where we serve HTTPS.

However, setting https: [compress: true] is invalid; Cowboy expects to be given the certification information as well.

I don’t think this would be the way to do things on Heroku; my understanding is that Heroku terminates SSL within their infrastructure and speaks HTTP internally to applications. So it seems like from our app’s perspective, http should be the correct place to configure this.

Has anyone gotten this to work?

2 Likes

This works for hex.pm on Heroku: https://github.com/hexpm/hexpm/blob/master/config/prod.exs#L10.

What response sizes did you try it on? In the past at least, cowboy did not compress small response bodies, the limit was at 300 bytes iirc.

2 Likes

I found the problem! We’re using load_from_system_env: true, and Endpoint.init/2 was overwriting the :http key without adding compress: true. I updated it as follows:

def init(_key, config) do
  if config[:load_from_system_env] do
    port = System.get_env(
      "PORT"
     ) || raise "expected the PORT environment variable to be set"
    {:ok, Keyword.put(config, :http, [:inet6, port: port, compress: true])} # <-- compress
  else
    {:ok, config}
  end
end

That did the trick!

In the past at least, cowboy did not compress small response bodies, the limit was at 300 bytes iirc

Yes, now that it’s working, I do see small responses not being gzipped, but most of them have Content-Encoding: gzip.

Thanks @ericmj! :smile:

6 Likes