From f55a3e7fce9abab43642a074aac5ec4cdf111e9f Mon Sep 17 00:00:00 2001 From: Ingo Oppermann Date: Fri, 22 Nov 2024 16:11:22 +0100 Subject: [PATCH] Allow to provide mime type mapping directly in config --- app/api/api.go | 1 + config/config.go | 24 +++++++++++++++++++++++- config/copy/copy.go | 16 ++++++---------- config/data.go | 3 ++- http/middleware/mime/mime.go | 11 ++++++++++- http/server.go | 4 ++++ 6 files changed, 46 insertions(+), 13 deletions(-) diff --git a/app/api/api.go b/app/api/api.go index 5fab94ec..9e792a2d 100644 --- a/app/api/api.go +++ b/app/api/api.go @@ -1476,6 +1476,7 @@ func (a *api) start(ctx context.Context) error { Metrics: a.metrics, Prometheus: a.prom, MimeTypesFile: cfg.Storage.MimeTypesFile, + MimeTypes: cfg.Storage.MimeTypes, Filesystems: httpfilesystems, IPLimiter: iplimiter, Profiling: cfg.Debug.Profiling, diff --git a/config/config.go b/config/config.go index a878065b..4c0cfd61 100644 --- a/config/config.go +++ b/config/config.go @@ -128,6 +128,7 @@ func (d *Config) Clone() *Config { data.Storage.Disk.Cache.Types.Allow = slices.Copy(d.Storage.Disk.Cache.Types.Allow) data.Storage.Disk.Cache.Types.Block = slices.Copy(d.Storage.Disk.Cache.Types.Block) data.Storage.S3 = slices.Copy(d.Storage.S3) + data.Storage.MimeTypes = copy.StringMap(d.Storage.MimeTypes) data.FFmpeg.Access.Input.Allow = slices.Copy(d.FFmpeg.Access.Input.Allow) data.FFmpeg.Access.Input.Block = slices.Copy(d.FFmpeg.Access.Input.Block) @@ -212,7 +213,28 @@ func (d *Config) init() { d.vars.Register(value.NewFile(&d.TLS.KeyFile, "", d.fs), "tls.key_file", "CORE_TLS_KEY_FILE", []string{"CORE_TLS_KEYFILE"}, "Path to key file in PEM format", false, false) // Storage - d.vars.Register(value.NewFile(&d.Storage.MimeTypesFile, "./mime.types", d.fs), "storage.mimetypes_file", "CORE_STORAGE_MIMETYPES_FILE", []string{"CORE_MIMETYPES_FILE"}, "Path to file with mime-types", false, false) + d.vars.Register(value.NewFile(&d.Storage.MimeTypesFile, "", d.fs), "storage.mimetypes_file", "CORE_STORAGE_MIMETYPES_FILE", []string{"CORE_MIMETYPES_FILE"}, "Path to file with mime-types, takes precedence over storage.mimetypes", false, false) + d.vars.Register(value.NewStringMapString(&d.Storage.MimeTypes, map[string]string{ + ".txt": "text/plain", + ".htm": "text/html", + ".html": "text/html", + ".js": "text/javascript", + ".css": "text/css", + ".json": "application/json", + ".m3u8": "application/vnd.apple.mpegurl", + ".xml": "application/xml", + ".ts": "video/MP2T", + ".mp4": "video/mp4", + ".jpg": "image/jpeg", + ".jpeg": "image/jpeg", + ".png": "image/png", + ".gif": "image/gif", + ".svg": "image/svg+xml", + ".ico": "image/vnd.microsoft.icon", + ".ttf": "font/ttf", + ".woff": "font/woff", + ".woff2": "font/woff2", + }), "storage.mimetypes", "CORE_STORAGE_MIMETYPES", nil, "List of extension to mime-type mappings", false, false) // Storage (Disk) d.vars.Register(value.NewMustDir(&d.Storage.Disk.Dir, "./data", d.fs), "storage.disk.dir", "CORE_STORAGE_DISK_DIR", nil, "Directory on disk, exposed on /", false, false) diff --git a/config/copy/copy.go b/config/copy/copy.go index ac48db13..8ef94fe7 100644 --- a/config/copy/copy.go +++ b/config/copy/copy.go @@ -1,25 +1,21 @@ package copy import ( + "maps" + "slices" + "github.com/datarhei/core/v16/config/value" - "github.com/datarhei/core/v16/slices" ) func StringMap(src map[string]string) map[string]string { - dst := make(map[string]string) - - for k, v := range src { - dst[k] = v - } - - return dst + return maps.Clone(src) } func TenantSlice(src []value.Auth0Tenant) []value.Auth0Tenant { - dst := slices.Copy(src) + dst := slices.Clone(src) for i, t := range src { - dst[i].Users = slices.Copy(t.Users) + dst[i].Users = slices.Clone(t.Users) } return dst diff --git a/config/data.go b/config/data.go index f7f057cf..be8b3ebb 100644 --- a/config/data.go +++ b/config/data.go @@ -105,7 +105,8 @@ type Data struct { CORS struct { Origins []string `json:"origins"` } `json:"cors"` - MimeTypesFile string `json:"mimetypes_file"` + MimeTypesFile string `json:"mimetypes_file"` + MimeTypes map[string]string `json:"mimetypes"` } `json:"storage"` RTMP struct { Enable bool `json:"enable"` diff --git a/http/middleware/mime/mime.go b/http/middleware/mime/mime.go index c346aa98..31767c8a 100644 --- a/http/middleware/mime/mime.go +++ b/http/middleware/mime/mime.go @@ -3,6 +3,7 @@ package mime import ( "bufio" + "maps" "os" "path/filepath" "strings" @@ -17,6 +18,7 @@ type Config struct { Skipper middleware.Skipper MimeTypesFile string + MimeTypes map[string]string DefaultContentType string } @@ -24,6 +26,7 @@ type Config struct { var DefaultConfig = Config{ Skipper: middleware.DefaultSkipper, MimeTypesFile: "", + MimeTypes: map[string]string{}, DefaultContentType: "application/data", } @@ -36,7 +39,13 @@ func NewWithConfig(config Config) echo.MiddlewareFunc { config.Skipper = DefaultConfig.Skipper } - mimeTypes := loadMimeFile(config.MimeTypesFile) + mimeTypes := map[string]string{} + + if len(config.MimeTypesFile) != 0 { + mimeTypes = loadMimeFile(config.MimeTypesFile) + } else { + mimeTypes = maps.Clone(config.MimeTypes) + } return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { diff --git a/http/server.go b/http/server.go index c7dc68ab..0dd84797 100644 --- a/http/server.go +++ b/http/server.go @@ -89,6 +89,7 @@ type Config struct { Metrics monitor.HistoryReader Prometheus prometheus.Reader MimeTypesFile string + MimeTypes map[string]string Filesystems []fs.FS IPLimiter net.IPLimitValidator Profiling bool @@ -162,6 +163,7 @@ type server struct { router *echo.Echo mimeTypesFile string + mimeTypes map[string]string profiling bool readOnly bool @@ -184,6 +186,7 @@ func NewServer(config Config) (serverhandler.Server, error) { s := &server{ logger: config.Logger, mimeTypesFile: config.MimeTypesFile, + mimeTypes: config.MimeTypes, profiling: config.Profiling, readOnly: config.ReadOnly, } @@ -529,6 +532,7 @@ func (s *server) setRoutes() { fs := s.router.Group(mountpoint) fs.Use(mwmime.NewWithConfig(mwmime.Config{ MimeTypesFile: s.mimeTypesFile, + MimeTypes: s.mimeTypes, DefaultContentType: filesystem.DefaultContentType, }))