为什么调用 API 时会出现 CORS 错误?

Why CORS error come out when I call an API?

我部署了一个项目,它有两个 API,分别是 loginloadMenu,到服务器。当我调用 login API 时,一切正常,我得到了结果。

但是当我尝试调用 loadMenu API 时,出现了 CORS 问题。

这是我的 nginx 配置文件:

server {
  listen 80;
  # set proper server name after domain set
  server_name xxxxxx;

  # Add Headers for odoo proxy mode
  proxy_set_header X-Forwarded-Host $host;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Real-IP $remote_addr;
  add_header X-Frame-Options "SAMEORIGIN";
  add_header X-XSS-Protection "1; mode=block";
  proxy_set_header X-Client-IP $remote_addr;
  proxy_set_header HTTP_X_FORWARDED_HOST $remote_addr;

  #   odoo    log files
  access_log  /var/log/nginx/odoo15-access.log;
  error_log       /var/log/nginx/odoo15-error.log;

  #   increase    proxy   buffer  size
  proxy_buffers   16  64k;
  proxy_buffer_size   128k;

  proxy_read_timeout 900s;
  proxy_connect_timeout 900s;
  proxy_send_timeout 900s;

  #   force   timeouts    if  the backend dies
  proxy_next_upstream error   timeout invalid_header  http_500    http_502
  http_503;

  types {
    text/less less;
    text/scss scss;
  }

  #   enable  data    compression
  gzip    on;
  gzip_min_length 1100;
  gzip_buffers    4   32k;
  gzip_types  text/css text/less text/plain text/xml application/xml application/json 
  application/javascript application/pdf image/jpeg image/png;
  gzip_vary   on;
  client_header_buffer_size 4k;
  large_client_header_buffers 4 64k;
  client_max_body_size 0;

    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
  location / {
    #add_header 'Access-Control-Allow-Origin' "$http_origin" always;
    #add_header 'Access-Control-Allow-Credentials' 'true' always;
    if ($request_method = OPTIONS) {
        add_header 'Access-Control-Allow-Origin' "$http_origin"; # DO NOT remove THIS LINES (doubled with outside 'if' above)
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Max-Age' 1728000; # cache preflight value for 20 days
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'My-First-Header,My-Second-Header,Authorization,Content-Type,Accept,Origin';
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
       return 204;
    }
    if ($request_method = POST) {
        add_header 'Access-Control-Allow-Origin' "$http_origin";
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' *;
    }
    #proxy_set_header host $http_host;    
    proxy_pass    http://127.0.0.1:8069;
    # by default, do not forward anything
    proxy_redirect off;
    proxy_cookie_path / "/; secure; HttpOnly;SameSite=None";
  }


  location /longpolling {
  proxy_pass http://127.0.0.1:8072;
  }
  location ~* .(js|css|png|jpg|jpeg|gif|ico)$ {
  expires 2d;
  proxy_pass http://127.0.0.1:8069;
  add_header Cache-Control "public, no-transform";
  }
  # cache some static data in memory for 60mins.
  location ~ /[a-zA-Z0-9_-]*/static/ {
  proxy_cache_valid 200 302 60m;
  proxy_cache_valid 404      1m;
  proxy_buffering    on;
  expires 864000;
  proxy_pass    http://127.0.0.1:8069;
  }
}

这里是错误信息

Access to fetch at 'http://127.0.0.1:8069/web/login?redirect=http%3A%2F%2F127.0.0.1%3A8069%2Fweb%2Fwebclient%2Fload_menus%2F1652856182783' (redirected from 'http://IP/web/webclient/load_menus/1652856182783') from origin 'http://localhost:8069' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

在此处使用 stab-in-the-dark,但我猜您在 127.0.0.1:8069(在服务器上)的 API 正在响应 fully-qualified 重定向 URL , 例如

< HTTP/1.1 302 Found
< Location: http://127.0.0.1:8069/web/login?...

这显然不是 URL 服务器内部网络之外的任何东西都可以访问的。

您缺少的是 proxy_redirect 配置以重写 Location 响应 headers 以使用 外部 地址...

proxy_redirect default;

# or the more verbose equivalent
# proxy_redirect http://127.0.0.1:8069 /;

如您的 last attempt at this question, it's usually a sign of something wrong with your API design 所述,如果它以 301 / 302 重定向响应。