From 92813fde49fac65217b6f0c84120946f2d69a6f6 Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 5 May 2026 19:58:56 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DAlpine=E4=B8=8AMIME?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E6=A3=80=E6=B5=8B=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fallbackMimeTypes 硬编码映射优先,不依赖系统 mime.types - Docker 镜像安装 mailcap 包提供 /etc/mime.types - 移除不可靠的 mime.AddExtensionType 方案 --- Dockerfile | 2 +- backend/cmd/main.go | 49 ++++++++++++++++++++++++++++----------------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/Dockerfile b/Dockerfile index b50f415..7adebf9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,7 +33,7 @@ RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main ./cmd/main.g FROM alpine:latest -RUN apk --no-cache add ca-certificates tzdata su-exec +RUN apk --no-cache add ca-certificates tzdata su-exec mailcap RUN addgroup -g 1001 -S appgroup && \ adduser -u 1001 -S appuser -G appgroup diff --git a/backend/cmd/main.go b/backend/cmd/main.go index 6905b5a..7c504fe 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -6,7 +6,6 @@ import ( "fmt" "io/fs" "log" - "mime" "net/url" "os" "strings" @@ -226,15 +225,6 @@ func startServer() { r := gin.Default() r.MaxMultipartMemory = 32 << 20 - mime.AddExtensionType(".js", "application/javascript; charset=utf-8") - mime.AddExtensionType(".mjs", "application/javascript; charset=utf-8") - mime.AddExtensionType(".css", "text/css; charset=utf-8") - mime.AddExtensionType(".html", "text/html; charset=utf-8") - mime.AddExtensionType(".json", "application/json; charset=utf-8") - mime.AddExtensionType(".svg", "image/svg+xml") - mime.AddExtensionType(".woff", "font/woff") - mime.AddExtensionType(".woff2", "font/woff2") - r.Use(middleware.Logger()) r.Use(middleware.Recovery()) r.Use(middleware.Cors()) @@ -284,10 +274,7 @@ func setupEmbeddedFrontend(r *gin.Engine) { return } - contentType := mime.TypeByExtension(decodedPath) - if contentType == "" { - contentType = "application/octet-stream" - } + contentType := getContentTypeByExtension(decodedPath) c.Header("Cache-Control", "public, max-age=31536000, immutable") c.Data(200, contentType, data) @@ -305,10 +292,7 @@ func setupEmbeddedFrontend(r *gin.Engine) { decodedPath = path } if data, err := fs.ReadFile(distFS, decodedPath); err == nil { - contentType := mime.TypeByExtension(decodedPath) - if contentType == "" { - contentType = "application/octet-stream" - } + contentType := getContentTypeByExtension(decodedPath) c.Data(200, contentType, data) return } @@ -343,6 +327,35 @@ func serveIndexHTML(c *gin.Context, indexHTML string) { c.Data(200, "text/html; charset=utf-8", []byte(html)) } +var fallbackMimeTypes = map[string]string{ + ".js": "application/javascript; charset=utf-8", + ".mjs": "application/javascript; charset=utf-8", + ".css": "text/css; charset=utf-8", + ".html": "text/html; charset=utf-8", + ".json": "application/json; charset=utf-8", + ".svg": "image/svg+xml", + ".png": "image/png", + ".jpg": "image/jpeg", + ".jpeg": "image/jpeg", + ".gif": "image/gif", + ".ico": "image/x-icon", + ".webp": "image/webp", + ".woff": "font/woff", + ".woff2": "font/woff2", + ".ttf": "font/ttf", + ".eot": "application/vnd.ms-fontobject", + ".xml": "application/xml", + ".txt": "text/plain; charset=utf-8", +} + +func getContentTypeByExtension(filename string) string { + ext := strings.ToLower(filename[strings.LastIndex(filename, "."):]) + if ct, ok := fallbackMimeTypes[ext]; ok { + return ct + } + return "application/octet-stream" +} + func getSettingString(settings map[string]interface{}, key, defaultValue string) string { if val, ok := settings[key]; ok { if str, ok := val.(string); ok && str != "" {