package route import ( "net/http" "strconv" "github.com/tamakyi/TamaBox/internal/route/assets" ) // writeBanned 写出「来源已被封禁」的响应。 // // 状态码仍然是 403 —— 语义不变,只把 body 从 13 字节的 "403 Forbidden" // 换成一张 256×256 的 webp(约 8.6 KB): // - 顶掉明文:爆破/扫描脚本不少会读响应体里的 "403 Forbidden" 来确认自己 // 已被拦,换掉 body 至少让这类判断失效(状态码本身还是照常返回); // - 给人看:误封(比如共享出口、代理)时打开浏览器看到一张写着 403 的图, // 比一个没有任何样式的白屏好判断得多。 // // 图片是编译期 embed 的,不走磁盘 IO,也不占一个可公开访问的 URL。 // 被封住的来源往往反复重试,所以这里显式给 Content-Length(否则 8 KB 会退回 // chunked),并标 no-store:中间层缓存一张 403 图没有意义,还会让解封后 // 的响应继续命中缓存。 func writeBanned(w http.ResponseWriter, method string) { h := w.Header() h.Set("Content-Type", "image/webp") h.Set("Content-Length", strconv.Itoa(len(assets.BannedImage))) h.Set("Cache-Control", "no-store, no-cache, must-revalidate") h.Set("X-Robots-Tag", "noindex, nofollow") w.WriteHeader(http.StatusForbidden) // HEAD 不写 body(net/http 也会丢弃,这里省掉一次无意义的拷贝)。 if method != http.MethodHead { _, _ = w.Write(assets.BannedImage) } }