我目前有以下 nginx 文件
server_tokens off;
upstream backend {
server unix:/home/www/api.to/app.sock weight=1;
#server 1.2.3.4 weight=1;
#server api3.example.com weight=1;
}
server {
server_name api.example.com;
client_max_body_size 10000m;
gzip_disable "msie6";
access_log off;
error_log on;
gzip_vary on;
gzip on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types application/javascript application/font-ttf ttf text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
location /word/report.html {
alias /var/log/nginx/report.html;
}
location / {
proxy_pass http://backend;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_read_timeout 1000; # this
}
location /static/downloads {
alias /home/www/api.to/static/downloads/;
add_header Content-disposition "attachment; filename=$1";
default_type application/octet-stream;
}
location /static/ {
alias /home/www/api.to/static/;
expires 35d;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
access_log off;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/api.example.com-0001/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/api.example.com-0001/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
当我发出发布请求并且只让上游进入本地 unix sock 时,它工作正常。
当我将上游更改为 1.2.3.4 或 api3.example.com 时,它会返回 CORS 问题。
两个系统都有同一个应用程序(api3.example.com 是 1.2.3.4 服务器 IP)。
如果我从本地向 api3.example.com 发送 post 请求,它会响应并运行。如果我从本地向 1.2.3.4 发送 post 请求,它也会响应并运行。
我推出了自己的自定义 CORS 中间件,如下所示,尽管我不认为它起到什么作用,因为它可以从其他来源正常工作,除非在上游。
middleware.py 位置
from django import http
class CorsMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
if (request.method == "OPTIONS" and "HTTP_ACCESS_CONTROL_REQUEST_METHOD" in request.META):
response = http.HttpResponse()
response["Content-Length"] = "0"
response["Access-Control-Max-Age"] = 86400
response["Access-Control-Allow-Origin"] = "*"
response["Access-Control-Allow-Methods"] = "DELETE, GET, OPTIONS, PATCH, POST, PUT"
response["Access-Control-Allow-Headers"] = "cache-control, accept, accept-encoding, authorization, content-type, dnt, origin, user-agent, x-csrftoken, x-requested-with"
return response
考虑到所有这些,出现的 CORS 错误如下图所示。但它们通常Response body is not available to scripts (Reason: CORS Missing Allow Origin)
都说Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.example.to/new/pdf-word/. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 404.
以及 CORS 缺少允许来源和 NS_ERROR_DOM_BAD_URI
我花了很多时间尝试调试这个问题,但仍然无济于事。nginx/1.22.1 版本
答案1
我能够实现这一点的唯一方法是将上游发送到接收服务器上的另一个端口。
IE
upstream backend {
server unix:/home/www/api.to/app.sock weight=1;
server 1.2.3.4:80000 weight=1;
}
并在接收 nginx 文件中放入
listen 8000;
在监听 80/443(分别是您使用的)旁边,或者正如我刚刚意识到的......将上游发送到 443。这都是因为我通过上游将流量发送到 IP,但将其发送到端口 80,我的应用程序在 ssl 端口 443 上。因此,在监听并发送到端口 8000 时它会起作用。