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

Can anyone help here?

I'm stuck on this too: CORS Syntax Not Working?