2

I'm trying to create a simple backend in go using Chi as my router and traefik as my reverse proxy. My cors headers are returning fine when I run the docker container by itself on port 8000. However, when I run it on my droplet using traefik, the endpoint's data returns fine, but none of the cors headers are returned in the response, and neither is any other header (I tried adding a test header, no luck). What's going on here? Is traefik filtering out my headers somehow?

I tried messing around with the traefik config to manually set the cors headers that way, but no luck. Here's my files for context:

// 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:

Update

I have managed to temporarily circumvent this problem by setting my cors headers in my compose.yaml file instead.


      - "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"

This allows the proper cors headers to get returned, but any headers I set in Go are still being filtered out. For example, I'm trying to implement Oauth with JWT tokens, and although it's working totally fine when the image is deployed locally without traefik, my headers are getting blocked when I visit the same path through my deployment.

Locally:

enter image description here

On the server:

enter image description here

8
  • Please test with AllowedHeaders: []string{"*"}. Traefik adds headers to the request before passing it to the app (and, as you don't allow these, the middleware will not respond) Commented Oct 16, 2024 at 3:54
  • Just tried setting AllowedHeaders, AllowedOrigins, and AllowedMethods all to []string{"*"}, no dice. Commented Oct 16, 2024 at 4:02
  • AllowedMethods does not appear to support []string{"*"}... Note that you should be able to set options.Debug to true so some debugging info will be output (by default it will log to stdout so you can use docker compose logs to view). Commented Oct 16, 2024 at 5:00
  • Since it seems like both AllowedMethods and AllowedHeaders don't seem to support the wildcard, I reverted the methods to what I allowed originally and added every header listed in the docs you linked to the allowed headers. Still not working. Even when I set the debug to true, all that was logged seemed normal: 2024/10/16 05:54:09 "GET http://my-server-url.com/ HTTP/1.1" from <ip> - 200 22B in 19.25µs Commented Oct 16, 2024 at 6:01
  • This question is similar to: Access from origin 'https://example.com' has been blocked even though I've allowed https://example.com/. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Oct 16, 2024 at 7:24

1 Answer 1

1

I figured out the issue. In the end, it wasn't an issue with traefik or chi, but rather with my docker build. I forgot to re-build the image without cache after adding in the cors headers. Once I did that, it worked perfectly fine.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.