首页 > 解决方案 > 用于 CORS 和正确 HTTPS 重新路由的 NGINX 配置

问题描述

嗨,我对 NGINX 非常缺乏经验,并且很难理解为什么事情没有按预期工作。我正在尝试测试使用 docker 容器制作的 API,该容器使用以下命令运行:docker run -d -v $(pwd):/app -p 8080:8000 --rm wiseeast/ya_bot.

我可以通过http://ffpr.isi.edu:8080/apiPOST 请求使用 Postman 发出 API 请求,但是使用 javascript 在 AJAX 上的相同请求会返回一个明显频繁的No 'Access-Control-Allow-Origin' header is present on the requested resource.错误。我试图通过添加在我的服务器上启用 CORS 来绕过此问题,add_header 'Access-Control-Allow-Origin' '*' always;因为我可以控制它,但它并没有解决问题。另外让我烦恼的是,使用 Postman 我可以成功地向 POST 请求http://ffpr.isi.edu:8080/api但不能向https://ffpr.isi.edu:8080/api.

另外,我有一个重新路由问题,鉴于我已阅读但无法正常工作,我认为应该直截了当。我有一个正确重新路由http://ffpr.isi.edu到的网页,https://ffpr.isi.edu但其余的重新路由不起作用。例如http://ffpr.isi.edu:5050/不安全地通过端口 80 加载,并且不会重新路由到https://ffpr.isi.edu:5050/. 另一方面,https://ffpr.isi.edu:5050/根本不会打开超时错误。

这是我的完整nginx.conf文件:

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;


    upstream frontend {
        server 0.0.0.0:8000; 
    }

    upstream ased_api {
        server 0.0.0.0:5000; 
    }

    upstream ya_bot {
        server 0.0.0.0:8080; 
    }

    upstream yesand {
        server 0.0.0.0:5050; 
    }


    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        return 301 https://$host$request_uri;
    }

# Settings for a TLS enabled server.
#

    server {
        listen  443 ssl http2; 
        listen  [::]:443 ssl http2;
        server_name ffpr.isi.edu; 

        ssl_certificate "/etc/nginx/ssl/ffpr_isi_edu_cert.cer";
        ssl_certificate_key "/etc/nginx/ssl/ffpr_isi_edu.key";
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

    location / {
        add_header 'Access-Control-Allow-Origin' '*';
        proxy_pass      http://frontend; 
        proxy_redirect      off;
        proxy_set_header    Host $host; 
        proxy_set_header    X-Real-IP $remote_addr; 
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Host $server_name;
    }

    location /api {
                proxy_pass              http://ased_api;
                proxy_redirect          off;
                proxy_set_header        Host $host;
                proxy_set_header        X-Real-IP $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header        X-Forwarded-Host $server_name;
    }

    location /ya_bot {
                proxy_pass              http://ya_bot;
                proxy_redirect          off;
                proxy_set_header        Host $host;
                proxy_set_header        X-Real-IP $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header        X-Forwarded-Host $server_name;
                add_header      'Access-Control-Allow-Origin' '*' always;
                add_header 'Access-Control-Allow-Credentials' 'true';
                add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
        }

    location /yesand {
                add_header 'Access-Control-Allow-Origin' '*';
                proxy_pass              http://yesand;
                proxy_redirect          off;
                proxy_set_header        Host $host;
                proxy_set_header        X-Real-IP $remote_addr;
                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header        X-Forwarded-Host $server_name;
        }
    }



    server {
        listen       443 ssl http2 default_server;
        listen       [::]:443 ssl http2 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        ssl_certificate "/etc/nginx/ssl/ffpr_isi_edu_cert.cer";
        ssl_certificate_key "/etc/nginx/ssl/ffpr_isi_edu.key";
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

}

我已经为这些问题困扰了很长时间,任何指针都非常感谢!

标签: nginx

解决方案


根据我的经验, add_header 'Access-Control-Allow-Origin' '*'; 在代理机器上没有解决问题。

但是,将后端 API 中的“Access-Control-Allow-Origin”标头设置为响应标头确实有效。例如,您可以在后端 API 上运行以下 Go 代码:

(*w).Header().Set(“Access-Control-Allow-Credentials”, “proxy-host-name”) 

至于重定向问题,您不需要使用两个单独的服务器块,而是在 nginx.conf 中尝试这个:

server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  _;


    listen  443 ssl http2; 
    listen  [::]:443 ssl http2;
    server_name ffpr.isi.edu; 

    ssl_certificate "/etc/nginx/ssl/ffpr_isi_edu_cert.cer";
    ssl_certificate_key "/etc/nginx/ssl/ffpr_isi_edu.key";
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

   if ($scheme != https) {
        return 301 https://$host$request_uri
   }
}

我希望这有帮助。


推荐阅读