我正在尝试使用 Chi 作为我的路由器和 traefik 作为我的反向代理来创建一个简单的后端。当我在端口 8000 上运行 docker 容器时,我的 cors 标头返回正常。但是,当我使用 traefik 在 Droplet 上运行它时,端点的数据返回正常,但响应中没有返回任何 cors 标头,也没有返回是任何其他标头(我尝试添加测试标头,但没有成功)。这是怎么回事? traefik 是否以某种方式过滤掉我的标头?
我尝试用 traefik 配置来手动设置 cors 标头,但没有成功。这是我的上下文文件:
// server.go
package server
import (
"encoding/json"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/cors"
"github.com/go-chi/render"
)
func (s *Server) RegisterRoutes() http.Handler {
r := chi.NewRouter()
r.Use(cors.Handler(cors.Options{
AllowedOrigins: []string{"https://my-deployment-url.netlify.app", "http://localhost:3000"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"},
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
ExposedHeaders: []string{"Link"},
AllowCredentials: true,
MaxAge: 300,
}))
r.Use(middleware.Logger)
r.Get("/", s.IndexHandler)
return r
}
func (s *Server) IndexHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Test-Header", "TestHeaderValue")
resp := map[string]string{
"message": "Route 2",
}
render.JSON(w, r, resp)
}
# compose.yaml
services:
reverse-proxy:
image: traefik:v3.1
command:
- "--providers.docker"
- "--providers.docker.exposedbydefault=false"
- "--entryPoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "[email protected]"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
ports:
- "80:80"
- "443:443"
volumes:
- letsencrypt:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock
goapp:
container_name: go
labels:
- "traefik.enable=true"
- "traefik.http.routers.kanjoy.rule=Host(`my-deployment-url`)"
- "traefik.http.routers.kanjoy.entrypoints=websecure"
- "traefik.http.routers.kanjoy.tls.certresolver=myresolver"
build:
context: .
dockerfile: Dockerfile.prod
volumes:
- ./:/app
depends_on:
- db
db:
image: postgres:latest
restart: unless-stopped
environment:
POSTGRES_DB: ${BLUEPRINT_DB_DATABASE}
POSTGRES_USER: ${BLUEPRINT_DB_USERNAME}
POSTGRES_PASSWORD: ${BLUEPRINT_DB_PASSWORD}
ports:
- "${BLUEPRINT_DB_PORT}:5432"
volumes:
- db:/var/lib/postgresql/data
volumes:
db:
letsencrypt:
我已经设法通过在我的
compose.yaml
文件中设置我的 cors 标头来暂时规避这个问题。
- "traefik.http.routers.to_kanjoy.middlewares=cors"
- "traefik.http.middlewares.cors.headers.accesscontrolallowmethods=GET,OPTIONS,PUT,POST,DELETE,PATCH"
- "traefik.http.middlewares.cors.headers.accesscontrolallowheaders=Content-Type,
Authorization, X-Requested-With"
- "traefik.http.middlewares.cors.headers.accesscontrolallowcredentials=true"
- "traefik.http.middlewares.cors.headers.accesscontrolalloworiginlist=https://my-deployment-url.netlify.app,http://localhost:3000"
- "traefik.http.middlewares.cors.headers.accesscontrolmaxage=100"
- "traefik.http.middlewares.cors.headers.addvaryheader=true"
这允许返回正确的 cors 标头,但我在 Go 中设置的任何标头仍会被过滤掉。例如,我正在尝试使用 JWT 令牌实现 Oauth,尽管在没有 traefik 的情况下在本地部署图像时它工作得很好,但当我通过部署访问相同的路径时,我的标头会被阻止。
我解决了这个问题。最后,这不是 traefik 或 chi 的问题,而是我的 docker 构建的问题。添加 cors 标头后,我忘记重新构建图像不带缓存。一旦我这样做了,它就完美地工作了。