Issue with CORS headers


I'm kind of going crazy trying to figure this out.

Here is a brief summary of what works and what doesn't:

API url is always the same. Let's assume it's

  • XHR request to the API works fine
let url = '';
let method = 'GET';
let xhr = new XMLHttpRequest();, url, true);
  • Request made with curl works fine.
curl -v -H "Origin:" -H "Access-Control-Request-Method: GET"
  • Request made using fetch doesn't work (Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.)
  • Request made using fetch to works
  • I don't see any request reaching traefik in the logs (log level set to DEBUG) for the requests that fail; therefore I quite obviously don't see the request reaching my API.

From what I see when trying to run a preflight request using curl, the requested headers aren't applied:

curl -v -X OPTIONS -H "Origin:" -H "Access-Control-Request-Method: GET"
*   Trying xxxx:443...
* Connected to (xxxx) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55b6d34d22f0)
> OPTIONS /api/test HTTP/2
> Host:
> user-agent: curl/7.68.0
> accept: */*
> origin:
> access-control-request-method: GET
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 200 
< access-control-allow-methods: GET,OPTIONS,PUT
< access-control-max-age: 100
< content-length: 0
< date: Wed, 08 Jun 2022 15:55:13 GMT

My traefik middleware:

      - "traefik.http.middlewares.api-headers.headers.accesscontrolallowmethods=GET,OPTIONS,PUT"
      - "traefik.http.middlewares.api-headers.headers.accesscontrolalloworiginlist=*"
      - "traefik.http.middlewares.api-headers.headers.accesscontrolmaxage=100"

I'm running out of ideas. I'm not even sure if traefik is the issue anymore considering the XHR requests work (and those requests get the proper CORS headers applied from traefik, verified by changing the values). Any insight is appreciated.