chore: embed health.html 到 binary,单文件分发
把 health.html 从外部依赖改为 //go:embed 内嵌, 实现真正的"单 exe 分发"。 - 新建 router/dashboard.go,用 //go:embed 嵌入 health.html - router/router.go:/dashboard handler 改为 w.Write(dashboardHTML) - setting/config.go:删 CheckStaticFiles(无需文件检查) - main.go:删 setting.CheckStaticFiles() 调用 - Dockerfile:删 COPY health.html 步骤(已嵌入) - .gitignore:加 release/(build 产物不入 git) - 物理移动 health.html 到 router/(embed 限制:同包或子包) 效果: - 之前: release 包 = tts-api.exe + health.html (2 个文件) - 之后: release 包 = tts-api.exe (1 个文件,~7 MB) - 用户部署无需额外文件,/dashboard 路由直接工作
This commit is contained in:
+4
-1
@@ -19,4 +19,7 @@ Thumbs.db
|
|||||||
!.env.example
|
!.env.example
|
||||||
|
|
||||||
# Local-only working notes (use task board for shared tracking)
|
# Local-only working notes (use task board for shared tracking)
|
||||||
TODO.md
|
TODO.md
|
||||||
|
|
||||||
|
# Release artifacts (build output)
|
||||||
|
release/
|
||||||
+1
-1
@@ -25,7 +25,7 @@ RUN apk --no-cache add ca-certificates tzdata \
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY --from=builder /app/tts-api .
|
COPY --from=builder /app/tts-api .
|
||||||
COPY --from=builder /app/health.html .
|
# health.html 已通过 //go:embed 嵌入 binary,无需单独复制
|
||||||
|
|
||||||
RUN chown -R appuser:appgroup /app
|
RUN chown -R appuser:appgroup /app
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ func main() {
|
|||||||
setting.InitAllConfigs()
|
setting.InitAllConfigs()
|
||||||
metrics.Init()
|
metrics.Init()
|
||||||
middleware.InitRateLimiter()
|
middleware.InitRateLimiter()
|
||||||
setting.CheckStaticFiles()
|
|
||||||
controller.InitController()
|
controller.InitController()
|
||||||
setting.LogStartupSummary()
|
setting.LogStartupSummary()
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package router
|
||||||
|
|
||||||
|
import _ "embed"
|
||||||
|
|
||||||
|
//go:embed health.html
|
||||||
|
var dashboardHTML []byte
|
||||||
+2
-1
@@ -20,7 +20,8 @@ func Setup() *mux.Router {
|
|||||||
r.HandleFunc("/v1/audio/speech", controller.OpenaiTTSHandler).Methods("POST", "OPTIONS")
|
r.HandleFunc("/v1/audio/speech", controller.OpenaiTTSHandler).Methods("POST", "OPTIONS")
|
||||||
r.HandleFunc("/health", controller.HealthHandler).Methods("GET")
|
r.HandleFunc("/health", controller.HealthHandler).Methods("GET")
|
||||||
r.HandleFunc("/dashboard", func(w http.ResponseWriter, r *http.Request) {
|
r.HandleFunc("/dashboard", func(w http.ResponseWriter, r *http.Request) {
|
||||||
http.ServeFile(w, r, "health.html")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
w.Write(dashboardHTML)
|
||||||
}).Methods("GET")
|
}).Methods("GET")
|
||||||
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Redirect(w, r, "/dashboard", http.StatusFound)
|
http.Redirect(w, r, "/dashboard", http.StatusFound)
|
||||||
|
|||||||
@@ -309,10 +309,3 @@ func maskAPIKey(key string) string {
|
|||||||
}
|
}
|
||||||
return key[:4] + "****" + key[len(key)-4:]
|
return key[:4] + "****" + key[len(key)-4:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckStaticFiles 检查 /dashboard 路由依赖的 health.html 是否存在。
|
|
||||||
func CheckStaticFiles() {
|
|
||||||
if _, err := os.Stat("health.html"); os.IsNotExist(err) {
|
|
||||||
log.Println("警告: health.html 不存在,/dashboard 路由将返回 404")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user