Issue with CORS that's been absolutely killing me - I'm sure it's a basic config issue I'm missing!

I did my best to search through the forum to see what I could be missing, but came up empty.

My CURL request shows a different response from my server than my browser and I am running into CORS issues.

The oddest parts of this is that you will see in my Curl request that I have a "Access-Control-Allow-Origin: http://app.localhost," but in my response from my front end call I don't get the same header.

A few things I've tried with no luck:

  • Completely removing CORS records from server
  • Adding and removing all of the labels shows on my docker-compose file

Curl Request:

$ curl -i http://yeet.localhost/graphql/ -H "Origin: http://app.localhost" -H "Access-Control-Request-Method: POST"
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://app.localhost
Access-Control-Expose-Headers: Link, Access-Control-Allow-Origin
Content-Length: 59
Content-Type: text/plain; charset=utf-8
Date: Sat, 08 Aug 2020 17:44:05 GMT
Vary: Origin
X-Ratelimit-Limit: 100
X-Ratelimit-Remaining: 97
X-Ratelimit-Reset: 1596908700

Response from Front end call:

Content-Length: 0
Date: Sat, 08 Aug 2020 17:46:16 GMT
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Ratelimit-Limit: 100
X-Ratelimit-Remaining: 100
X-Ratelimit-Reset: 1596908820

Error message from my apollo client:

Access to fetch at 'http://yeet.localhost/graphql/' from origin 'http://app.localhost' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Go CORS config:

	r := chi.NewRouter()
	r.Use(middleware.Recoverer)
	r.Use(middleware.Logger)
	r.Use(middleware.Timeout(30 * time.Second))
	// TODO: Try to break this
	r.Use(httprate.LimitByIP(100, 1*time.Minute))
	// TODO Try to reduce this
	r.Use(cors.Handler(cors.Options{
		AllowedOrigins:   []string{"http://app.localhost"},
		AllowedMethods:   []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
		AllowedHeaders:   []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token", "Access-Control-Allow-Origin"},
		ExposedHeaders:   []string{"Link", "Access-Control-Allow-Origin"},
		AllowCredentials: true,
		MaxAge:           300, // Maximum value not ignored by any of major browsers
	}))

Traefik config:

Adding http://app.localhost to the accesscontrolalloworiginlist and allowedhosts did not work either.

# https://dev.to/simplecto/my-configuration-for-traefik-2-0-docker-and-letsencrypt-285d
version: '3.8'
services:
  traefik:
    container_name: traefik
    image: traefik:v2.2
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--entryPoints.web.address=:80"
      - "--entryPoints.websecure.address=:443"
    restart: always
    ports:
      - 80:80
      - 443:443
      - 8080:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
  reverse-proxy:
    build: ../proxy-middleware
    command: fresh
    security_opt:
      - "seccomp:unconfined"
    cap_add:
      - SYS_PTRACE
    volumes:
      - ../proxy-middleware:/go/src/github.com/austincollinpena/proxy-middleware
    restart: always
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.reverse-proxy.rule=Host(`api.localhost`)"
      - "traefik.http.services.reverse-proxy.loadbalancer.server.port=8089"
      - "traefik.http.middlewares.testheader.headers.accesscontrolalloworiginlist=http://localhost"
      - "traefik.http.middlewares.testheader.headers.allowedhosts=http://localhost"
      - "traefik.http.middlewares.testheader.headers.accesscontrolalloworigin=origin-list-or-null"
      - "traefik.http.middlewares.testheader.headers.accesscontrolallowheaders=*"
      - "traefik.http.middlewares.testheader.headers.accesscontrolexposeheaders=*"
      - "traefik.http.middlewares.testHeader.Headers.AccessControlAllowMethods=GET,OPTIONS,PUT,DELETE"
  react:
    build: ../web-app
    command: npm run start
    volumes:
      - ../web-app:/opt/web
    links:
      - reverse-proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.react.rule=Host(`app.localhost`)"
      - "traefik.http.services.react.loadbalancer.server.port=3000"
    restart: on-failure
  redisMaster:
    image: "redis:alpine"
    command: redis-server --appendonly yes --requirepass sOmE_sEcUrE_pAsS
    ports:
      - "6379:6379"
    depends_on:
      - helper
    environment:
      - REDIS_REPLICATION_MODE=master
    links:
      - reverse-proxy
    sysctls:
      net.core.somaxconn: '511'
    volumes:
      - redis-data:/data
  helper:
    image: alpine
    command: sh -c "echo never > /sys/kernel/mm/transparent_hugepage/enabled"
    privileged: true
volumes:
  redis-data:

As one may have guessed, my issue was not with Traefik, but with my own CORs implemenation. I had a new header that wasn't recognized that was blocked.

I switched to github.com/rs/cors which has a nice debug option and that solved it for me.

nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header X-FRock-Transactionid $formatted_id;
more_set_headers "Transaction-ID: $formatted_id";
proxy_set_header ssl-android-client-cert $ssl_client_cert;

  if ($http_referer ~* "^https?:\/\/((?:.*\.mp-xyz-xyz-dr\.1\.com)|(?:.*\.mpdev-xyz\.aws\.xyz\.cloud)|(?:.*\.merchant\.xyz\.in))") { 
    add_header 'Set-Cookie' "xyzred=$http_referer; Path=/" always;
  }
  
  if ($http_origin ~* "^https?:\/\/((?:localhost:?[0-9]*)|(?:.*\.localhost:?[0-9]*)|(?:localhost)|(?:.*\.localhost)|(?:.*\.mp-xyz-xyz-dr\.1\.com)|(?:.*\.mp-xyz\.aws\.xyz\.cloud)|(?:.*\.merchantxyz\.xyz\.in)|(?:web1008\.1\.com)|(?:web1009\.1\.com)|(?:web1008\.1\.com)|(?:web1009\.1\.com)|(?:xyz\.onexyz24\.co\.in)|(?:prod\.xyz\.xyzapps\.com)|(?:.*\.app\.dev\.k8s\.ipp-digital\.aws\.xyz\.cloud)|(?:.*\.app\.dc\.xyz\.k8s\.ipp-digital\.1\.com)|(?:.*\.app\.dr\.xyz\.k8s\.ipp-digital\.1\.com)|(?:.*\.xyz\.aws\.xyz\.cloud)|(?:.*\.xyz\.xyz\.dev))$") {
    set $cors "true";
  }
  if ($request_method = 'OPTIONS') {
    set $cors "${cors}options";
  }
  if ($cors = "true") {
    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
    add_header 'Access-Control-Allow-Methods' 'PUT,GET,POST,HEAD,PATCH,DELETE' always;
    add_header 'Access-Control-Allow-Headers' 'authorization,x-requested-with,accept-api-version,content-type,cookie' always;
  }
  if ($cors = "trueoptions") {
    add_header 'Access-Control-Allow-Origin' "$http_origin";
    add_header 'Access-Control-Allow-Methods' 'PUT,GET,POST,HEAD,PATCH,DELETE,OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'authorization,x-requested-with,accept-api-version,content-type,cookie';
    add_header 'Access-Control-Max-Age' 600;
    add_header 'Content-Type' 'text/plain charset=UTF-8';
    add_header 'Content-Length' 0;
    return 204;
  }

HI, I am getting cors allow origin issue with traefik 2.3 version, let me know how to convert from nginx annotation to traefik to fix this issue