使用nginx代理在node.js应用上启用Cors

时间:2016-05-19 22:52:46

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

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

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

我还设置了带加密的ssl。我目前遇到的问题是我无法对服务器进行跨域ajax调用。我收到一个错误,没有'Access-Control-Allow-Origin'标题存在。我已在我的节点应用程序中设置了相应的标头响应,并尝试按照我可以找到的nginx的几个示例而没有运气。以下是我的代码。

nginx我尝试删除标题

    '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"));
});

这是我的app.js脚本使用快递

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;
    }

}

任何可以帮助我设置正确标头以允许CORS的建议都将非常感激。提前谢谢。

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

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

可悲的是,这仍然不起作用。

<!DOCTYPE html>
<html>
    <head>
        <title>v0.01 Multi Section Page</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <style>
            body {
               background-color: #efefef;
               font-family: sans-serif;
               text-align: left;
               padding: 20px 0 0 20px;
            }
            
            .mainScr {
               max-width: 1500px;
               margin: 1px;

            }
            
            .mainInfo {
                background-color: #D4FCD5;
                min-width: 495px;
                max-width: 1470px; 
                min-height: 100px;
                border: 1px double green;
            }

            .screenParts {
                vertical-align: top;
                width: 49%;
                max-width: 730px;
                min-width: 495px;
                min-height: 450px;
                border: 1px solid white;
                background: #F7E7C4;
                margin: 1px;
                display: inline-block;
            }
            
            .graphicsPanel {
                width: 100%;
                height: 66%;
                border: 1px solid blue;
                background: lightblue;
            }
          
            .dataPlots {
                width: 100%;
                height: 33%;
                border: 1px solid brown;
                background: beige;
            }
            
            .infoSubPanel {
                min-height:450px;
                width:48%;
                min-width: 250;
                display:inline-flex;
                border: 1px solid brown;
            }
            .scrollabletextbox {
                width: 100%;
                height: 100%;
                min-height: 500px;
                font-family: Verdana, Tahoma, Arial, Helvetica, sans-serif;
                font-size: 100%;
                overflow:scroll;
                resize: none;
                text-align: left;
            }
        </style>
    </head>
      
    <body>
        <div class="mainInfo">
            <h1>Very important data goes here...</h1>
        </div>        
        <div class="mainScr">     
            <div id="visual" class="screenParts">
                <div class="graphicsPanel">
                    <h1>Some Graphics Goes Here</h1>
                    <h1>Some Graphics Goes Here</h1>
                    <h1>Some Graphics Goes Here</h1>
                    <h1>Some Graphics Goes Here</h1>
                    <h1>Some Graphics Goes Here</h1>
                </div>
                
                <div class="dataPlots">
                    <div style="display: block;">
                        <p> charts and plots go here</p>
                        <p> charts and plots go here</p>
                        <p> charts and plots go here</p>
                        <p> charts and plots go here</p>
                        <p> charts and plots go here</p>
                    </div>
                </div>
            </div>
            <div id="detail" class="screenParts">
                <div class="infoSubPanel">
                    <div style="display: block;">
                        <p>Some info and date-time will go here...</p>
                        <p>Some info and date-time will go here...</p>
                        <p>Some info and date-time will go here...</p>
                        <p>Some info and date-time will go here...</p>
                        <p>Some info and date-time will go here....</p>
                        <p>Some info and date-time will go here...</p>
                    </div>
                </div>
                <div class="infoSubPanel">
                    <textarea class="scrollabletextbox" name="logs">
blah blah blah blah blah
blah blah blah blah blah
blah blah blah blah blah
blah blah blah blah blah
blah blah blah blah blah
blah blah blah blah blah
blah blah blah blah blah
blah blah blah blah blah
blah blah blah blah blah
blah blah blah blah blah                        
                    </textarea>
                </div>
            </div>        
        
        </div>
    </body>
</html>

3 个答案:

答案 0 :(得分:3)

事实证明我收到的错误消息不准确。问题不是标题设置。原来我需要用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;

感谢您的建议。

答案 1 :(得分: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' ]
}));

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

答案 2 :(得分:0)

你几乎就在那里。

您必须将代理视为外部服务器以及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;
  }
}