我的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都位于同一台服务器上,但是端口不同。
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。
答案 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