Skip to content

Commit

Permalink
refactor: refactor gzipHandler to use config struct instead of Option…
Browse files Browse the repository at this point in the history
…s struct

- Rename `Options` to `config` in `gzipHandler` struct
- Initialize `config` in `newGzipHandler` function
- Apply options to `config` in `newGzipHandler` function
- Remove `Options` initialization and application in `newGzipHandler`
- Rename fields in `gzipHandler` to use camelCase
- Add comments to explain `DefaultExcludedExtentions` and `Option` interface
- Replace `Options` struct with `config` struct
- Ensure `optionFunc` implements `Option` interface
- Update `WithExcludedExtensions`, `WithExcludedPaths`, `WithExcludedPathsRegexs`, `WithDecompressFn`, and `WithDecompressOnly` functions to use `config` instead of `Options`

Signed-off-by: appleboy <[email protected]>
  • Loading branch information
appleboy committed Jan 12, 2025
1 parent eae4239 commit 9bb40fc
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 41 deletions.
28 changes: 17 additions & 11 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,22 @@ import (
)

type gzipHandler struct {
*Options
*config
gzPool sync.Pool
}

func newGzipHandler(level int, options ...Option) *gzipHandler {
func newGzipHandler(level int, opts ...Option) *gzipHandler {
cfg := &config{
excludedExtensions: DefaultExcludedExtentions,
}

// Apply each option to the config
for _, o := range opts {
o.apply(cfg)
}

handler := &gzipHandler{
Options: DefaultOptions,
config: cfg,
gzPool: sync.Pool{
New: func() interface{} {
gz, err := gzip.NewWriterLevel(io.Discard, level)
Expand All @@ -30,18 +39,15 @@ func newGzipHandler(level int, options ...Option) *gzipHandler {
},
},
}
for _, setter := range options {
setter(handler.Options)
}
return handler
}

func (g *gzipHandler) Handle(c *gin.Context) {
if fn := g.DecompressFn; fn != nil && c.Request.Header.Get("Content-Encoding") == "gzip" {
if fn := g.decompressFn; fn != nil && c.Request.Header.Get("Content-Encoding") == "gzip" {
fn(c)
}

if g.DecompressOnly || !g.shouldCompress(c.Request) {
if g.decompressOnly || !g.shouldCompress(c.Request) {
return
}

Expand Down Expand Up @@ -71,14 +77,14 @@ func (g *gzipHandler) shouldCompress(req *http.Request) bool {
}

extension := filepath.Ext(req.URL.Path)
if g.ExcludedExtensions.Contains(extension) {
if g.excludedExtensions.Contains(extension) {
return false
}

if g.ExcludedPaths.Contains(req.URL.Path) {
if g.excludedPaths.Contains(req.URL.Path) {
return false
}
if g.ExcludedPathesRegexs.Contains(req.URL.Path) {
if g.excludedPathesRegexs.Contains(req.URL.Path) {
return false
}

Expand Down
73 changes: 43 additions & 30 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,69 +9,82 @@ import (
"github.com/gin-gonic/gin"
)

var (
DefaultExcludedExtentions = NewExcludedExtensions([]string{
".png", ".gif", ".jpeg", ".jpg",
})
DefaultOptions = &Options{
ExcludedExtensions: DefaultExcludedExtentions,
}
)
// DefaultExcludedExtentions is a predefined list of file extensions that should be excluded from gzip compression.
// These extensions typically represent image files that are already compressed
// and do not benefit from additional compression.
var DefaultExcludedExtentions = NewExcludedExtensions([]string{
".png", ".gif", ".jpeg", ".jpg",
})

// Option is an interface that defines a method to apply a configuration
// to a given config instance. Implementations of this interface can be
// used to modify the configuration settings of the logger.
type Option interface {
apply(*config)
}

// Ensures that optionFunc implements the Option interface at compile time.
// If optionFunc does not implement Option, a compile-time error will occur.
var _ Option = (*optionFunc)(nil)

type Options struct {
ExcludedExtensions ExcludedExtensions
ExcludedPaths ExcludedPaths
ExcludedPathesRegexs ExcludedPathesRegexs
DecompressFn func(c *gin.Context)
DecompressOnly bool
type optionFunc func(*config)

func (o optionFunc) apply(c *config) {
o(c)
}

type Option func(*Options)
type config struct {
excludedExtensions ExcludedExtensions
excludedPaths ExcludedPaths
excludedPathesRegexs ExcludedPathesRegexs
decompressFn func(c *gin.Context)
decompressOnly bool
}

// WithExcludedExtensions returns an Option that sets the ExcludedExtensions field of the Options struct.
// Parameters:
// - args: []string - A slice of file extensions to exclude from gzip compression.
func WithExcludedExtensions(args []string) Option {
return func(o *Options) {
o.ExcludedExtensions = NewExcludedExtensions(args)
}
return optionFunc(func(o *config) {
o.excludedExtensions = NewExcludedExtensions(args)
})
}

// WithExcludedPaths returns an Option that sets the ExcludedPaths field of the Options struct.
// Parameters:
// - args: []string - A slice of paths to exclude from gzip compression.
func WithExcludedPaths(args []string) Option {
return func(o *Options) {
o.ExcludedPaths = NewExcludedPaths(args)
}
return optionFunc(func(o *config) {
o.excludedPaths = NewExcludedPaths(args)
})
}

// WithExcludedPathsRegexs returns an Option that sets the ExcludedPathesRegexs field of the Options struct.
// Parameters:
// - args: []string - A slice of regex patterns to exclude paths from gzip compression.
func WithExcludedPathsRegexs(args []string) Option {
return func(o *Options) {
o.ExcludedPathesRegexs = NewExcludedPathesRegexs(args)
}
return optionFunc(func(o *config) {
o.excludedPathesRegexs = NewExcludedPathesRegexs(args)
})
}

// WithDecompressFn returns an Option that sets the DecompressFn field of the Options struct.
// Parameters:
// - decompressFn: func(c *gin.Context) - A function to handle decompression of incoming requests.
func WithDecompressFn(decompressFn func(c *gin.Context)) Option {
return func(o *Options) {
o.DecompressFn = decompressFn
}
return optionFunc(func(o *config) {
o.decompressFn = decompressFn
})
}

// WithDecompressOnly is an option that configures the gzip middleware to only
// decompress incoming requests without compressing the responses. When this
// option is enabled, the middleware will set the DecompressOnly field of the
// Options struct to true.
func WithDecompressOnly() Option {
return func(o *Options) {
o.DecompressOnly = true
}
return optionFunc(func(o *config) {
o.decompressOnly = true
})
}

// Using map for better lookup performance
Expand Down

0 comments on commit 9bb40fc

Please sign in to comment.