繁体   English   中英

Socket.io 和 nginx CORS 投入生产

[英]Socket.io and nginx CORS on production

我正在尝试使用 socket.io v.3.1.1 进行生产的应用程序。

它在使用 webpack devServer 用于 3000 上的客户端和 nodemon 用于 4000 上的服务器进行开发时效果很好。

但是当我把它放在生产服务器上时,客户抱怨:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5003/socket.io/?EIO=4&transport=polling&t=NUmy2Us.

服务器

import express from 'express'
import { createServer } from 'http'
import { Server } from 'socket.io'

const app = express()
const prod = process.env.NODE_ENV === 'production'
const port = process.env.PORT || prod ? 5003 : 4000
const httpServer = createServer(app)

const io = new Server(httpServer, {
  cors: {
    origin: '*',
    methods: ['GET', 'POST']
  }
})

const connections = []

io.on('connection', (socket) => {
  connections.push(socket)
  console.log(`Socket id ${socket.id} connected`)

  socket.on('disconnect', () => {
    connections.splice(connections.indexOf(socket), 1)
  })
})

httpServer.listen(port, () => console.log(`App listening on port ${port}.`))
....

客户

...
import { io } from 'socket.io-client'

const port = process.env.NODE_ENV === 'development' ? '4000' : '5003'
const socket = io(`http://localhost:${port}`)

此设置确实适用于开发,但是当我将其在端口 5003 上投入生产时,它会抛出 CORS。

在我得到的 nginx 服务器块上

location /thisapp/ {
  auth_basic $authentication;
  auth_basic_user_file /var/www/.htpasswd;
  try_files $uri $uri/ =404;
}

# And other proxies for express routing
location /api/process {
  proxy_pass http://localhost:5003/api/process;
}

location /api/process/download {
  proxy_pass http://localhost:5003/api/process/download;
}

我知道该应用程序正在服务器上监听 5003。

pm2日志应用

App listening on port 5003.

当我查看 web sockets 选项卡上的网络时

在开发我得到这个:

在此处输入图像描述

在生产上:

在此处输入图像描述

生产服务器在 https 上运行,让我们加密,但这对于我运行的其他应用程序来说从来都不是问题,我想知道 socket.io 是否需要我做点什么。

我尝试了不同方法的多种组合,但我总是得到这个:

在此处输入图像描述

我上周刚刚遇到这个问题——虽然不是 Socket.io——所以希望我能提供帮助。


在回答之前,有一个链接指向您阅读正在发生的事情: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#how_to_allow_cross-origin_access


如果您的 NGINX 有权使用more_set_headers然后尝试将其添加到您的位置块中:

  more_set_headers 'Access-Control-Allow-Origin: *';

如果可行,您接下来可以尝试将其进一步缩减为:

  more_set_headers 'Access-Control-Allow-Origin: http://localhost:5003';

如果您无权访问more_set_headers ,则可以改用add_headers ,但它的名称令人困惑。 它不仅添加标题; 它还将删除层次结构更上层的块应用的任何标头,例如在您的服务器块中。 more_set_headers不会删除这些标题,并且是真正的加法。

语法有点不同。 如果您被迫使用add_headers尝试:

  add_header Access-Control-Allow-Origin *;

或更严格:

  add_header Access-Control-Allow-Origin http://localhost:5003;

最后,如果您需要支持多个来源,您可以这样做让 NGINX 自动返回与发出请求的来源兼容的 header。

在您的服务器块之外:

  map $http_origin $allow_origin {
      ~^(http://localhost:5003|http://example.com)$ $http_origin;
  }

在您的位置块内:

add_header Access-Control-Allow-Origin $allow_origin;

我不是 100% 确定使用mapmore_set_headers的语法,但这应该可以帮助您完成 95% 的工作。

最后经过很多来回,结果与标题没有任何关系。

我认为我的问题是双重的。

在 Dev 上,我在端口 3000 上使用 webpack devServer 作为前端,在 4000 上使用 nodemon 作为后端,所以我没有使用 Nginx 或 Pm2,它工作得很好。

因此,在生产中,我没有 socket.io 的任何块,而Pm2 以集群模式运行,有两个实例,当我将它更改为 Pm2 上的单个实例并添加 Z3D7A7766E813CDEB1C1BAE9 的 Nginx 位置块时,它开始工作:81FF9

服务器

import express from 'express'
import { createServer } from 'http'
import { Server } from 'socket.io'

const app = express()
const prod = process.env.NODE_ENV === 'production'
const port = process.env.PORT || prod ? 5003 : 4000
const httpServer = createServer(app)

const io = new Server(httpServer)
// Or to make it also work on Dev 
const io = new Server(httpSever, { cors: true })

const connections = []

io.on('connection', (socket) => {
  connections.push(socket)
  console.log(`Socket id ${socket.id} connected`)

  socket.on('disconnect', () => {
    connections.splice(connections.indexOf(socket), 1)
  })
})

httpServer.listen(port, () => console.log(`App listening on port ${port}.`))

Nginx

location /socket.io/ {
  proxy_pass http://localhost:5003/socket.io/;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_set_header Host $host;
}

客户

import { io } from 'socket.io-client'
const socket = io()

// Or to make it also work on Dev 
const dev = process.env.NODE_ENV === 'development'
const socket = dev ? io('http:localhost:4000') ? io()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM