You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Socket.IO服务器HTTPS连接报错400:Bad request version问题求助

Socket.IO切换HTTPS后无法连接,报错400 Bad request version

问题描述

我使用Python的socketio和eventlet搭建Socket.IO服务器,客户端采用socketio库实现。HTTP协议下客户端可正常连接服务器,功能运行符合预期,但切换为HTTPS协议时无法建立连接,报错信息为code 400, message Bad request version。服务器部署在AWS EC2实例中。

服务器代码(server.py)

import socketio
import eventlet
from threading import Thread
import redis
import time

sio = socketio.Server()
app = socketio.WSGIApp(sio)

redis_conn = None


def initialize_redis_conn():
    global redis_conn
    if redis_conn is None:
        redis_conn = redis.StrictRedis(host='localhost', port=6379, decode_responses=True)
        print("redis connection init")


def insert_update_sid(sid, unique_id):
    """
    Inserts or updates the sid and uniqueId of the client into the Redis cache.
    """
    initialize_redis_conn()
    key = f"DATA_KEY_{unique_id}"
    expiry_in_seconds = 1800
    redis_conn.setex(key, expiry_in_seconds, sid)
    print("Data inserted into Redis successfully")


def get_sid_by_unique_id(unique_id):
    """
    Returns the sessionId (sid) of a client using the uniqueId.
    """
    initialize_redis_conn()
    print("fetching sid")
    key = f"DATA_KEY_{unique_id}"
    sid = redis_conn.get(key)
    if sid:
        print(f"Got sid {sid} using uid {unique_id}")
        return sid
    else:
        return None


def run_sqs():
    data = {
        "communicationStatus": "OKAY",
        "status": "Complete"
    }
    unique_id = "123789"
    if unique_id:
        print("inside sqs impl is : ", unique_id)
        sid = get_sid_by_unique_id(unique_id=unique_id)
        if sid:
            print("calling send response to client")
            send_response_to_client(sid, data)
            print(
                f"Response has been sent to the client with sessionId: {sid} and uniqueId : {unique_id}")
        else:
            print(f"Client not found for the given uniqueId: {unique_id}")


def send_response_to_client(sid, resp):
    """
    this func sends the response to the client
    """

    sio.emit('response_from_server', f'response : {resp}')
    print("data sent to client ")


@sio.event
def connect(sid, environ):

    print(f"client {sid} connected")
    print("sid type is: ", type(sid))
    token = environ.get('HTTP_TOKEN')
    sio.emit("acknowledge", "ack recevied from server", room=sid)
    if token:
        auth_status_code = 200
        if auth_status_code == 200:
            unique_id = "123789"
            # insert the sid and uniqueId into redis cache 
            insert_update_sid(sid, unique_id)


@sio.event
def disconnect(sid):
    """
    this is a disconnect event which disconnects the client from server
    """
    print(f"client {sid} disconnected")

def start_server():
   eventlet.spawn(run_sqs)
   eventlet.spawn(eventlet.wsgi.server(eventlet.listen(('0.0.0.0', 5000)), app))


if __name__ == '__main__':
    start_server()

客户端代码(client.py)

import requests
import socketio

PORT = "5000"

IP = "localhost"

sio = socketio.Client()


@sio.event
def connect():
    print("connection established to server connect event")


@sio.event
def disconnect():
    print("client disconnected from server")


@sio.event
def server_response(response):
    print("response from server recived")
    print(f"response received from server: {response}")


@sio.event
def acknowledge(ack):
    print(ack)


if __name__ == '__main__':
    data = {}
    stage = "dev"
    token = get_token(stage)
    token = "Radom_token"
    if token:
        print("Token has been generated.")

        url = f"http://{IP}:{PORT}"

        sio.connect(url, transports=['websocket', 'polling'], headers={'token': token})
        sio.wait()

    else:
        print("Token has not been generated ")

报错信息

code 400, message Bad request version ('À\x13À')
"\x16\x03\x01\x01\x4\x01\x00\x01\x00\x03\x03n}\x99ºSíÕêwí\x0bà¶\x1a>ìx±¦\x18g\x09¡TÏ\x16Hª¦oŤ Z^Ðæw\x1a\x8fЫä³\x8f¬}Dr!]{\x09\x8d¼\x8cã\x90IUȳ\x84Fª\00.\x13\x01\x13\x02\x13\x03\x13\x04\x13\x05À+À/À,À0̨̩À\x09À\x13À" 400 -

解决方案

这个错误的核心原因是当前服务器仅配置了HTTP支持,没有启用HTTPS。当客户端用HTTPS连接时,发送的是TLS加密流量,服务器无法识别为合法的HTTP请求,因此返回400错误。

1. 配置服务器HTTPS支持

修改服务器的start_server函数,使用eventlet.wrap_ssl为监听套接字添加SSL层:

def start_server():
    eventlet.spawn(run_sqs)
    # 创建基础监听套接字
    sock = eventlet.listen(('0.0.0.0', 5000))
    # 用SSL证书包装套接字(替换为你的证书路径)
    ssl_sock = eventlet.wrap_ssl(
        sock,
        certfile='path/to/your/cert.pem',
        keyfile='path/to/your/key.pem',
        server_side=True
    )
    # 启动HTTPS服务器
    eventlet.spawn(eventlet.wsgi.server(ssl_sock, app))

2. 更新客户端连接地址

将客户端的连接URL从HTTP改为HTTPS:

url = f"https://{IP}:{PORT}"

3. 额外注意事项

  • 证书获取:生产环境建议使用Let's Encrypt等正规CA签发的证书;测试环境可使用自签名证书(生成命令:openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes)。
  • 自签名证书的客户端处理:如果使用自签名证书,客户端需要禁用SSL验证(仅测试环境使用):
    sio.connect(url, transports=['websocket', 'polling'], headers={'token': token}, ssl_verify=False)
    
  • AWS安全组配置:确保EC2实例的安全组开放了5000端口的HTTPS入站流量。

内容的提问来源于stack exchange,提问作者user22982329

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 03:02:02