首页 > 解决方案 > Flask-socketio 的 https、http、wss 问题无法在 Heroku 中连接

问题描述

我有一个几个月前可以工作的烧瓶套接字 io 应用程序,但我不确定发生了什么。我已将其简化为基础知识。输出日志显示了一堆乱码,我认为这应该是 TLS 握手的开始(来自我所做的研究)。控制台显示与 CORS 相关的错误。我不知道为什么会这样-本地主机的起源不应该相同吗?服务器是否发送安全请求?

我已经尝试过这个socketio = SocketIO(app, cors_allowed_origins='*')问题 中提到的,但问题仍然存在。这是日志输出,过去它会显示轮询 url: 记录服务器的输出。

仍在接收事件

我的 application.py 代码:

from flask import Flask, render_template
from flask_socketio import SocketIO, emit

app = Flask(__name__)
app.config["SECRET_KEY"] = 'secret?'
socketio = SocketIO(app, engineio_logger=True, logger=True)

@app.route("/", methods=["GET"])
def index():
    return render_template("layout.html")

@socketio.on('message')
def handleMessage(msg):
    print(msg)
    emit(msg, broadcast=True)

if __name__ == '__main__':
    socketio.run(app)

Javascript:

document.addEventListener('DOMContentLoaded', () => {
    connectSocketIO();
    addMessage();
});

var socket;
function connectSocketIO () {
    socket = io.connect('http://' + document.domain + ':' + location.port);
    socket.on('connect', () => {
        console.log('client connected');
        socket.on('disconnect', () => console.log('client disconnected'));
    });

    socket.on('message', (data) => {
        console.log(data);
    });
}
function addMessage () {
    // emit a new message announcement when message is posted
    document.querySelector('#btn').onclick = () => {
        const message = document.querySelector('input').value;
        socket.emit('message', {'message': message});
        return false;
    };
}

要求.txt

Flask
Flask-SocketIO
gunicorn
eventlet==0.24.1

编辑:

最初的问题似乎是由在 io.connect 中指定 https 协议引起的 - 更改已解决了乱码输出。
这导致 Firefox 抛出错误:
Firefox can't establish a connection to the server as wss://url

在 Chrome 中它可以工作,但连接更改为 http。两者都警告cookies滥用sameSite属性
Cookie "io" will be soon rejected because it has the "sameSite" attribute set to "none" or an invalid value, without the "secure" attribute.

Heroku Procfile:
web: gunicorn --worker-class eventlet -w 1 application:app

在服务器端,Heroku 的日志:

2020-07-28T12:41:43.350016+00:00 app[web.1]: https://flack-messaging-app.herokuapp.com is not an accepted origin.

2020-07-28T12:41:43.346991+00:00 heroku[router]: at=info method=POST path="/socket.io/?EIO=3&transport=polling&t=NELSMDM&sid=f25e5af236d347eaa3100951014be579" host=flack-messaging-app.herokuapp.com request_id=1041f8b4-71b8-4cf5-a321-75014d2ccde7 fwd="78.146.97.151" dyno=web.1 connect=1ms service=8ms status=400 bytes=182 protocol=https

2020-07-28T12:41:44.399195+00:00 heroku[router]: at=info method=POST path="/socket.io/?EIO=3&transport=polling&t=NELSMTk&sid=f25e5af236d347eaa3100951014be579" host=flack-messaging-app.herokuapp.com request_id=dba0c5f4-6afd-4621-ad7e-4c511911a714 fwd="78.146.97.151" dyno=web.1 connect=2ms service=3ms status=400 bytes=182 protocol=https

2020-07-28T12:41:44.402016+00:00 app[web.1]: https://flack-messaging-app.herokuapp.com is not an accepted origin.

2020-07-28T12:41:45.481764+00:00 heroku[router]: at=info method=GET path="/socket.io/?EIO=3&transport=polling&t=NELSMkn" host=flack-messaging-app.herokuapp.com request_id=8ba7cc91-5e33-4113-a15d-84e5ceba8ca4 fwd="78.146.97.151" dyno=web.1 connect=1ms service=3ms status=200 bytes=385 protocol=https

2020-07-28T12:41:45.483979+00:00 app[web.1]: 5b1138c7e62a4ea2bff2beb55eb5241d: Sending packet OPEN data {'sid': '5b1138c7e62a4ea2bff2beb55eb5241d', 'upgrades': ['websocket'], 'pingTimeout': 60000, 'pingInterval': 25000}

2020-07-28T12:41:45.484100+00:00 app[web.1]: 5b1138c7e62a4ea2bff2beb55eb5241d: Sending packet MESSAGE data 0

2020-07-28T12:41:45.571836+00:00 app[web.1]: https://flack-messaging-app.herokuapp.com is not an accepted origin.

2020-07-28T12:41:45.566552+00:00 heroku[router]: at=info method=GET path="/socket.io/?EIO=3&transport=websocket&sid=5b1138c7e62a4ea2bff2beb55eb5241d" host=flack-messaging-app.herokuapp.com request_id=d802cd1c-c875-4406-a75e-2c3ca2368de0 fwd="78.146.97.151" dyno=web.1 connect=0ms service=2ms status=400 bytes=187 protocol=https

2020-07-28T12:41:48.383640+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/socket.io/?EIO=3&transport=polling&t=NELSG6k&sid=f25e5af236d347eaa3100951014be579" host=flack-messaging-app.herokuapp.com request_id=26757146-e11f-43d6-a243-65172f72dd5e fwd="78.146.97.151" dyno=web.1 connect=1ms service=30001ms status=503 bytes=0 protocol=https

标签: herokusocket.iocs50flask-socketio

解决方案


好的,看起来有两个问题:

  1. 在客户端的 io.connect 中,使用了 connect 参数,
    https:// + document.domain + location.port但服务器使用的是 http://,因此导致输出乱码。更改https://window.location.protocol + '//' + 'rest_of_url'修复乱码输出。

  2. Heroku 使用 https:// 但我的服务器配置为 http:// - 我仍然不确定要在 Flask 中更改哪些设置以使用另一个设置,但在我的 application.py 中,对于 Socket 构造函数,添加了cors_allowed_origins='https://myurl'固定wss 无法连接的问题。从那以后,我习惯于
    cors_allowed_origins=['http://url', 'https://url']允许安全和非安全访问。我对 Heroku 或 Flask 不够熟悉,无法强行将一个放在另一个之上,这个解决方案对我来说效果很好。


推荐阅读