aws ec2 nginx 反向代理到 nodejs 允许 cors 不工作

问题描述 投票:0回答:1

我尝试了几个例子:

/etc/nginx/conf.d/default.conf

server {
    listen  80;
    server_name ec2ip;

    set $cors_origin "";
    set $cors_cred   "";
    set $cors_header "";
    set $cors_method "";
 
    if ($http_origin ~ '^https?://(localhost|mywebsite\.co\.uk)$') {
      set $cors_origin $http_origin;
      set $cors_cred   true;
      set $cors_header $http_access_control_request_headers;
      set $cors_method $http_access_control_request_method;
    }

    add_header Access-Control-Allow-Origin      $cors_origin;
    add_header Access-Control-Allow-Credentials $cors_cred;
    add_header Access-Control-Allow-Headers     $cors_header;
    add_header Access-Control-Allow-Methods     $cors_method;

    location / {

        # Add proxy headers for cors
        proxy_set_header Access-Control-Allow-Origin      $cors_origin;   
        proxy_set_header Access-Control-Allow-Credentials $cors_cred;     
        proxy_set_header Access-Control-Allow-Headers     $cors_header;   
        proxy_set_header Access-Control-Allow-Methods     $cors_method;
    
        proxy_pass http://localhost:8081; # my nodejs application
        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;
    }
}

我可以查看家乡路线 - 即 / 因为它只渲染 html 尽管有上述情况,我无法发布到 /api/users/register 因为我收到 cors 错误。

我的nodejs应用程序使用fastify:

节点服务器.ts

const server = Fastify();

const indexHtml = fs
  .readFileSync(path.join(__dirname, "/index.html"))
  .toString();

server.get("/", async (request, reply) => {
  console.log('indexHtml', indexHtml);
  reply.type("text/html").send(indexHtml); // <body>Hello from nodejs</body>
});

server.post("/api/users/register", opts, (req, reply) => {
  reply.header("Access-Control-Allow-Origin", "*");
  reply.header("Access-Control-Allow-Methods", "POST");
  reply.header("Access-Control-Allow-Headers",  "*");
  reply.code(201);
  reply.send({ message: "Success" });
});

server.listen({ port: 8081 }, (err, address) => {
 // stuff...
});

访问网址 http://ec2ip/

来自nodejs的你好

来自我的应用程序的 API 请求,网址为 http://localhost

axios({
  method: 'POST',
  url: 'http://ec2ip/api/users/register',
  data: {},
  headers: {
        'Access-Control-Allow-Origin': '*',
        'Content-Type': 'application/json',
        'Access-Control-Allow-Methods':'POST,OPTIONS',
  },
  withCredentials: true
});

> Error: 
register    CORS error  xhr apiRegister.ts:5    0 B 28 ms   register    204 preflight   

node.js nginx amazon-ec2 cors
1个回答
0
投票

好的,我修好了。

  1. 从 Nodejs 中删除所有允许标头。不需要。仅在 nginx 中设置。
  2. 删除 nginx proxy_set_header。不需要。
  3. 如果我使用 withCredentials: true。那么我就无法在nginx中设置通配符*了。 我必须为允许cors设置特定的IP地址。我还必须添加凭据。
add_header 'Access-Control-Allow-Credentials' $cors_cred;
  1. if 语句不起作用。我也找不到一种方法将它们记录在我的访问日志中来测试它们,所以用地图解决方案解决了。

  2. 发出 api 请求时包含 withCredentials: true

最终 nginx 配置

# Instead of if statements, declare my variables at the top (within http object)
# This way I can log them later to test they worked.

map $http_origin $cors_origin {
   ~^https?://localhost$      $http_origin;
   ~^https?://(www)?mysite\.co\.uk$ $http_origin;
   default "";
}
map "$cors_origin" $cors_cred {
   ~^$ false;
   default true;
}

# echo into log to test variables
log_format upstream_time "$time_local http_origin=$http_origin remote_addr=$remote_addr allow_origin=$cors_origin cred=$cors_cred";
 
server {
    listen  80;
    server_name my-EC2-PUBLIC-ip;

    location / {


   # Trigger the log into the access_log:
   # tail -f /var/log/nginx/access.log

   access_log /var/log/nginx/access.log upstream_time;
   if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' $cors_origin;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Credentials' $cors_cred;
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
     
        # Tell client that this pre-flight info is valid for 20 days
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain; charset=utf-8';
        add_header 'Content-Length' 0;
        return 204;
     }
     if ($request_method = 'POST') {
        add_header 'Access-Control-Allow-Credentials' $cors_cred always;
        add_header 'Access-Control-Allow-Origin' $cors_origin always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;   
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
     }


        proxy_pass http://localhost:8081;
        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;
    }
}
  1. 一定要重启节点服务器
  2. 一定要重启nginx
  3. 重新发布测试
  4. 有效
© www.soinside.com 2019 - 2024. All rights reserved.