Cloudflare strips headers on custom domain for Cloudflare Pages

I have a React app (hosted on Cloudflare Pages) consuming a Flask API which I deployed on DigitalOcean App platform. I am using custom domains for both, app.example.com and api.example.com respectively.

When I try to use the app through the domain provided by Cloudflare Pages, my-app.pages.dev, I have no issues.

But when I try to use it through my custom domain app.example.com, I see that certain headers get stripped in the response to the preflight OPTIONS request. These are

access-control-allow-credentials: true
access-control-allow-headers: content-type
access-control-allow-methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT
allow: POST, OPTIONS
vary: Origin

This causes issues with CORS, as displayed in the browser console:

Access to XMLHttpRequest at ‘https://api.example.com/auth/login’ from origin ‘https://app.example.com’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The value of the ‘Access-Control-Allow-Credentials’ header in the response is ‘’ which must be ‘true’ when the request’s credentials mode is ‘include’. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

Users can login without any issues on Cloudflare provided domain my-app.pages.dev, but whenever they try to login through the custom domain, they receive this error.

Another detail: the only difference between the preflight request in two cases is, the browser sets the following on app.example.com

origin: https://app.example.com
referer: https://app.example.com/login
sec-fetch-site: same-site

And the following on my-app.pages.dev

origin: https://my-app.pages.dev
referer: https://my-app.pages.dev/login
sec-fetch-site: cross-site

I am using Flask-CORS with support_credentials=True to handle CORS on the API, and axios with {withCredentials: true} to consume the API on the frontend.

Is this due to a Cloudflare policy that I’m not aware of?

Just resolved this issue, will update on how I did it soon. No need for further assistance.

2 Likes

Happy to hear you resolved it. Would love any insight here as CORS issues can get very confusing!

This was due to the App Spec on DigitalOcean. I had CORS specific setting on the YAML file:

I changed

- cors:
    allow_headers:
    - '*'
    allow_methods:
    - GET
    - OPTIONS
    - POST
    - PUT
    - PATCH
    - DELETE
    allow_origins:
    - prefix: https://app.example.com # <== I removed this line
    - regex: https://*.example.com
    - regex: http://*.example.com

to

- cors:
    allow_headers:
    - '*'
    allow_methods:
    - GET
    - OPTIONS
    - POST
    - PUT
    - PATCH
    - DELETE
    allow_origins:
    - regex: https://*.example.com
    - regex: http://*.example.com

For reference, this is the cURL command I used to debug the problem:

curl -I -XOPTIONS  https://api.example.com \
    -H 'origin: https://app.example.com' \
    -H 'access-control-request-method: GET'

So it wasn’t due to Cloudflare. Funny enough, DigitalOcean App Platform traffic goes through Cloudflare by default which added to my confusion.

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.