'Cors problem with nginx/django from react app on docker
I have a question about cors implementation in django. Having a problem with setting the correct cors values. My deployment is on docker. I have a deployed 3 containers:
- backend: Django + DRF as backend (expose 8000 port)
- Nginx to server my backend (use exposed 8000 port and set it to 1338)
- frontend React app used with nginx (uses port 1337)
Everything is on localhost. I use axios from frontend to call get/post requests. (I call to 1338 port then I think it is redirected to internal service on 8000 port) For backend I had to install django-cors-headers package to work with CORS. I think I set up it correctly. But there are scenarios where it does not work.
In settings.py
INSTALLED_APPS = [
...
"corsheaders",
]
...
MIDDLEWARE = [
...
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
...
]
Nginx.conf for nginx image:
upstream backend {
server backend:8000;
}
server {
listen 80;
add_header Access-Control-Allow-Origin *;
location / {
proxy_pass http://backend;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host:1337;
proxy_redirect off;
}
location /static/ {
alias /home/app/web/staticfiles/;
}
}
First scenario
In settings.py
CORS_ALLOW_ALL_ORIGINS = True
No get/post requests work. Get message:
CORS Multiple Origin Not Allowed
Second scenario
In settings.py
CORS_ALLOWED_ORIGINS = ["http://localhost:1337"]
Works with get requests, but does not work with post requests.
For post requests:
- options with error: CORS Missing Allow Header
- post with error: NS_ERROR_DOM_BAD_URI
It works if I am not using nginx for backend.
Adding request headers as requested in the comment.
I am not sure what else could I add here. So my deployed project is here (it also is easy to launch if you have docker on your machine: https://gitlab.com/k.impolevicius/app-001
Solution 1:[1]
I have come across this issue a while back, and I think the issue is with the headers. In the MDN docs, it is stated here that other than for the simple requests, we'll get preflighted requests with OPTIONS method. There are 3 main headers that we need to send in response in your case
Access-Control-Allow-Origin: http://localhost:1337
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
From the looks of it you have configured the first header and you should be seeing it in the network tab too, and since the error is about missing allow headers, you need to add Access-Control-Allow-Methods
header
to your nginx file
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
Seeing your network tab on the requested headers will give more context here, generally you should be seeing Access-Control-Request-Method
and Access-Control-Request-Headers
headers in the OPTIONS
request. If there are some headers that you aren't allowing, please write an nginx rule for the same. You can look into this solution for more reference
Solution 2:[2]
Good day, seems that problem is in axios.post
not in Django or nginx.
Because if you do curl post or post from drf browsable api, it works fine:
curl -X POST http://localhost:1337/Country/ \
-H "Content-Type: application/json" \
-d '{"name": "other"}'
{"id":6,"name":"other"}%
But react app generates this OPTIONS
request:
app-001-backend-1 | [13/May/2022 05:56:20] "OPTIONS /Country/ HTTP/1.0" 200 0
app-001-nginx-1 | 192.168.240.1 - - [13/May/2022:05:56:20 +0000] "OPTIONS /Country/ HTTP/1.1" 200 0 "http://localhost:1338/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Safari/605.1.15" "-"
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Chaitanya Tetali |
Solution 2 | akun.dev |