From e6b84bc54802321ea181c31a0ab49add7cb6be14 Mon Sep 17 00:00:00 2001 From: vicanso Date: Wed, 28 Feb 2024 20:31:58 +0800 Subject: [PATCH] feat: support encoding fs static serve --- middleware/static_embed.go | 16 ++++++++++++---- middleware/static_serve.go | 32 +++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/middleware/static_embed.go b/middleware/static_embed.go index 095d562..e9380f9 100644 --- a/middleware/static_embed.go +++ b/middleware/static_embed.go @@ -28,6 +28,7 @@ import ( "bytes" "embed" "io" + "io/fs" "os" "path/filepath" "strings" @@ -109,20 +110,27 @@ type tarFS struct { Prefix string // tar file File string + // embed fs + Embed *embed.FS } var _ StaticFile = (*tarFS)(nil) // NewTarFS returns a new tar static fs -func NewTarFS(file string, prefix string) *tarFS { +func NewTarFS(file string) *tarFS { return &tarFS{ - Prefix: prefix, - File: file, + File: file, } } func (t *tarFS) get(file string, includeContent bool) (bool, []byte, error) { - f, err := os.Open(t.File) + var f fs.File + var err error + if t.Embed != nil { + f, err = t.Embed.Open(t.File) + } else { + f, err = os.Open(t.File) + } if err != nil { return false, nil, err } diff --git a/middleware/static_serve.go b/middleware/static_serve.go index 7f081ee..248a56c 100644 --- a/middleware/static_serve.go +++ b/middleware/static_serve.go @@ -85,6 +85,8 @@ type ( } ) +type EncodingFsSelector func(*elton.Context) (string, StaticFile) + const ( // ErrStaticServeCategory static serve error category ErrStaticServeCategory = "elton-static-serve" @@ -93,6 +95,8 @@ const ( var ( // ErrStaticServeNotAllowQueryString not all query string ErrStaticServeNotAllowQueryString = getStaticServeError("static serve not allow query string", http.StatusBadRequest) + // ErrStaticServeFsIsNil static fs is nil + ErrStaticServeFsIsNil = getStaticServeError("static fs is nil", http.StatusBadRequest) // ErrStaticServeNotFound static file not found ErrStaticServeNotFound = getStaticServeError("static file not found", http.StatusNotFound) // ErrStaticServeOutOfPath file out of path @@ -149,7 +153,7 @@ func generateETag(buf []byte) string { return fmt.Sprintf(`"%x-%s"`, size, hash) } -// NewDefaultStaticServe returns a new default static server milldeware using FS +// NewDefaultStaticServe returns a new default static server middleware using FS func NewDefaultStaticServe(config StaticServeConfig) elton.Handler { return NewStaticServe(&FS{}, config) } @@ -158,10 +162,7 @@ func toSeconds(d time.Duration) string { return strconv.Itoa(int(d.Seconds())) } -// NewStaticServe returns a new static serve middleware, suggest to set the MaxAge and SMaxAge for cache control for better performance. -// It will return an error if DenyDot is true and filename is start with '.'. -// It will return an error if DenyQueryString is true and the querystring is not empty. -func NewStaticServe(staticFile StaticFile, config StaticServeConfig) elton.Handler { +func NewEncodingStaticServe(config StaticServeConfig, selector EncodingFsSelector) elton.Handler { cacheArr := []string{ "public", } @@ -221,6 +222,10 @@ func NewStaticServe(staticFile StaticFile, config StaticServeConfig) elton.Handl if config.DenyQueryString && url.RawQuery != "" { return ErrStaticServeNotAllowQueryString } + encoding, staticFile := selector(c) + if staticFile == nil { + return ErrStaticServeFsIsNil + } // 如果有配置目录的index文件 if config.IndexFile != "" { fileInfo := staticFile.Stat(file) @@ -284,11 +289,15 @@ func NewStaticServe(staticFile StaticFile, config StaticServeConfig) elton.Handl } fileBuf = buf } + // set content encoding + if encoding != "" { + c.SetHeader(elton.HeaderContentEncoding, encoding) + } for k, v := range config.Header { c.AddHeader(k, v) } - // 未设置cache control - // 或文件符合正则 + // not set cache control + // or the file match no cache if cacheControl == "" || (noCacheRegexp != nil && noCacheRegexp.MatchString(file)) { c.NoCache() @@ -309,3 +318,12 @@ func NewStaticServe(staticFile StaticFile, config StaticServeConfig) elton.Handl return c.Next() } } + +// NewStaticServe returns a new static serve middleware, suggest to set the MaxAge and SMaxAge for cache control for better performance. +// It will return an error if DenyDot is true and filename is start with '.'. +// It will return an error if DenyQueryString is true and the query string is not empty. +func NewStaticServe(staticFile StaticFile, config StaticServeConfig) elton.Handler { + return NewEncodingStaticServe(config, func(ctx *elton.Context) (string, StaticFile) { + return "", staticFile + }) +}