diff --git a/client.go b/client.go index 520f74e..4181cf2 100644 --- a/client.go +++ b/client.go @@ -343,6 +343,14 @@ func WithRedirects(redirectFunc RedirectFunc) ClientOption { }) } +// WithDisableCompression configures the HTTP client to not automatically +// request compressed responses, and disables automatic response decompression. +func WithDisableCompression(ok bool) ClientOption { + return clientOptionFunc(func(opts *clientOptions) { + opts.disableCompression = ok + }) +} + // RedirectFunc is a function that advises an HTTP client on whether to // follow a redirect. The given req is the redirected request, based on // the server's previous status code and "Location" header, and the given @@ -390,6 +398,7 @@ type clientOptions struct { tlsHandshakeTimeout time.Duration defaultTimeout time.Duration requestTimeout time.Duration + disableCompression bool } func (opts *clientOptions) applyDefaults() { diff --git a/client_test.go b/client_test.go index 0be95f4..d57e5f6 100644 --- a/client_test.go +++ b/client_test.go @@ -207,6 +207,7 @@ func TestNewClient_TransportConfig(t *testing.T) { dialCount.Add(1) return defaultDialer.DialContext(ctx, network, addr) }), + WithDisableCompression(true), ) client3 := makeClient(t, ctx, transportOption) // all defaults, no explicitly configured backend @@ -225,6 +226,7 @@ func TestNewClient_TransportConfig(t *testing.T) { require.Equal(t, int64(1<<20), rtOpts.MaxResponseHeaderBytes) require.Zero(t, rtOpts.IdleConnTimeout) require.True(t, rtOpts.KeepWarm) + require.False(t, rtOpts.DisableCompression) // and check that settings were conveyed to round tripper as expected val, ok = latestResults.Load(addr1) require.True(t, ok) @@ -234,6 +236,7 @@ func TestNewClient_TransportConfig(t *testing.T) { require.Equal(t, 10*time.Second, transport.TLSHandshakeTimeout) require.Equal(t, int64(1<<20), transport.MaxResponseHeaderBytes) require.Zero(t, transport.IdleConnTimeout) + require.False(t, transport.DisableCompression) // no redirects sendGetRequest(t, ctx, client1, fmt.Sprintf("http://%s/redirect", addr1), expectRedirect("/foo")) @@ -254,6 +257,7 @@ func TestNewClient_TransportConfig(t *testing.T) { require.Equal(t, int64(1<<20), rtOpts.MaxResponseHeaderBytes) require.Zero(t, rtOpts.IdleConnTimeout) require.False(t, rtOpts.KeepWarm) + require.False(t, rtOpts.DisableCompression) // now try backend with the options sendGetRequest(t, ctx, client2, fmt.Sprintf("http://%s/foo", addr2), expectSuccess("got it")) @@ -271,6 +275,7 @@ func TestNewClient_TransportConfig(t *testing.T) { require.Equal(t, int64(10101), rtOpts.MaxResponseHeaderBytes) require.Equal(t, time.Second, rtOpts.IdleConnTimeout) require.True(t, rtOpts.KeepWarm) + require.True(t, rtOpts.DisableCompression) // and check that settings were conveyed to round tripper as expected val, ok = latestResults.Load(addr2) require.True(t, ok) @@ -282,6 +287,7 @@ func TestNewClient_TransportConfig(t *testing.T) { require.Equal(t, 5*time.Second, transport.TLSHandshakeTimeout) require.Equal(t, int64(10101), transport.MaxResponseHeaderBytes) require.Equal(t, time.Second, transport.IdleConnTimeout) + require.True(t, transport.DisableCompression) // This one allows redirects sendGetRequest(t, ctx, client2, fmt.Sprintf("http://%s/redirect3", addr2), expectSuccess("got it")) diff --git a/transport.go b/transport.go index b2ca9f6..3946662 100644 --- a/transport.go +++ b/transport.go @@ -105,6 +105,9 @@ type TransportConfig struct { // KeepWarm indicates that the round-tripper should try to keep a ready // network connection open to reduce any delays in processing a request. KeepWarm bool + // DisableCompression is used by the round-tripper to disable automatically + // requesting compressed content and decompressing transparently. + DisableCompression bool } func transportConfigFromOptions(opts *clientOptions) TransportConfig { @@ -116,6 +119,7 @@ func transportConfigFromOptions(opts *clientOptions) TransportConfig { IdleConnTimeout: opts.idleConnTimeout, TLSClientConfig: opts.tlsClientConfig, TLSHandshakeTimeout: opts.tlsHandshakeTimeout, + DisableCompression: opts.disableCompression, } } @@ -134,6 +138,7 @@ func (s simpleTransport) NewRoundTripper(_, _ string, opts TransportConfig) Roun TLSClientConfig: opts.TLSClientConfig, MaxResponseHeaderBytes: opts.MaxResponseHeaderBytes, ExpectContinueTimeout: 1 * time.Second, + DisableCompression: opts.DisableCompression, } // no way to populate pre-warm function since http.Transport doesn't provide // any way to do that :( @@ -151,7 +156,8 @@ func (s h2cTransport) NewRoundTripper(_, _ string, opts TransportConfig) RoundTr }, // We don't bother setting the TLS config, because h2c is plain-text only //TLSClientConfig: opts.TLSClientConfig, - MaxHeaderListSize: uint32(opts.MaxResponseHeaderBytes), + MaxHeaderListSize: uint32(opts.MaxResponseHeaderBytes), + DisableCompression: opts.DisableCompression, } return RoundTripperResult{RoundTripper: transport, Scheme: "http", Close: transport.CloseIdleConnections} }