【问题标题】:Enable Cors on node.js app with nginx proxy使用 nginx 代理在 node.js 应用上启用 Cors
【发布时间】:2016-05-24 20:34:14
【问题描述】:

我已经设置了一个数字海洋水滴,它是一个使用 nginx 和节点的反向代理服务器。我以数字海洋中的本教程为起点

https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-14-04

我还设置了带有 let encrypt 的 ssl。我目前遇到的问题是我无法对服务器进行跨域 ajax 调用。我收到 No 'Access-Control-Allow-Origin' header is present 的错误消息。我已经在我的节点应用程序中设置了适当的标头响应,并尝试遵循我可以为 nginx 找到的几个示例,但没有运气。下面是我的代码。

nginx 删除了我对标头的尝试

server {
listen 443 ssl;

server_name lefthookservices.com www.lefthookservices.com;

ssl_certificate /etc/letsencrypt/live/lefthookservices.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/lefthookservices.com/privkey.pem;

 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-$
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_stapling on;
    ssl_stapling_verify on;
    add_header Strict-Transport-Security max-age=15768000;

location / {


    proxy_pass http://127.0.0.1:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;



}
  location ~ /.well-known {
           allow all;
    }

}

server {
    listen 80;
    server_name lefthookservices.com  www.lefthookservices.com;
    return 301 https://$host$request_uri;
}

这是我使用 express 的 app.js 脚本

    'use strict';
var colors = require('colors/safe');

var express = require('express');

var knack = require('./knack_call.js');

var bodyParser = require('body-parser');

var cors = require('cors');

colors.setTheme({
  custom: ['blue', 'bgWhite']
});

var app = express();

app.use(bodyParser.json());


// allow for cross domain ajax

app.get('/',  function(request, response){

    response.send('hello\n');

});

app.post('/', function(request, response){

    response.header("Access-Control-Allow-Origin", "*");
    response.header("Access-Control-Allow-Headers", "X-Requested-With");
    response.header("Access-Control-Allow-Methods', 'GET,POST");

    knack.getData(request, response);
});

app.listen(8080, '127.0.0.1', function(m){
    console.log(colors.custom("Captin the server is at full strength"));
});

任何可以帮助我设置正确的标题以允许 CORS 的建议将不胜感激。提前谢谢你。

由于 Tristans 在下面的回答,我的 Nginx 代码现在看起来像这样。

server {
    listen 443 ssl;

    server_name lefthookservices.com www.lefthookservices.com;

    ssl_certificate /etc/letsencrypt/live/lefthookservices.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/lefthookservices.com/privkey.pem;

     ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_dhparam /etc/ssl/certs/dhparam.pem;
        ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES$
        ssl_session_timeout 1d;
        ssl_session_cache shared:SSL:50m;
        ssl_stapling on;
        ssl_stapling_verify on;
        add_header Strict-Transport-Security max-age=15768000;

    location / {

        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        if ($http_origin ~*(https?://.*\exponential.singularityu\.org(:[0-9]+)?$)){
            set $cors "1";
        }
        if ($request_method = 'OPTIONS') {
             set $cors "${cors}o";
           }


        if ($cors = "1") {
          more_set_headers 'Access-Control-Allow-Origin: $http_origin';
          more_set_headers 'Access-Control-Allow-Credentials: true';
          proxy_pass      http://127.0.0.1:8080;
        }

        if ($cors = "1o") {
           more_set_headers 'Access-Control-Allow-Origin: $http_origin';
           more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE';
           more_set_headers 'Access-Control-Allow-Credentials: true';
           more_set_headers 'Access-Control-Allow-Headers: Origin,Content-Type,Accept';
           add_header Content-Length 0;
           add_header Content-Type text/plain;
           return 204;
         }

        proxy_pass http://127.0.0.1:8080;




    }
}
location ~ /.well-known {
           allow all;
    }

}

遗憾的是这仍然不起作用。

server {
    listen 80;
    server_name lefthookservices.com  www.lefthookservices.com;
    return 301 https://$host$request_uri;
}

【问题讨论】:

    标签: node.js nginx proxy cors digital-ocean


    【解决方案1】:

    事实证明,我收到的错误消息不准确。问题不是标题设置。事实证明,我需要使用 jsonp 发出请求,并且需要以不同的方式处理传入的数据。 app.js 调用的函数中出现错误,导致连接超时。这导致适当的标头未返回到导致错误消息的浏览器。

    对于任何希望找到有效的 NGINX 配置的人,这是我的。

    proxy_pass http://127.0.0.1:8080;
       # proxy_http_version 1.1;
        proxy_set_header Access-Control-Allow-Origin *;
       # proxy_set_header Upgrade $http_upgrade;
       # proxy_set_header Connection '';
        proxy_set_header Host $host;
       # proxy_cache_bypass $http_upgrade;
    

    感谢您的建议。

    【讨论】:

      【解决方案2】:

      将 Nginx 排除在这个等式之外。如果您的设置与我的设置相似,那么它与您的 COR 问题没有任何关系,我相信它是。我看到您正在使用 cors 模块,但我可以看到您实际上并没有使用它。

      您的设置足够简单,您或许可以摆脱默认设置,因此,在app.use(bodyParser.json()); 正下方,将您的app.js 更新为:

      app.use(cors());
      

      这可能开箱即用。如果没有,您可以传递一组选项。我的看起来像这样:

      app.use(cors({
          origin: myorigin.tld, 
          allowedHeaders: [ 'Accept-Version', 'Authorization', 'Credentials', 'Content-Type' ]
      }));
      

      文档中提供了其他配置选项。

      【讨论】:

      • 我在使用 socket.io 时遇到了类似的问题。我必须正确设置原始规则。我一直在寻找 nginx 配置中的问题,但它只是从上游传递 400 错误。
      【解决方案3】:

      你快到了。

      您必须将代理视为外部服务器以及您的 Node.js 应用程序。

      所以,简而言之,你需要在你的 nginx 配置中添加一个标头。

      看看这个链接, https://gist.github.com/pauloricardomg/7084524

      万一这被删除了:

      #
      # Acts as a nginx HTTPS proxy server
      # enabling CORS only to domains matched by regex 
      # /https?://.*\.mckinsey\.com(:[0-9]+)?)/
      #
      # Based on: 
      # * http://blog.themillhousegroup.com/2013/05/nginx-as-cors-enabled-https-proxy.html
      # * http://enable-cors.org/server_nginx.html
      #
      server {
        listen 443 default_server ssl;
        server_name localhost;
      
        # Fake certs - fine for development purposes :-)
        ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
        ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
      
        ssl_session_timeout 5m;
      
        location / {
          proxy_redirect off;
          proxy_set_header Host $host;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      
          # Nginx doesn't support nested If statements, so we
          # concatenate compound conditions on the $cors variable
          # and process later
      
          # If request comes from allowed subdomain
          # (*.mckinsey.com) then we enable CORS
          if ($http_origin ~* (https?://.*\.mckinsey\.com(:[0-9]+)?$)) {
             set $cors "1";
          }
      
          # OPTIONS indicates a CORS pre-flight request
          if ($request_method = 'OPTIONS') {
             set $cors "${cors}o";
          }
      
          # Append CORS headers to any request from 
          # allowed CORS domain, except OPTIONS
          if ($cors = "1") {
             more_set_headers 'Access-Control-Allow-Origin: $http_origin';
             more_set_headers 'Access-Control-Allow-Credentials: true';
             proxy_pass      http://serverIP:serverPort;
          }
      
          # OPTIONS (pre-flight) request from allowed 
          # CORS domain. return response directly
          if ($cors = "1o") {
             more_set_headers 'Access-Control-Allow-Origin: $http_origin';
             more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE';
             more_set_headers 'Access-Control-Allow-Credentials: true';
             more_set_headers 'Access-Control-Allow-Headers: Origin,Content-Type,Accept';
             add_header Content-Length 0;
             add_header Content-Type text/plain;
             return 204;
          }
      
          # Requests from non-allowed CORS domains
             proxy_pass      http://serverIP:serverPort;
        }
      }
      

      【讨论】:

      • 感谢特里斯坦的回复。可悲的是,这仍然对我不起作用。我编辑了我的原始问题,以包括我尝试实施您的解决方案。任何进一步的帮助将不胜感激。绝对是 nginx 初学者。
      猜你喜欢
      • 1970-01-01
      • 2018-02-09
      • 2020-04-18
      • 2019-06-27
      • 2015-04-20
      • 1970-01-01
      • 2016-09-17
      • 2020-05-15
      • 2023-03-24
      相关资源
      最近更新 更多