django-cors-headers not working: No 'Access-Control-Allow-Origin' header is present on the requested resource

Question:

Full error:

Access to XMLHttpRequest at 'https://[redacted]/api/get_match_urls/' from origin 'https://trello.com' 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.

I am making an API call from an extension while at trello.com

I have corsheaders in my INSTALLED_APPS. I have 'corsheaders.middleware.CorsMiddleware' in my middleware as high up as possible. And I have CORS_ORIGIN_ALLOW_ALL set to True. Yes I’ve tried the alternate alias CORS_ALLOW_ALL_ORIGINS and it still didn’t work. Anyone have any ideas?

MIDDLEWARE = [
    
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Asked By: Mike Johnson Jr

||

Answers:

I had a look at the corsheaders.middleware.CorsMiddleware and it seems if you set CORS_ALLOW_ALL_ORIGINS and not CORS_ALLOW_CREDENTIALS it will return Access-Control-Allow-Origin: *, but if you also set CORS_ALLOW_CREDENTIALS then it will return the origin from the request headers.

here is the part of the code that does that

origin = request.META.get("HTTP_ORIGIN")

# omiting the lines in between

if conf.CORS_ALLOW_ALL_ORIGINS and not conf.CORS_ALLOW_CREDENTIALS:
    response[ACCESS_CONTROL_ALLOW_ORIGIN] = "*"
else:
    response[ACCESS_CONTROL_ALLOW_ORIGIN] = origin

another idea would be also to use CORS_ALLOWED_ORIGIN_REGEXES e.g

CORS_ALLOWED_ORIGIN_REGEXES = [
    r".*",
]
Answered By: knetsi

Could not make it work after trying everything mentioned here. In fact, everything mentioned in the django-cors-headers documentation was already there in my settings.py.

After a lot of digging in, I found out the culprit was the "MIDDLEWARE" definition itself in settings.py. According to my version of django (which is 1.7) it needs to be "MIDDLEWARE_CLASSES" and not "MIDDLEWARE". You can find this out when you look at the django documentation for middlewares which can be found here https://docs.djangoproject.com/en/1.8/topics/http/middleware/ (don’t forget to choose your version of django from right bottom corner). When this change was done, my preflights started returning the needed response headers.

Still scratching my head thinking how simple was the solution (when found out) for an issue which took hours away from me 🙁

Answered By: Anoop Kc