4

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

9
  • Can you given an example of a failing POST request? Does it perhaps contain a non-standard header not allowed by CORS? Commented May 7, 2022 at 12:19
  • I ca try tomorrow. I am far away. By the way, you can try to launch it. I added repo to it. Commented May 7, 2022 at 12:25
  • 1
    You write that you call the backend on port 1338, but in your repo it seems vice versa: The frontend is called at localhost:1338 and requests go to the backend at localhost:1337. In that case, you also need CORS_ALLOWED_ORIGINS = ["http://localhost:1338"]. Commented May 7, 2022 at 12:36
  • Share your nginx configuration as well. Also are you using any prefix with the urls that you passed in CORS_URLS_REGEX ? Also I feel the configuration is missing in nginx Commented May 7, 2022 at 14:11
  • @HeikoTheißen Yes frontend is 1338, but it calls nginx on port 1337, which calls 8000 (exposed port) backend server. If you have docker it can be launched and checked with different options. That is why I created this project. Commented May 9, 2022 at 13:55

2 Answers 2

5

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

Sign up to request clarification or add additional context in comments.

3 Comments

@K.I. Can you share the screenshots of your request and response headers from the network tab so we can identify the issue more clearly?
Added to post as asked,
This solution you referenced in your answer solved my problem.
0

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" "-"

1 Comment

Yes I know that I can run it from dfr browsable api. But how to fix it in code? I run standard axios post call in frontend/src/App.js: const handleInsert = async () => { const response = await axios.post( "localhost:1337/Country", country ); }; Some headers disappears :) during request from fronted?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.