fix anwser token and database issus

This commit is contained in:
tamakyi
2026-09-15 11:06:09 +08:00
parent e683e798aa
commit adcc42cc8c
33 changed files with 1011 additions and 802 deletions
+16 -24
View File
@@ -13,15 +13,12 @@ import (
"strings"
)
// GzipHandler 返回一个压缩中间件,用于包装 http.Handler。
// 它对可压缩的响应(HTML / CSS / JS / JSON 等文本类型)做 gzip 压缩,
// 自动跳过图片、视频、字体等已经压缩过的格式。
//
// 由于 flamego 的 Context 无法替换底层 ResponseWriter,这里采用在
// http.Server 最外层包装 Handler 的方式,保证对所有响应(含静态文件)生效。
// GzipHandler 对可压缩的文本响应(HTML / CSS / JS / JSON 等)做 gzip 压缩,
// 自动跳过图片、视频、字体等已压缩格式。
// flamego 的 Context 无法替换底层 ResponseWriter,故在 http.Server 最外层包装
// Handler,保证对所有响应(含静态文件)生效。
func GzipHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 客户端不支持 gzip 时直接透传
if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
next.ServeHTTP(w, r)
return
@@ -32,8 +29,7 @@ func GzipHandler(next http.Handler) http.Handler {
gz: gzip.NewWriter(w),
}
defer func() {
// 只有真正写入过 body 才关闭 gzip 流,避免 302/204 等
// 无 body 响应被追加空的 gzip 尾块
// 只有真正写入过 body 才关闭,避免 302/204 等无 body 响应被追加空的 gzip 尾块
if gw.compress && gw.wrote {
_ = gw.gz.Close()
}
@@ -42,8 +38,8 @@ func GzipHandler(next http.Handler) http.Handler {
})
}
// gzipResponseWriter 包装 http.ResponseWriter,在 WriteHeader 时根据
// Content-Type 决定是否启用 gzip,保持接口兼容(Flusher / Hijacker / Pusher)。
// gzipResponseWriter 在 WriteHeader 时按 Content-Type 决定是否启用 gzip,
// 并保持 Flusher / Hijacker / Pusher 接口兼容。
type gzipResponseWriter struct {
http.ResponseWriter
gz *gzip.Writer
@@ -52,8 +48,8 @@ type gzipResponseWriter struct {
wroteHeader bool
}
// WriteHeader 记录状态码,并根据 Content-Type 决定是否压缩。
// 由于 Content-Encoding 改变后 Content-Length 不再准确,需要删除该头。
// WriteHeader 记录状态码并决定是否压缩;Content-Encoding 改变后 Content-Length
// 不再准确,需删除该头。
func (w *gzipResponseWriter) WriteHeader(status int) {
if w.wroteHeader {
return
@@ -75,15 +71,14 @@ func (w *gzipResponseWriter) WriteHeader(status int) {
w.ResponseWriter.WriteHeader(status)
}
// Write 写入响应体。若尚未 WriteHeader(handler 依赖 net/http 自动嗅探
// Content-Type 的情况),先用首个字节块探测类型再决策。
// Write 写入响应体。若尚未 WriteHeader,先用首个字节块探测类型再决策。
func (w *gzipResponseWriter) Write(b []byte) (int, error) {
if !w.wroteHeader {
ct := w.Header().Get("Content-Type")
if ct == "" {
ct = http.DetectContentType(b)
// 将嗅探到的类型写回响应头,使 WriteHeader 的压缩判定能正确生效
// (否则空 Content-Type 会被判定为"不压缩",导致本应压缩的纯文本响应未压缩)。
// 嗅探结果须写回头,否则空 Content-Type 会被判为「不压缩」,
// 导致本应压缩的纯文本响应漏压。
w.Header().Set("Content-Type", ct)
}
w.WriteHeader(http.StatusOK)
@@ -95,7 +90,7 @@ func (w *gzipResponseWriter) Write(b []byte) (int, error) {
return w.ResponseWriter.Write(b)
}
// Flush 转发底层 Flusher,并在压缩模式下先刷新 gzip 缓冲。
// Flush 转发底层 Flusher,压缩模式下先刷新 gzip 缓冲。
func (w *gzipResponseWriter) Flush() {
if w.compress && w.gz != nil {
_ = w.gz.Flush()
@@ -121,24 +116,21 @@ func (w *gzipResponseWriter) Push(target string, opts *http.PushOptions) error {
return http.ErrNotSupported
}
// shouldCompressContentType 判断响应 Content-Type 是否值得压缩。
// 空类型、二进制图片/视频/音频/字体等已压缩格式直接跳过。
// shouldCompressContentType 判断 Content-Type 是否值得压缩:空类型与已压缩的
// 二进制格式(图片 / 视频 / 音频 / 字体 / 归档等)直接跳过。
func shouldCompressContentType(ct string) bool {
ct = strings.ToLower(strings.TrimSpace(ct))
if ct == "" {
return false
}
// SVG 是文本格式,值得压缩;其余图片格式已是压缩格式
if strings.HasPrefix(ct, "image/") {
return strings.Contains(ct, "svg")
return strings.Contains(ct, "svg") // SVG 是文本格式
}
// 视频 / 音频 / 字体已是压缩格式
if strings.HasPrefix(ct, "video/") || strings.HasPrefix(ct, "audio/") ||
strings.HasPrefix(ct, "font/") {
return false
}
// 已知压缩或二进制格式
switch ct {
case "application/zip", "application/gzip", "application/x-7z-compressed",
"application/x-rar-compressed", "application/pdf",