静态资源缓存应避免直接使用iris.FileServer,因其不支持标准HTTP缓存头且无法利用sendfile;推荐用ctx.ServeFile手动设Cache-Control,或交由Nginx/Caddy处理。

静态资源缓存中间件必须绕开 iris.FileServer
iris.FileServer 是纯 Go 实现,不支持标准 HTTP 缓存头(如 Cache-Control、ETag)的自动注入,也无法利用内核 sendfile。直接用它配缓存中间件,只会让响应体被多次读取、内存拷贝加剧,反而拖慢大文件传输。真正有效的做法是:用 iris.File 或 ctx.ServeFile 配合手动设置响应头,或干脆交由 Nginx / Caddy 处理。
用 ctx.ServeFile + 手动设置 Cache-Control 最可控
对单个文件或少量固定路径,直接在路由 handler 中调用 ctx.ServeFile 并写死缓存策略,避免中间件误判路径或重复消费 body。
- 必须在调用
ctx.ServeFile前设置状态码和 header,否则无效 -
Cache-Control: public, max-age=31536000适合指纹化文件(如app.a1b2c3.js) -
Cache-Control: public, max-age=3600更适合未指纹化的 CSS/JS - 别设
Expires——Cache-Control优先级更高,且更易维护
app.Get("/static/{file:path}", func(ctx iris.Context) {
file := ctx.Params().Get("file")
if strings.Contains(file, "..") {
ctx.StatusCode(403)
return
}
fpath := "./static/" + file
ctx.Header("Cache-Control", "public, max-age=3600")
ctx.ServeFile(fpath)
})
全局静态目录缓存需自定义中间件 + 文件系统校验
若坚持用 iris.FileServer("./static"),必须自己写中间件拦截 GET 请求、校验文件存在性、设置 header,并跳过 ctx.Next() 防止二次处理。但要注意:ctx.Request().URL.Path 可能含编码字符,需先 url.PathUnescape;同时要防止目录遍历(如 ../../../etc/passwd)。
- 中间件里不能调
ctx.ReadBody(),否则ServeFile会读不到文件 - 用
os.Stat检查文件是否存在且为普通文件,避免链接或目录暴露 - 对
.html或.json这类常被动态生成的后缀,建议禁用缓存:no-cache - 若用
app.Handle("GET", "/static/*filepath", ...),注意*filepath会包含开头的/,拼路径时得裁掉
生产环境强烈建议移出 Iris,交给反向代理
哪怕你写了完美的缓存中间件,Go runtime 仍要为每个静态请求分配 goroutine、buffer 和 syscall 上下文。而 Nginx 的 sendfile 是零拷贝,Caddy 的 file_server 自带 ETag、gzip 和 range 支持。Iris 只需负责 API,静态资源走独立域名(如 static.example.com)并配置 CDN 回源,才是真实效的方案。
容易被忽略的是:开发时本地用 iris.FileServer 很方便,但一旦压测发现 CPU 被 runtime.mallocgc 占满,八成就是静态文件没甩出去。这时候改代码不如改部署结构。


















