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
相关产品推荐
相关产品推荐

