django-cors-headers not work

Each Answer to this Q is separated by one/two green lines.

django-cors-headers not work

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.gis',
    'corsheaders',
    'rest_framework',
    'world',
    'userManager',
    'markPost',
    'BasicServices',
)


MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True

Everything is normal, but did not work

here my response headers

Cache-Control: max-age=0
Content-Type: text/html; charset=utf-8
Date: Tue, 20 Jan 2015 13:16:17 GMT
Expires: Tue, 20 Jan 2015 13:16:17 GMT
Last-Modified: Tue, 20 Jan 2015 13:16:17 GMT
Server: WSGIServer/0.1 Python/2.7.8
Set-Cookie: csrftoken=snXksqpljbCLW0eZ0EElFxKbiUkYIvK0; expires=Tue, 19-Jan-2016 13:16:17 GMT; Max-Age=31449600; Path=/
Vary: Cookie
X-Frame-Options: SAMEORIGIN

I was having this same issue and everything seemed to be in the right place. Then I figured out that I had started the server before adding 'corsheaders.middleware.CorsMiddleware', to the MIDDLEWARE_CLASSES. After making the correction, it was still not working. After trying a bunch of stuff, I opened it in another browser and it worked. So it turned out that I just needed to clear the browser cache.

According to the process_response code from CorsMiddleware:

response[ACCESS_CONTROL_ALLOW_ORIGIN] = "*" if (
            settings.CORS_ORIGIN_ALLOW_ALL and
            not settings.CORS_ALLOW_CREDENTIALS) else origin

You must set settings like this:

# CORS Config
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = False

Do not forget to add

‘corsheaders.middleware.CorsMiddleware’,

at top of MIDDLEWARE variable :

See docs :

CorsMiddleware should be placed as high as possible, especially before
any middleware that can generate responses such as Django’s
CommonMiddleware or Whitenoise’s WhiteNoiseMiddleware. If it is not
before, it will not be able to add the CORS headers to these
responses.

If you are testing this you need to ensure you include at least the Origin header in the request.

E.g.:

$ http GET http://127.0.0.1:8000/todos/ Origin:http://www.someorigin.com
HTTP/1.0 200 OK
Access-Control-Allow-Origin: *
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Date: Sat, 14 Nov 2015 04:42:38 GMT
Server: WSGIServer/0.1 Python/2.7.10
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

You will get more feedback with a preflight CORS request:

$ http OPTIONS http://127.0.0.1:8000/todos/ Origin:http://www.someorigin.com
HTTP/1.0 200 OK
Access-Control-Allow-Headers: x-requested-with, content-type, accept, origin, authorization, x-csrftoken, user-agent, accept-encoding
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 86400
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Date: Sat, 14 Nov 2015 04:45:37 GMT
Server: WSGIServer/0.1 Python/2.7.10
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

Somehow django-cors-headers would not work for me with Django 2 despite following all the steps. The pre-flight check would retrun a 405 error.

I ended up writing a small middleware:

from django import http


class CorsMiddleware(object):
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        if (request.method == "OPTIONS"  and "HTTP_ACCESS_CONTROL_REQUEST_METHOD" in request.META):
            response = http.HttpResponse()
            response["Content-Length"] = "0"
            response["Access-Control-Max-Age"] = 86400
        response["Access-Control-Allow-Origin"] = "*"
        response["Access-Control-Allow-Methods"] = "DELETE, GET, OPTIONS, PATCH, POST, PUT"
        response["Access-Control-Allow-Headers"] = "accept, accept-encoding, authorization, content-type, dnt, origin, user-agent, x-csrftoken, x-requested-with"
        return response

Then added this middleware in my settings.py :

MIDDLEWARE = [
    'apps.core.middleware.CorsMiddleware',
     ... others below it
]

This did the trick for me.

I guess corsheaders and clickjacking middlewares are not compatible. At least I got rid off X-Frame-Options header when I commented out django.middleware.clickjacking.XFrameOptionsMiddleware.

I’ve just CORS_ORIGIN_ALLOW_ALL = True setting.

I spent a couple of hours and tried a lot of solutions to fix this.
I think we need to followed the steps mentioned here

One more step:
Finally it works after I added:

CORS_ALLOW_HEADERS = [‘*’]

after:

ALLOWED_HOSTS=[‘*’]

CORS_ORIGIN_ALLOW_ALL = True

I think it allows all the headers including Authorization.

I tried installing django-cors-headers to fix the error I was getting when running my django app with production settings.

‘ URL ‘ from origin ‘http://localhost:3000’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

CORS ERROR

My app loads fine when running in development and installing django-cors-headers did not resolve the issue. For some reason chrome was blocking Material icons from loading when I was in production.

enter image description here

Once I discovered what the issue was I felt it was important to share how I fixed it as I feel a lot of people coming to this question will have the same circumstances.

This solution will hopefully work for those who are serving their static content (like images) from another server such as an AWS S3 bucket like I was and getting this error.

If you are and it is being blocked by chrome in the same way, installing django-cors-headers won’t do anything. This is because the problem lies with the configuration of the S3 bucket (Azure etc) and not the django app.

Go to the AWS S3 dashboard and once you select the bucket you are using to host the static files of your django app, click on the permissions tab.

permissions tab of s3 bucket

Scroll down to the cross-origin resource sharing (CORS) section and click ‘Edit’.

CORS section

And if you want to just resolve the issue completely (for just serving static files blocked by chrome), enter the following JSON and then click ‘Save changes’ at the bottom.

[
    {
        "AllowedHeaders": [],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

There is more information here on how to configure your S3 bucket’s CORS configuration.

After saving this configuration the error went away and my icons loaded properly.

icons loading properly

Footnote:

Given I was also misunderstanding how the Access-Control-Allow-Origin header worked I have taken an image from Mozilla’s Doc’s on Cross-Origin Resource Sharing but edited it to show my situation to hopefully explain how the header works.

server client diagram

Imagine that Chrome and localhost were exchanging mail and all of a sudden chrome starts getting mail from AWS but it doesn’t have Chromes name of it. Good guy Chrome is thinking, uh I don’t know if I should be viewing this information, it isn’t from the origin (localhost) so I don’t know if I’m allowed and it could be sensitive information sent by mistake. Therefore I won’t open it.

The Allow-Access-Control-Origin header is S3 writing on that mail ‘it’s ok, you (Chrome) have permission to view the information in this mail’.

django-cors-headers is necessary for situations were you have an app hosted on a server A (origin) that is making requests to a django app on server B, that is not the origin. For example, if your django app was a rest api hosted on heroku and you had a react/angular app hosted on Azure that made requests to that api – then your django app would need it.

django app that needs django-cors-headers

From Django 2 MIDDLEWARE_CLASSES is changed to MIDDLEWARE. In this case if you have Django 2 make sure the MIDDLWARE is as it should be such that MIDDLEWARES get executed.

Final solution would be send response with CORS allowed headers.

response["Access-Control-Allow-Origin"] = "*"
response['Content-Type'] = "application/json; charset=utf-8"
response["Access-Control-Allow-Origin"] = "*"
response["Access-Control-Allow-Methods"] = "GET, OPTIONS"
response["Access-Control-Max-Age"] = "1000"
response["Access-Control-Allow-Headers"] = "X-Requested-With, Content-Type, My-Token"

For me I had to add non-standard headers. Even if CORS_ORIGIN_ALLOW_ALL = True is set, it will still check if the headers are allowed.

from corsheaders.defaults import default_headers

CORS_ALLOW_HEADERS = list(default_headers) + [
    'my-custom-header',  
]

The same can be done for non-standard methods:

from corsheaders.defaults import default_methods

CORS_ALLOW_METHODS = list(default_methods) + [
    'POKE',
]

django-cors-headers works perfectly for handling CORS policy issue.

After doing the above steps, just try to clear browser cache or try making same request in chrome(incognito) or firefox(private window).

Are you trying to use the url inside an iframe?

If that is the case, then the header X-Frame-Options: SAMEORIGIN might be causing a problem.

To fix it remove the middleware, django.middleware.clickjacking.XFrameOptionsMiddleware.

I added ‘corsheaders.middleware.CorsMiddleware’ at the top of middleware array and it worked for me.

If none of the mentioned settings (After CORS installation and changing configs in settings.py) works, just turn off your adblocker if that is enabled for your local website. This small configuration worked for me.

For those who have CORS error for FONTS
For me the problem was solved by changing apache config.

add these lines of code to VirtualHost or .htaccess

for apache server, this file is in this directory:
/etc/apache2/sites-enabled/
important if ssl certificate is enabled for your website, these codes should be added to ssl config file

<IfModule mod_headers.c>
  <FilesMatch "\.(ttf|ttc|otf|eot|woff|font.css|css|woff2)$">
    Header set Access-Control-Allow-Origin "*"
  </FilesMatch>
</IfModule>

This worked for me:

python -m pip install django-cors-headers
MIDDLEWARE = [  
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
]

INSTALLED_APPS = [
    ...
    'corsheaders',
    ...
]

`ALLOWED_HOSTS = ['*']`

`CORS_ORIGIN_ALLOW_ALL = True`

Make sure to include: corsheaders.middleware.CorsMiddleware, as high as possible

For reference: https://pypi.org/project/django-cors-headers/, https://docs.djangoproject.com/en/3.0/ref/settings/

What I did was depreciate the version of django-cors-headers for it to work.
I moved from version 3.2.1 to 2.4.0. You can do that by installing the specific version using pip

pip install django-cors-headers==2.4.0


The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .