I am having a CORS issue with my Django Rest Framework and React app on the same server. I am running Vagrant with an Ubuntu 18 box and NGINX installed (I am assuming this issue will translate to DigitalOcean) I apologize ahead of time if I am providing too much information. DRF is using Supervisor and Gunicorn is on port 8000. I created my React app using create-react-app. I then used npm run build
to create the static files.
NGINX Setup:
React Conf
server {
listen 8080;
server_name sandbox.dev;
root /var/sites/sandbox/frontend/build;
index index.html;
client_max_body_size 4G;
location / {
try_files $uri $uri/ /index.html;
}
Django Conf
upstream sandbox_server {
server unix:/var/tmp/gunicorn_sanbox.sock fail_timeout=0;
}
server {
listen 8000;
server_name api.sandbox.dev;
...
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://sandbox_server;
break;
}
Django Setup:
INSTALLED_APPS = [
...
'rest_framework',
'corsheaders',
'myapp',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
...
]
I have tried the following with no luck
CORS_ORIGIN_ALLOW_ALL = True
and
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = ('192.168.19.76:8080','localhost:8080',)
React App.js
...
fetch("http://localhost:8000/api/v1/token-auth/", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({"email":"[email protected]", "password":"testuser"}),
})
So to state the obvious CORS is correct because the Origin is localhost:8080 which is a different port so it sees it as cross origin. I have tried the different settings with cors origin allow, but it is still the same issue every time. Obviously I am doing something wrong, but I can't see it.
My thoughts are
Option 1
proxy pass using the django nginx conf file and do away with the react nginx conf file, but I don't know what affect that might cause in production or if this is a good idea. Is there a better way?
location /api {
proxy_set_header X-Forwarded_for $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://sandbox_server;
So finalize my thoughts and my question. After trying the different Django options for CORS I am still getting the CORS error. Why, and is it my NGINX conf files causing it or something else? Will I expect to see this in DigitalOcean?
UPDATE 1
I forgot to add the error. Here is the CORS error
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8000/api/v1/token-auth/. (Reason: CORS request did not succeed).
For those wanting to know the output from the network tab
Host localhost:8000
Origin http://192.168.19.76:8080
Pragma no-cache
Referer http://192.168.19.76:8080/
UPDATE 2 I did test using curl, and everything returned as expected so I know DRF is working corrently.
curl --data "[email protected]&password=testuser" http://localhost:8000/api/v1/token-auth/
FINAL UPDATE
Thanks to paulsm4 for all the help and just plain awesomeness.
So, I did abandon django-cors-headers and rolled my own. To answer paulsm4's question, I do not have add_header 'Access-Control-Allow-Origin' '*';
in the NGINX file although I did think about letting NGINX handle CORS vs Django, but never went that far. @paulsm4, this is the proxy_pass I was talking about. The key was adding this block of code to NGINX for the react portion in conjunction with my middleware.
location /api {
proxy_set_header X-Forwarded_For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://sandbox_server;
The above code by itself worked, but it did not allow me to whitelist any incoming URLs. Creating my own middleware allowed me to whitelist. I have no idea why django-cors-headers or even django-cors-middleware did not work for me. What was strange was that fetch never made it far enough with those two packages to get response headers and an error of any sorts, other than the CORS error I was asking about. With the middleware I wrote, fetch was able to fully make the call, and return some response headers whether it succeeded or failed.
For future reference, I might revisit NGINX and allowing it to handle CORS. Here is a good link CORS on NGINX
NOTE
To clarify; the only middleware installed besides what Django already includes is the cors middleware. Both Django and React reside on the same server, but with different ports.
Django settings.py
INSTALLED_APPS = [
...
# Third Party
'rest_framework',
'corsheaders',
# My Apps
'account',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
'django.middleware.csrf.CsrfViewMiddleware',
'corsheaders.middleware.CorsPostCsrfMiddleware',
...
]
CORS_ORIGIN_WHITELIST = (
'null',
'192.168.19.76:8080',
'localhost:8080',
'app.sandbox.com:8080'
)
React App.js
fetch("http://localhost:8000/api/v1/token-auth/", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
"email": "[email protected]",
"password": "testuser"
}),
})
So I am at wits end here. It is either django-cors-headers that is not working or it could possibly be NGINX.
We've been exchanging comments; here's my current understanding:
PROBLEM: You have have a Django back-end API (on port 8080) and a React Front end (on port 8000). Both are currently running on localhost, but will ultimately reside on DigitalOcean. The React client is getting Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8000/api/v1/token-auth/. (Reason: CORS request did not succeed).
You need to configure CORS.
The request headers in the HTTP traffic you've captured clearly shows this isn't happening yet.
Some relevant links include:
django-cors-headers not work
Handling CORS in Django REST Framework
Djgano REST Framework: CORS
SUGGESTED NEXT STEP:
If you haven't already, please install and configure django-cors-headers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With