From 2f9a27b282dd2c7ea68ab2847a5408bdc9cb106d Mon Sep 17 00:00:00 2001 From: n0vad3v Date: Wed, 27 Nov 2024 14:14:26 +0800 Subject: [PATCH] Init 0.13.0 --- config/config.go | 32 +++++++++++++++++--------------- encoder/prefetch.go | 11 ++++++++++- handler/router.go | 10 ++++++++-- handler/router_test.go | 21 +++++++++++++++++++++ helper/helper.go | 10 +++++++++- helper/helper_test.go | 6 +++--- pics/config.json | 16 ++++++++++++++++ 7 files changed, 84 insertions(+), 22 deletions(-) create mode 100644 pics/config.json diff --git a/config/config.go b/config/config.go index e5ddc5f04..3eccbfa1d 100644 --- a/config/config.go +++ b/config/config.go @@ -43,20 +43,22 @@ const ( ) var ( - ConfigPath string - Jobs int - DumpSystemd bool - DumpConfig bool - ShowVersion bool - ProxyMode bool - Prefetch bool // Prefech in go-routine, with WebP Server Go launch normally - PrefetchForeground bool // Standalone prefetch, prefetch and exit - Config = NewWebPConfig() - Version = "0.12.3" - WriteLock = cache.New(5*time.Minute, 10*time.Minute) - ConvertLock = cache.New(5*time.Minute, 10*time.Minute) - LocalHostAlias = "local" - RemoteCache *cache.Cache + ConfigPath string + Jobs int + DumpSystemd bool + DumpConfig bool + ShowVersion bool + ProxyMode bool + Prefetch bool // Prefech in go-routine, with WebP Server Go launch normally + PrefetchForeground bool // Standalone prefetch, prefetch and exit + AllowNonImage bool + Config = NewWebPConfig() + Version = "0.13.0" + WriteLock = cache.New(5*time.Minute, 10*time.Minute) + ConvertLock = cache.New(5*time.Minute, 10*time.Minute) + LocalHostAlias = "local" + RemoteCache *cache.Cache + DefaultAllowedTypes = []string{"jpg", "png", "jpeg", "bmp", "gif", "svg", "nef", "heic"} // Default allowed image types ) type MetaFile struct { @@ -99,7 +101,7 @@ func NewWebPConfig() *WebpConfig { Port: "3333", ImgPath: "./pics", Quality: 80, - AllowedTypes: []string{"jpg", "png", "jpeg", "bmp", "gif", "svg", "nef", "heic", "webp"}, + AllowedTypes: DefaultAllowedTypes, ConvertTypes: []string{"webp"}, ImageMap: map[string]string{}, ExhaustPath: "./exhaust", diff --git a/encoder/prefetch.go b/encoder/prefetch.go index 91e22d1c3..b222b9471 100644 --- a/encoder/prefetch.go +++ b/encoder/prefetch.go @@ -33,9 +33,18 @@ func PrefetchImages() { if info.IsDir() { return nil } - if !helper.CheckAllowedType(picAbsPath) { + // Only convert files with image extensions, use smaller of config.DefaultAllowedTypes and config.Config.AllowedTypes + if helper.CheckAllowedExtension(picAbsPath) { + // File type is allowed by user, check if it is an image + if helper.CheckImageExtension(picAbsPath) { + // File is an image, continue + } else { + return nil + } + } else { return nil } + // RawImagePath string, ImgFilename string, reqURI string metadata := helper.ReadMetadata(picAbsPath, "", config.LocalHostAlias) avifAbsPath, webpAbsPath, jxlAbsPath := helper.GenOptimizedAbsPath(metadata, config.LocalHostAlias) diff --git a/handler/router.go b/handler/router.go index f115bde87..6010611db 100644 --- a/handler/router.go +++ b/handler/router.go @@ -59,14 +59,20 @@ func Convert(c *fiber.Ctx) error { log.Debugf("Incoming connection from %s %s %s", c.IP(), reqHostname, reqURIwithQuery) - if !helper.CheckAllowedType(filename) { + if !helper.CheckAllowedExtension(filename) { msg := "File extension not allowed! " + filename log.Warn(msg) c.Status(http.StatusBadRequest) - _ = c.Send([]byte(msg)) + _ = c.SendString(msg) return nil } + // Check if the file extension is allowed and not with image extension + // In this case we will serve the file directly + if helper.CheckAllowedExtension(filename) && !helper.CheckImageExtension(filename) { + return c.SendFile(path.Join(config.Config.ImgPath, reqURI)) + } + // Rewrite the target backend if a mapping rule matches the hostname if hostMap, hostMapFound := config.Config.ImageMap[reqHost]; hostMapFound { log.Debugf("Found host mapping %s -> %s", reqHostname, hostMap) diff --git a/handler/router_test.go b/handler/router_test.go index 94b296b42..7d5566ab5 100644 --- a/handler/router_test.go +++ b/handler/router_test.go @@ -195,12 +195,33 @@ func TestConvertNotAllowed(t *testing.T) { defer resp.Body.Close() assert.Contains(t, string(data), "File extension not allowed") + // not allowed, but we have the file, this should return File extension not allowed + url = "http://127.0.0.1:3333/config.json" + resp, data = requestToServer(url, app, chromeUA, acceptWebP) + defer resp.Body.Close() + assert.Contains(t, string(data), "File extension not allowed") + // not allowed, random file url = url + "hagdgd" resp, data = requestToServer(url, app, chromeUA, acceptWebP) defer resp.Body.Close() assert.Contains(t, string(data), "File extension not allowed") +} + +func TestConvertPassThrough(t *testing.T) { + setupParam() + config.Config.AllowedTypes = []string{"*"} + var app = fiber.New() + app.Get("/*", Convert) + + // not allowed, but we have the file, this should return File extension not allowed + url := "http://127.0.0.1:3333/config.json" + resp, data := requestToServer(url, app, chromeUA, acceptWebP) + defer resp.Body.Close() + assert.Equal(t, http.StatusOK, resp.StatusCode) + assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) + assert.Contains(t, string(data), "HOST") } func TestConvertProxyModeBad(t *testing.T) { diff --git a/helper/helper.go b/helper/helper.go index 974d69d9c..a9dce081d 100644 --- a/helper/helper.go +++ b/helper/helper.go @@ -84,7 +84,8 @@ func ImageExists(filename string) bool { return !info.IsDir() } -func CheckAllowedType(imgFilename string) bool { +// CheckAllowedExtension checks if the image extension is in the user's allowed types +func CheckAllowedExtension(imgFilename string) bool { if config.Config.AllowedTypes[0] == "*" { return true } @@ -93,6 +94,13 @@ func CheckAllowedType(imgFilename string) bool { return slices.Contains(config.Config.AllowedTypes, imgFilenameExtension) } +// CheckImageExtension checks if the image extension is in the WebP Server Go's default types +func CheckImageExtension(imgFilename string) bool { + imgFilenameExtension := strings.ToLower(path.Ext(imgFilename)) + imgFilenameExtension = strings.TrimPrefix(imgFilenameExtension, ".") // .jpg -> jpg + return slices.Contains(config.DefaultAllowedTypes, imgFilenameExtension) +} + func GenOptimizedAbsPath(metadata config.MetaFile, subdir string) (string, string, string) { webpFilename := fmt.Sprintf("%s.webp", metadata.Id) avifFilename := fmt.Sprintf("%s.avif", metadata.Id) diff --git a/helper/helper_test.go b/helper/helper_test.go index 645291dca..3448ff62b 100644 --- a/helper/helper_test.go +++ b/helper/helper_test.go @@ -37,13 +37,13 @@ func TestImageExists(t *testing.T) { }) } -func TestCheckAllowedType(t *testing.T) { +func TestCheckAllowedExtension(t *testing.T) { t.Run("not allowed type", func(t *testing.T) { - assert.False(t, CheckAllowedType("./helper_test.go")) + assert.False(t, CheckAllowedExtension("./helper_test.go")) }) t.Run("allowed type", func(t *testing.T) { - assert.True(t, CheckAllowedType("test.jpg")) + assert.True(t, CheckAllowedExtension("test.jpg")) }) } diff --git a/pics/config.json b/pics/config.json new file mode 100644 index 000000000..bb3e051b5 --- /dev/null +++ b/pics/config.json @@ -0,0 +1,16 @@ +{ + "HOST": "127.0.0.1", + "PORT": "3333", + "QUALITY": "80", + "IMG_PATH": "./pics", + "EXHAUST_PATH": "./exhaust", + "IMG_MAP": {}, + "ALLOWED_TYPES": ["jpg","png","jpeg","gif","bmp","svg","heic","nef"], + "CONVERT_TYPES": ["webp"], + "STRIP_METADATA": true, + "ENABLE_EXTRA_PARAMS": false, + "READ_BUFFER_SIZE": 4096, + "CONCURRENCY": 262144, + "DISABLE_KEEPALIVE": false, + "CACHE_TTL": 259200 +} \ No newline at end of file