From eea4537f2204ed2bf07eeca0aa5d62b4d6182798 Mon Sep 17 00:00:00 2001 From: Nova Kwok Date: Mon, 3 Jul 2023 16:57:47 +0800 Subject: [PATCH] iOS 16 supports AVIF and WebP (#242) * iOS 16 supports AVIF and WebP * iOS 17 should support WebP and AVIF too * Determine image type by GetFileContentType --- handler/router.go | 11 +++++------ helper/helper.go | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/handler/router.go b/handler/router.go index e84ffd2..5793f80 100644 --- a/handler/router.go +++ b/handler/router.go @@ -3,7 +3,7 @@ package handler import ( "net/http" "net/url" - "strings" + "os" "webp_server_go/config" "webp_server_go/encoder" "webp_server_go/helper" @@ -93,11 +93,10 @@ func Convert(c *fiber.Ctx) error { } finalFilename := helper.FindSmallestFiles(availableFiles) - if strings.HasSuffix(finalFilename, ".webp ") { - c.Set("Content-Type", "image/webp") - } else if strings.HasSuffix(finalFilename, ".avif") { - c.Set("Content-Type", "image/avif") - } + + buf, _ := os.ReadFile(finalFilename) + contentType := helper.GetFileContentType(buf) + c.Set("Content-Type", contentType) c.Set("X-Compression-Rate", helper.GetCompressionRate(rawImageAbs, finalFilename)) return c.SendFile(finalFilename) diff --git a/helper/helper.go b/helper/helper.go index fecea57..c956337 100644 --- a/helper/helper.go +++ b/helper/helper.go @@ -1,9 +1,8 @@ package helper import ( + "bytes" "fmt" - "github.com/cespare/xxhash" - "github.com/valyala/fasthttp" "os" "path" "path/filepath" @@ -11,9 +10,35 @@ import ( "time" "webp_server_go/config" + "github.com/cespare/xxhash" + "github.com/h2non/filetype" + "github.com/valyala/fasthttp" + log "github.com/sirupsen/logrus" ) +func avifMatcher(buf []byte) bool { + // use hexdump on macOS to see the magic number + // 0000001c 66747970 61766966 00000000 61766966 6d696631 6d696166 + magicHeader := []byte{ + 0x0, 0x0, 0x0, 0x1c, + 0x66, 0x74, 0x79, 0x70, + 0x61, 0x76, 0x69, 0x66, + 0x0, 0x0, 0x0, 0x0, + 0x61, 0x76, 0x69, 0x66, + 0x6d, 0x69, 0x66, 0x31, + 0x6d, 0x69, 0x61, 0x66, + } + + return len(buf) > 1 && bytes.Equal(buf[:28], magicHeader) || strings.Contains(string(buf), "ftypavif") +} + +func GetFileContentType(buffer []byte) string { + filetype.AddMatcher(filetype.NewType("avif", "image/avif"), avifMatcher) + kind, _ := filetype.Match(buffer) + return kind.MIME.Value +} + func FileCount(dir string) int64 { var count int64 = 0 _ = filepath.Walk(dir, @@ -144,10 +169,18 @@ func GuessSupportedFormat(header *fasthttp.RequestHeader) []string { // chrome on iOS will not send valid image accept header if strings.Contains(ua, "iPhone OS 14") || strings.Contains(ua, "CPU OS 14") || strings.Contains(ua, "iPhone OS 15") || strings.Contains(ua, "CPU OS 15") || + strings.Contains(ua, "iPhone OS 16") || strings.Contains(ua, "CPU OS 16") || + strings.Contains(ua, "iPhone OS 17") || strings.Contains(ua, "CPU OS 17") || strings.Contains(ua, "Android") || strings.Contains(ua, "Linux") { supported["webp"] = true } + // iOS 16 supports AVIF + if strings.Contains(ua, "iPhone OS 16") || strings.Contains(ua, "CPU OS 16") || + strings.Contains(ua, "iPhone OS 17") || strings.Contains(ua, "CPU OS 17") { + supported["avif"] = true + } + // save true value's key to slice var accepted []string for k, v := range supported {