'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

enter image description here

It works if I am not using nginx for backend.

Adding request headers as requested in the comment.

enter image description here

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