Вопрос или проблема
Я пытаюсь создать простой бэкэнд на Go, используя Chi в качестве маршрутизатора и Traefik в качестве реверс-прокси. Мои заголовки CORS возвращаются нормально, когда я запускаю контейнер Docker отдельно на порту 8000. Однако, когда я запускаю его на своем сервере с использованием Traefik, данные конечной точки возвращаются нормально, но ни один из заголовков 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:
Ответ или решение
Когда вы запускаете ваше приложение на Go с использованием маршрутизатора Chi и прокси-сервера Traefik, может возникнуть ситуация, когда заголовки CORS возвращаются в ответах, когда вы запускаете контейнер локально, но не работают при проксировании через Traefik. Ваша проблема может быть вызвана несколькими факторами, связанными с конфигурацией Traefik и вашим приложением. Давайте рассмотрим возможные причины и решения более подробно.
Возможные причины проблемы
-
Отсутствие правильной маршрутизации заголовков:
Traefik может не передавать заголовки к вашему приложению, если они неправильно настроены. Параметры маршрутизации, такие какtraefik.http.routers.kanjoy.rule
, могут не совпадать с запросом, что может привести к фильтрации заголовков. -
CORS-обработчик в приложении:
Убедитесь, что CORS настроен правильно и приложение действительно обрабатывает заголовки, которые вы ожидаете увидеть. Вы уже настроили обработчик CORS, но полезно проверить, возвращаются ли заголовки в локальной среде без Traefik. -
Обработка OPTIONS запросов:
CORS требует, чтобы браузеры отправляли предварительные запросы (OPTIONS
) для проверки допустимости источника. Убедитесь, что ваши маршруты обрабатывают OPTIONS запросы и что ваш прокси-сервер правильно перенаправляет их. -
Настройки Traefik:
Проверка конфигурации Traefik на наличие неправильных параметров или исключений, которые могут ограничивать передачу заголовков. Также стоит проверить версию Traefik, так как разные версии могут иметь различные механизмы работы с заголовками.
Решения и рекомендации
-
Проверка конфигурации Traefik:
Убедитесь, что в конфигурации Traefik установлены необходимые заголовки. Попробуйте добавить следующие строки в вашу конфигурацию Traefik для явного назначения заголовков:labels: - "traefik.http.middlewares.cors.headers.accesscontrolalloworigins=*" - "traefik.http.middlewares.cors.headers.accesscontrolallowmethods=GET, POST, PUT, DELETE, OPTIONS, HEAD" - "traefik.http.middlewares.cors.headers.accesscontrolallowheaders=Accept, Authorization, Content-Type, X-CSRF-Token" - "traefik.http.middlewares.cors.headers.accesscontrolexposeheaders=Link"
Затем подключите этот middleware к вашему маршруту:
- "traefik.http.routers.kanjoy.middlewares=cors@docker"
-
Логи и инструменты отладки:
Используйте логи Traefik, чтобы просмотреть, каким образом обрабатываются ваши запросы и каковы заголовки, которые отправляются. Это может помочь вам отследить, где именно теряется информация. -
Тестирование CORS с другими инструментами:
Попробуйте протестировать ваше приложение с помощью инструментов, таких как Postman или curl, для проверки заголовков, чтобы изолировать проблему от браузера. -
Изучение документации:
Ознакомьтесь с документацией Traefik по CORS и заголовкам. Это поможет вам понять, как правильно конфигурировать ваше приложение и Traefik для достижения желаемого поведения.
Заключение
Проблема с отсутствием заголовков CORS при использовании Traefik может быть связана с конфигурацией маршрутизации, особенностями обработки запросов или настройками самих заголовков. Проведя проверку маршрутов и оптимизируя конфигурацию Traefik, вы сможете исправить ситуацию и обеспечить правильное возвращение необходимой информации клиентам. Не забывайте также о том, что кросс-доменные запросы часто требуют дополнительных проверок и инструментов отладки, чтобы убедиться, что все настройки произведены корректно.