Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ type Config struct {

// Response headers to add to every static.
Response map[string]string `mapstructure:"response"`

// GzipEnabled determines if gzip compression is enabled for serving static files.
GzipEnabled bool `mapstructure:"gzip_enabled"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is a good name for the option. From my POV option name should be self-explanatory.
I think that we may remove that option at all and check the gzip header only.

}

// Valid returns nil if config is valid.
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.23
toolchain go1.23.4

require (
github.com/klauspost/compress v1.17.11
github.com/roadrunner-server/context v1.0.2
github.com/roadrunner-server/errors v1.4.1
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/roadrunner-server/context v1.0.2 h1:MSK6mjG2KsFKS1IoieMrY9Ia7SGxDGh/tagpBQxi1SE=
Expand Down
26 changes: 26 additions & 0 deletions plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package static

import (
"fmt"
"github.com/klauspost/compress/gzhttp"
"io"
"net/http"
"path"
"strings"
Expand Down Expand Up @@ -48,6 +50,9 @@ type Plugin struct {
forbiddenExtensions map[string]struct{}
// opentelemetry
prop propagation.TextMapPropagator

// gzipEnabled indicates if gzip compression is enabled for serving static files.
gzipEnabled bool
}

// Init must return configure service and return true if the service hasStatus enabled. Must return error in case of
Expand Down Expand Up @@ -79,6 +84,7 @@ func (s *Plugin) Init(cfg Configurer, log Logger) error {

s.log = log.NamedLogger(PluginName)
s.root = http.Dir(s.cfg.Dir)
s.gzipEnabled = s.cfg.GzipEnabled

// init forbidden
for i := 0; i < len(s.cfg.Forbid); i++ {
Expand Down Expand Up @@ -225,6 +231,26 @@ func (s *Plugin) Middleware(next http.Handler) http.Handler { //nolint:gocognit,
}
}

if s.gzipEnabled && strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
s.log.Debug("gzip compression requested")
// Skip compression for already compressed formats
contentType := http.DetectContentType(make([]byte, 512))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you detecting the content-type for the empty slice of bytes?

if strings.Contains(contentType, "image/") ||
strings.Contains(contentType, "video/") ||
strings.Contains(contentType, "audio/") {
s.log.Debug("skipping compression for already compressed content",
zap.String("type", contentType))
} else {
gzhttp.GzipHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, err := io.Copy(w, f)
if err != nil {
s.log.Error("failed to copy file to response: ", zap.Error(err))
}
})).ServeHTTP(w, r)
return
}
}

// we passed all checks - serve the file
http.ServeContent(w, r, finfo.Name(), finfo.ModTime(), f)
})
Expand Down