CORS error while consuming calling REST API with React
The currently accepted answer potentially opens sites up to security risks:
Why does the error happen:
In order for your AJAX request to work well, there are two things that need to happen:
- The request has to be accepted by the server.
- The returned request must be accepted by the browser, so that the client-side can do something with it.
The error that the OP reports, indicates that the second part of this process is failing. This is because if the request is sent from domain that is different to the server returning the request, the browser won't accept it unless the appropriate headers are set (that is, the server has given permission for the browser to read it).
How to fix it:
Now to fix this, we can use django-cors-headers
. This will add the apropriate headers, so that the browser accepts the returned response. To install run:
pip install django-cors-headers
and add it to your middleware:
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
Now, you need to add the domain you are sending your AJAX request from, to the list of allowed domains:
CORS_ALLOWED_ORIGINS = [
"www.example.com",
"http://127.0.0.1:8000",
...
]
What about CORS_ORIGIN_ALLOW_ALL
?
Do not use this unless you have a specific need to. Setting this to true, will mean that, any origin will be able to make a request to your API, and get a response. Unless you are making a public API, you probably won't need to do this. More likely you will only need to serve a single domain or a few domains (maybe you have a front-end, served from a different place to your API etc.)
If you are happy for any domain to access your API then you can set the following:
CORS_ORIGIN_ALLOW_ALL = True
If you do this, you will also need to set the following:
ALLOWED_HOSTS = ['*']
The reason for this, is Django will only accept certain hosts by default, so there's no point setting CORS_ORIGIN_ALLOW_ALL = True
unless you're actually going to accept requests from anyone (that is the part 1 in the explanation above).
Note that by setting allowed hosts to a wildcard, you open yourself up to HTTP host header attacks. Make sure you understand these, and have made sure you are not affected. You can read more about them in the django docs.
Also note: if you have not set your ALLOWED_HOSTS
and you are wondering why your requests are working, it is because when DEBUG=True
certain hosts are allowed automatically, http://127.0.0.1:8000
etc.
Install django-cors-headers through pip install django-cors-headers
Then, add in installed apps 'corsheaders'.
Add the setting,
CORS_ORIGIN_ALLOW_ALL = True
and,
ALLOWED_HOSTS = ['*']
This should do the trick.
UPDATE
You'll also need to add it to the middlewares,
MIDDLEWARE = [ # Or MIDDLEWARE_CLASSES on Django < 1.10
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]