Skip to content

Commit

Permalink
Merge pull request #56 from le0pard/disable_compresion_settings
Browse files Browse the repository at this point in the history
Add ability to disable compression for thruster by env variable
  • Loading branch information
kevinmcconnell authored Feb 6, 2025
2 parents b701248 + 9a77a09 commit ba05db9
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 28 deletions.
39 changes: 20 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,25 +73,26 @@ configuration. But if you need to customize its behavior, there are a few
environment variables that you can set.

| Variable Name | Description | Default Value |
|-----------------------|---------------------------------------------------------|---------------|
| `TLS_DOMAIN` | Comma-separated list of domain names to use for TLS provisioning. If not set, TLS will be disabled. | None |
| `TARGET_PORT` | The port that your Puma server should run on. Thruster will set `PORT` to this value when starting your server. | 3000 |
| `CACHE_SIZE` | The size of the HTTP cache in bytes. | 64MB |
| `MAX_CACHE_ITEM_SIZE` | The maximum size of a single item in the HTTP cache in bytes. | 1MB |
| `X_SENDFILE_ENABLED` | Whether to enable X-Sendfile support. Set to `0` or `false` to disable. | Enabled |
| `MAX_REQUEST_BODY` | The maximum size of a request body in bytes. Requests larger than this size will be refused; `0` means no maximum size is enforced. | `0` |
| `STORAGE_PATH` | The path to store Thruster's internal state. Provisioned TLS certificates will be stored here, so that they will not need to be requested every time your application is started. | `./storage/thruster` |
| `BAD_GATEWAY_PAGE` | Path to an HTML file to serve when the backend server returns a 502 Bad Gateway error. If there is no file at the specific path, Thruster will serve an empty 502 response instead. Because Thruster boots very quickly, a custom page can be a useful way to show that your application is starting up. | `./public/502.html` |
| `HTTP_PORT` | The port to listen on for HTTP traffic. | 80 |
| `HTTPS_PORT` | The port to listen on for HTTPS traffic. | 443 |
| `HTTP_IDLE_TIMEOUT` | The maximum time in seconds that a client can be idle before the connection is closed. | 60 |
| `HTTP_READ_TIMEOUT` | The maximum time in seconds that a client can take to send the request headers and body. | 30 |
| `HTTP_WRITE_TIMEOUT` | The maximum time in seconds during which the client must read the response. | 30 |
| `ACME_DIRECTORY` | The URL of the ACME directory to use for TLS certificate provisioning. | `https://acme-v02.api.letsencrypt.org/directory` (Let's Encrypt production) |
| `EAB_KID` | The EAB key identifier to use when provisioning TLS certificates, if required. | None |
| `EAB_HMAC_KEY` | The Base64-encoded EAB HMAC key to use when provisioning TLS certificates, if required. | None |
| `FORWARD_HEADERS` | Whether to forward X-Forwarded-* headers from the client. | Disabled when running with TLS; enabled otherwise |
| `DEBUG` | Set to `1` or `true` to enable debug logging. | Disabled |
|-----------------------------|---------------------------------------------------------|---------------|
| `TLS_DOMAIN` | Comma-separated list of domain names to use for TLS provisioning. If not set, TLS will be disabled. | None |
| `TARGET_PORT` | The port that your Puma server should run on. Thruster will set `PORT` to this value when starting your server. | 3000 |
| `CACHE_SIZE` | The size of the HTTP cache in bytes. | 64MB |
| `MAX_CACHE_ITEM_SIZE` | The maximum size of a single item in the HTTP cache in bytes. | 1MB |
| `GZIP_COMPRESSION_ENABLED` | Whether to enable gzip compression for static assets. Set to `0` or `false` to disable. | Enabled |
| `X_SENDFILE_ENABLED` | Whether to enable X-Sendfile support. Set to `0` or `false` to disable. | Enabled |
| `MAX_REQUEST_BODY` | The maximum size of a request body in bytes. Requests larger than this size will be refused; `0` means no maximum size is enforced. | `0` |
| `STORAGE_PATH` | The path to store Thruster's internal state. Provisioned TLS certificates will be stored here, so that they will not need to be requested every time your application is started. | `./storage/thruster` |
| `BAD_GATEWAY_PAGE` | Path to an HTML file to serve when the backend server returns a 502 Bad Gateway error. If there is no file at the specific path, Thruster will serve an empty 502 response instead. Because Thruster boots very quickly, a custom page can be a useful way to show that your application is starting up. | `./public/502.html` |
| `HTTP_PORT` | The port to listen on for HTTP traffic. | 80 |
| `HTTPS_PORT` | The port to listen on for HTTPS traffic. | 443 |
| `HTTP_IDLE_TIMEOUT` | The maximum time in seconds that a client can be idle before the connection is closed. | 60 |
| `HTTP_READ_TIMEOUT` | The maximum time in seconds that a client can take to send the request headers and body. | 30 |
| `HTTP_WRITE_TIMEOUT` | The maximum time in seconds during which the client must read the response. | 30 |
| `ACME_DIRECTORY` | The URL of the ACME directory to use for TLS certificate provisioning. | `https://acme-v02.api.letsencrypt.org/directory` (Let's Encrypt production) |
| `EAB_KID` | The EAB key identifier to use when provisioning TLS certificates, if required. | None |
| `EAB_HMAC_KEY` | The Base64-encoded EAB HMAC key to use when provisioning TLS certificates, if required. | None |
| `FORWARD_HEADERS` | Whether to forward X-Forwarded-* headers from the client. | Disabled when running with TLS; enabled otherwise |
| `DEBUG` | Set to `1` or `true` to enable debug logging. | Disabled |

To prevent naming clashes with your application's own environment variables,
Thruster's environment variables can optionally be prefixed with `THRUSTER_`.
Expand Down
18 changes: 10 additions & 8 deletions internal/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ type Config struct {
UpstreamCommand string
UpstreamArgs []string

CacheSizeBytes int
MaxCacheItemSizeBytes int
XSendfileEnabled bool
MaxRequestBody int
CacheSizeBytes int
MaxCacheItemSizeBytes int
XSendfileEnabled bool
GzipCompressionEnabled bool
MaxRequestBody int

TLSDomains []string
ACMEDirectoryURL string
Expand Down Expand Up @@ -79,10 +80,11 @@ func NewConfig() (*Config, error) {
UpstreamCommand: os.Args[1],
UpstreamArgs: os.Args[2:],

CacheSizeBytes: getEnvInt("CACHE_SIZE", defaultCacheSize),
MaxCacheItemSizeBytes: getEnvInt("MAX_CACHE_ITEM_SIZE", defaultMaxCacheItemSizeBytes),
XSendfileEnabled: getEnvBool("X_SENDFILE_ENABLED", true),
MaxRequestBody: getEnvInt("MAX_REQUEST_BODY", defaultMaxRequestBody),
CacheSizeBytes: getEnvInt("CACHE_SIZE", defaultCacheSize),
MaxCacheItemSizeBytes: getEnvInt("MAX_CACHE_ITEM_SIZE", defaultMaxCacheItemSizeBytes),
XSendfileEnabled: getEnvBool("X_SENDFILE_ENABLED", true),
GzipCompressionEnabled: getEnvBool("GZIP_COMPRESSION_ENABLED", true),
MaxRequestBody: getEnvInt("MAX_REQUEST_BODY", defaultMaxRequestBody),

TLSDomains: getEnvStrings("TLS_DOMAIN", []string{}),
ACMEDirectoryURL: getEnvString("ACME_DIRECTORY", defaultACMEDirectoryURL),
Expand Down
2 changes: 2 additions & 0 deletions internal/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ func TestConfig_override_defaults_with_env_vars(t *testing.T) {
usingEnvVar(t, "CACHE_SIZE", "256")
usingEnvVar(t, "HTTP_READ_TIMEOUT", "5")
usingEnvVar(t, "X_SENDFILE_ENABLED", "0")
usingEnvVar(t, "GZIP_COMPRESSION_ENABLED", "0")
usingEnvVar(t, "DEBUG", "1")
usingEnvVar(t, "ACME_DIRECTORY", "https://acme-staging-v02.api.letsencrypt.org/directory")

Expand All @@ -123,6 +124,7 @@ func TestConfig_override_defaults_with_env_vars(t *testing.T) {
assert.Equal(t, 256, c.CacheSizeBytes)
assert.Equal(t, 5*time.Second, c.HttpReadTimeout)
assert.Equal(t, false, c.XSendfileEnabled)
assert.Equal(t, false, c.GzipCompressionEnabled)
assert.Equal(t, slog.LevelDebug, c.LogLevel)
assert.Equal(t, "https://acme-staging-v02.api.letsencrypt.org/directory", c.ACMEDirectoryURL)
}
Expand Down
5 changes: 4 additions & 1 deletion internal/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ type HandlerOptions struct {
maxRequestBody int
targetUrl *url.URL
xSendfileEnabled bool
gzipCompressionEnabled bool
forwardHeaders bool
}

func NewHandler(options HandlerOptions) http.Handler {
handler := NewProxyHandler(options.targetUrl, options.badGatewayPage, options.forwardHeaders)
handler = NewCacheHandler(options.cache, options.maxCacheableResponseBody, handler)
handler = NewSendfileHandler(options.xSendfileEnabled, handler)
handler = gzhttp.GzipHandler(handler)
if options.gzipCompressionEnabled {
handler = gzhttp.GzipHandler(handler)
}

if options.maxRequestBody > 0 {
handler = http.MaxBytesHandler(handler, int64(options.maxRequestBody))
Expand Down
25 changes: 25 additions & 0 deletions internal/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,30 @@ func TestHandlerGzipCompression_when_proxying(t *testing.T) {
assert.Less(t, transferredSize, fixtureLength("loremipsum.txt"))
}

func TestNotHandlerGzipCompression_when_disabled(t *testing.T) {
fixtureLength := strconv.FormatInt(fixtureLength("loremipsum.txt"), 10)

upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Length", fixtureLength)
w.Write(fixtureContent("loremipsum.txt"))
}))
defer upstream.Close()

options := handlerOptions(upstream.URL)
options.gzipCompressionEnabled = false
h := NewHandler(options)

w := httptest.NewRecorder()
r := httptest.NewRequest("GET", "/", nil)
r.Header.Set("Accept-Encoding", "gzip")
h.ServeHTTP(w, r)

assert.Equal(t, http.StatusOK, w.Code)
assert.Contains(t, w.Header().Get("Content-Type"), "text/plain")
assert.Empty(t, w.Header().Get("Content-Encoding"))
assert.Equal(t, fixtureLength, w.Header().Get("Content-Length"))
}

func TestHandlerGzipCompression_is_not_applied_when_not_requested(t *testing.T) {
fixtureLength := strconv.FormatInt(fixtureLength("loremipsum.txt"), 10)

Expand Down Expand Up @@ -248,6 +272,7 @@ func handlerOptions(targetUrl string) HandlerOptions {
cache: NewMemoryCache(defaultCacheSize, defaultMaxCacheItemSizeBytes),
targetUrl: url,
xSendfileEnabled: true,
gzipCompressionEnabled: true,
maxCacheableResponseBody: 1024,
badGatewayPage: "",
forwardHeaders: true,
Expand Down
1 change: 1 addition & 0 deletions internal/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func (s *Service) Run() int {
cache: s.cache(),
targetUrl: s.targetUrl(),
xSendfileEnabled: s.config.XSendfileEnabled,
gzipCompressionEnabled: s.config.GzipCompressionEnabled,
maxCacheableResponseBody: s.config.MaxCacheItemSizeBytes,
maxRequestBody: s.config.MaxRequestBody,
badGatewayPage: s.config.BadGatewayPage,
Expand Down

0 comments on commit ba05db9

Please sign in to comment.