[英]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% 确定使用map
和more_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.