托管在同一服务器上的Django和React的CORS问题

时间:2019-01-25 19:39:44

标签: django reactjs nginx cors vagrant

我的Django Rest Framework和React应用程序在同一服务器上遇到了CORS问题。我正在运行带有Ubuntu 18盒并安装了NGINX的Vagrant(我假设此问题将转化为DigitalOcean),如果我提供的信息过多,我会深表歉意。 DRF正在使用Supervisor,而Gunicorn在端口8000上。我使用create-react-app创建了我的React应用。然后,我使用npm run build创建了静态文件。

NGINX设置:

反应会议

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设置:

INSTALLED_APPS = [
    ...
    'rest_framework',
    'corsheaders',
    'myapp',
]
MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    ...
]

我没有运气尝试过以下

CORS_ORIGIN_ALLOW_ALL = True

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":"test@user.com", "password":"testuser"}),
})

因此声明明显的CORS是正确的,因为Origin是localhost:8080,这是一个不同的端口,因此它将其视为交叉源。我尝试了使用cors origin允许的不同设置,但是每次仍然是相同的问题。显然我做错了,但看不到。

我的想法是

选项1

使用django nginx conf文件进行

proxy传递,并取消了react nginx conf文件,但是我不知道这可能对生产造成什么影响,或者这是否是个好主意。有更好的方法吗?

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;

因此确定我的想法和问题。尝试为CORS使用不同的Django选项后,我仍然收到CORS错误。为什么,是我的NGINX conf文件引起的还是其他原因?我希望在DigitalOcean中看到这一点吗?

更新1

我忘记添加错误。这是CORS错误

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).

对于那些想了解“网络”标签中的输出的人

Host    localhost:8000
Origin  http://192.168.19.76:8080
Pragma  no-cache
Referer http://192.168.19.76:8080/

更新2 我使用curl进行了测试,一切都按预期返回,所以我知道DRF正在正常工作。

curl --data "email=test@user.com&password=testuser" http://localhost:8000/api/v1/token-auth/

最终更新

感谢paulsm4的所有帮助,而且简直很棒。

所以,我放弃了django-cors-headers并推出了自己的。为了回答paulsm4的问题,尽管我确实考虑过让NGINX处理CORS与Django,但我在NGINX文件中没有add_header 'Access-Control-Allow-Origin' '*';,但从未走过这么远。 @ paulsm4,这是我在说的proxy_pass。关键是将这段代码块与我的中间件一起添加到NGINX的react部分。

    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;

上面的代码本身可以工作,但是它不允许我将任何传入的URL列入白名单。创建自己的中间件使我可以列入白名单。我不知道为什么django-cors-header甚至django-cors-middleware对我不起作用。奇怪的是,除了我问的CORS错误以外,fetch从未使这两个软件包足够远地获得响应标头和任何类型的错误。使用我编写的中间件,fetch能够完全进行调用,并无论成功还是失败都返回一些响应头。

为将来参考,我可能会重新访问NGINX并允许其处理CORS。这是一个很好的链接 CORS on NGINX

注意

澄清;除了Django已经包含的之外,唯一安装的中间件是cors中间件。 Django和React都位于同一台服务器上,但是端口不同。

  1. api.sandbox.com:8000是Django Rest Framework
  2. app.sandbox.com:8080是React静态文件
  3. Django 2.0.2
  4. Python 3.6
  5. django-cors-headers 2.4.0
  6. Vagrant / VirtualBox Ubuntu 18.04
  7. NGINX

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'
)

反应App.js

    fetch("http://localhost:8000/api/v1/token-auth/", {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            "email": "test@user.com", 
            "password": "testuser"
       }),
    })

所以我很机智。可能是django-cors-header无法正常工作,也可能是NGINX。

1 个答案:

答案 0 :(得分:2)

我们一直在交换意见;这是我目前的理解:

问题:您有一个Django后端API(在端口8080上)和一个React前端(在端口8000上)。两者当前都在localhost上运行,但最终将驻留在DigitalOcean上。 React客户端正在获取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).

您需要配置CORS。

您捕获的HTTP流量中的请求标头清楚地表明这尚未发生。

一些相关的链接包括:

建议的下一步:

如果尚未安装,请安装并配置django-cors-headers