Fiber需手动分离静态资源与API路由:用app.Static()挂载前端dist目录(须放路由前),app.Group("/api")隔离后端接口,并全局注册CORS中间件;CSRF需前后端协同传递token,部署时推荐Nginx托管静态文件、Fiber仅处理API。

后端服务怎么暴露静态资源和API路由
Fiber 默认不托管前端静态文件,也不自动区分 /api/ 和根路径。你得手动配两套逻辑:一套用 app.Static() 挂载前端构建后的 dist 目录,另一套用 app.Group("/api") 隔离后端接口。关键点是顺序——Static() 必须放在所有路由注册之前,否则会被后续的 app.Get("*") 通配捕获,导致 HTML 页面无法加载。
常见错误现象:index.html 能打开,但页面内请求 /api/users 返回 404;或者所有路径都返回首页(SPA fallback 写错位置)。
- 前端构建输出目录必须是绝对路径,比如
app.Static("/", "/var/www/dist"),相对路径容易在不同工作目录下失效 - SPA fallback(处理前端路由)要写成
app.Get("*", func(c *fiber.Ctx) error { return c.SendFile("/var/www/dist/index.html") }),且必须放在Static()之后、/api路由之前 -
/api分组里不要漏掉.Use()中间件,比如 JWT 校验或 CORS,否则跨域请求直接失败
如何让前端正确拿到并携带 CSRF token
Fiber 没有自动注入 token 到模板或响应头的机制,CSRF 防护必须前后端协同:后端生成 token 并通过 cookie 或 JSON 响应体返回,前端读取后在每次敏感请求的 header 或 body 中带上。用 csurf.New() 时,默认只对非 GET/HEAD/OPTIONS 方法校验,但你得显式排除静态资源路径,否则 /favicon.ico 或 /assets/main.js 可能触发 403。
典型配置陷阱:CookieSameSite 不设为 Lax 或 Strict,会导致现代浏览器拒绝发送该 cookie;CookieSecure: true 却没配 HTTPS,token 根本不会被浏览器保存。
- 初始化中间件时必须传入
Store,比如用fiber/storage/memory.New(),否则启动 panic - 前端首次访问
/api/csrf-token(需单独加一个路由返回{ "token": c.Locals("csrf_token").(string) })才能拿到 token - AJAX 请求需手动设置
headers: { "X-CSRF-Token": token },Fiber 不会自动从 header 读取,除非你在csurf.New()里指定KeyLookup: "header:X-CSRF-Token"
为什么 CORS 中间件要放在路由分组外层
如果把 cors.New() 放在 api := app.Group("/api") 里面,它只作用于该分组下的路由,而预检请求(OPTIONS)是发到具体路径如 /api/users 的,不是 /api。Fiber 不会自动为未定义的 OPTIONS 路径生成响应,结果就是浏览器卡在预检阶段,控制台报 No 'Access-Control-Allow-Origin' header。
正确做法是全局注册:app.Use(cors.New()),且必须在任何 app.Get()、app.Post() 之前。如果需要细粒度控制(比如只允许特定域名调用登录接口),就别用中间件,改用 c.Context().Set("Access-Control-Allow-Origin", "...") 手动写 header。
- 生产环境慎用
cors.Config{AllowOrigins: "*"},尤其涉及 Cookie 认证时,浏览器会直接拒绝 - 若前端用
credentials: true,后端必须配AllowCredentials: true且AllowOrigins不能为*,得写死域名 - 某些 Nginx 反向代理配置会覆盖 Fiber 的 CORS header,此时应在 Nginx 层统一加
add_header
部署时二进制文件和前端资源怎么组织
Go 编译出的单体二进制本身不依赖运行时,但 Fiber 服务启动后需要读取前端静态文件。别把 dist 目录打进二进制(用 embed.FS 虽然可行,但更新前端就得重编译后端),更别让二进制在运行时去相对路径找 ./dist——服务器工作目录不可控,极易 404。
最稳的方式是明确约定路径:比如把二进制放 /opt/myapp/server,前端文件放 /opt/myapp/dist,然后在代码里写死绝对路径 app.Static("/", "/opt/myapp/dist")。再配合 systemd 服务文件里的 WorkingDirectory 字段确保环境一致。
- 宝塔面板部署时,Nginx 的
location /应指向/opt/myapp/dist,而location /api/反向代理到127.0.0.1:3000(Fiber 监听端口) - 别让 Fiber 监听
0.0.0.0:80,这需要 root 权限,且绕过 Nginx 失去 gzip、HTTPS 终结等能力 - 如果用
app.Config().CaseSensitive = false,注意 Linux 文件系统区分大小写,/Dist和/dist会被当成两个路径


















