diff --git a/middleware/static_embed.go b/middleware/static_embed.go index 21c6d44..1ebf582 100644 --- a/middleware/static_embed.go +++ b/middleware/static_embed.go @@ -1,3 +1,4 @@ +//go:build go1.16 // +build go1.16 // Copyright (c) 2021 Tree Xie @@ -23,6 +24,7 @@ package middleware import ( + "archive/tar" "bytes" "embed" "io" @@ -31,6 +33,7 @@ import ( "strings" "github.com/vicanso/elton" + "github.com/vicanso/hes" ) type embedStaticFS struct { @@ -39,7 +42,7 @@ type embedStaticFS struct { FS embed.FS } -// NewEmbedStaticFS resturns a new embed static fs +// NewEmbedStaticFS returns a new embed static fs func NewEmbedStaticFS(fs embed.FS, prefix string) *embedStaticFS { return &embedStaticFS{ Prefix: prefix, @@ -47,9 +50,13 @@ func NewEmbedStaticFS(fs embed.FS, prefix string) *embedStaticFS { } } -func (es *embedStaticFS) getFile(file string) string { +func getFile(prefix string, file string) string { windowsPathSeparator := "\\" - return strings.ReplaceAll(filepath.Join(es.Prefix, file), windowsPathSeparator, "/") + return strings.ReplaceAll(filepath.Join(prefix, file), windowsPathSeparator, "/") +} + +func (es *embedStaticFS) getFile(file string) string { + return getFile(es.Prefix, file) } // Exists check the file exists @@ -94,3 +101,83 @@ func (es *embedStaticFS) SendFile(c *elton.Context, file string) error { c.BodyBuffer = bytes.NewBuffer(buf) return nil } + +type tarFS struct { + // prefix of file + Prefix string + // tar file + File string +} + +// NewTarFS returns a new tar static fs +func NewTarFS(file string, prefix string) *tarFS { + return &tarFS{ + Prefix: prefix, + File: file, + } +} + +func (t *tarFS) get(file string, includeContent bool) (bool, []byte, error) { + f, err := os.Open(t.File) + if err != nil { + return false, nil, err + } + defer f.Close() + tr := tar.NewReader(f) + var data []byte + found := false + file = getFile(t.Prefix, file) + for { + hdr, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return false, nil, err + } + if hdr.Name == file { + found = true + if includeContent { + buf, err := io.ReadAll(tr) + if err != nil { + return false, nil, err + } + data = buf + } + break + } + } + return found, data, nil +} + +// Exists check the file exists +func (t *tarFS) Exists(file string) bool { + found, _, _ := t.get(file, false) + return found +} + +// Get returns content of file +func (t *tarFS) Get(file string) ([]byte, error) { + found, data, err := t.get(file, true) + if err != nil { + return nil, err + } + if !found { + return nil, hes.NewWithStatusCode("Not Found", 404) + } + return data, nil +} + +// Stat return nil for file stat +func (t *tarFS) Stat(file string) os.FileInfo { + return nil +} + +// NewReader returns a reader of file +func (t *tarFS) NewReader(file string) (io.Reader, error) { + buf, err := t.Get(file) + if err != nil { + return nil, err + } + return bytes.NewReader(buf), nil +} diff --git a/middleware/static_serve.go b/middleware/static_serve.go index 67532d2..7f081ee 100644 --- a/middleware/static_serve.go +++ b/middleware/static_serve.go @@ -276,9 +276,6 @@ func NewStaticServe(staticFile StaticFile, config StaticServeConfig) elton.Handl } } - for k, v := range config.Header { - c.AddHeader(k, v) - } // 如果有设置before response if config.BeforeResponse != nil && fileBuf != nil { buf, err := config.BeforeResponse(file, fileBuf) @@ -287,6 +284,9 @@ func NewStaticServe(staticFile StaticFile, config StaticServeConfig) elton.Handl } fileBuf = buf } + for k, v := range config.Header { + c.AddHeader(k, v) + } // 未设置cache control // 或文件符合正则 if cacheControl == "" ||