KeyError: 'upgrade'
Darth-Carrotpie opened this issue · comments
Sometimes getting a weird error. Not sure on what action exactly...
2018-08-24 10:13:03,075 DEBUG webserver client left: None
Exception happened during processing of request from ('122.228.10.51', 26823)
Traceback (most recent call last):
File "/usr/lib64/python3.6/socketserver.py", line 639, in process_request_thread
self.finish_request(request, client_address)
File "/usr/lib64/python3.6/socketserver.py", line 361, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/home/ec2-user/libraries/websocket_server.py", line 166, in init
StreamRequestHandler.init(self, socket, addr, server)
File "/usr/lib64/python3.6/socketserver.py", line 696, in init
self.handle()
File "/home/ec2-user/libraries/websocket_server.py", line 177, in handle
self.handshake()
File "/home/ec2-user/libraries/websocket_server.py", line 319, in handshake
assert headers['upgrade'].lower() == 'websocket'
KeyError: 'upgrade'
I have the same issue. I'm currently trying to interconnect a python process (implementing python-websocket-server) and a nodejs server (on the same machine) with socket.io client.
This error disappeared by changing the options passed to the socket.io client instanciation like so
var ioClient = require('socket.io-client');
var myClient = ioClient('http://127.0.0.1:1234', {
"upgrade": true,
"transports": ['websocket']
});
it's still do not work because the connection is closed right away..
Well, I think I figured out what's causing the errors for me.
Since my server is being hosted in Amazon AWS, there could be all kinds of crawlers checking for services and such. I think the server loses its mind, when there's a http message, which looks similar to:
b'\x03\x00\x00/*\xe0\x00\x00\x00\x00\x00Cookie: mstshash=Administr\r\n'
Whenever these messages occur, server breaks.
I ran into this same error when I was attempting to use SSL. If I run a server without it, then everything works just fine. As soon as I add an SSL cert into the mix, I first get an error:
Traceback (most recent call last):
File "/usr/lib/python3.6/socketserver.py", line 721, in __init__
self.handle()
File "/home/damian/hopemud/websocket_server/websocket_server.py", line 199, in handle
self.handshake()
File "/home/damian/hopemud/websocket_server/websocket_server.py", line 334, in handshake
headers = self.read_http_headers()
File "/home/damian/hopemud/websocket_server/websocket_server.py", line 322, in read_http_headers
http_get = self.rfile.readline().decode().strip()
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfc in position 8: invalid start byte
Then, when I add a a proxy_pass to try to upgrade the header for the web client, I get the same error you do:
Traceback (most recent call last):
File "/usr/lib/python3.6/socketserver.py", line 721, in __init__
self.handle()
File "/home/damian/hopemud/websocket_server/websocket_server.py", line 199, in handle
self.handshake()
File "/home/damian/hopemud/websocket_server/websocket_server.py", line 337, in handshake
assert headers['upgrade'].lower() == 'websocket'
KeyError: 'upgrade'
Have not found a way around this.
Same problem here. :(
Has anybody found a solution, yet?
def handshake(self):
headers = self.read_http_headers()
print("Handshake", headers)
if 'upgrade' in headers:
try:
assert headers['upgrade'].lower() == 'websocket'
except AssertionError:
self.keep_alive = False
return
try:
key = headers['sec-websocket-key']
except KeyError:
logger.warning("Client tried to connect but was missing a key")
self.keep_alive = False
return
response = self.make_handshake_response(key)
with self._send_lock:
self.handshake_done = self.request.send(response.encode())
self.valid_client = True
self.server._new_client_(self)
else:
print("请升级到ws协议")
修改库文件代码
def read_http_headers(self):
headers = {}
# first line should be HTTP GET
http_get = self.rfile.readline().decode().strip()
if not http_get.upper().startswith('GET'):
logger.warning("Unsupported HTTP method")
response = 'HTTP/1.1 400 Bad Request\r\n\r\n'
with self._send_lock:
self.request.sendall(response.encode())
self.keep_alive = False
return headers
#assert http_get.upper().startswith('GET')
# remaining should be headers
while True:
header = self.rfile.readline().decode().strip()
if not header:
break
head, value = header.split(':', 1)
headers[head.lower().strip()] = value.strip()
return headers
def handshake(self):
headers = self.read_http_headers()
#print("Handshake", headers)
#针对
if 'upgrade' in headers:
try:
assert headers['upgrade'].lower() == 'websocket'
except AssertionError:
self.keep_alive = False
return
try:
key = headers['sec-websocket-key']
except KeyError:
logger.warning("Client tried to connect but was missing a key")
self.keep_alive = False
return
response = self.make_handshake_response(key)
with self._send_lock:
self.handshake_done = self.request.send(response.encode())
self.valid_client = True
self.server._new_client_(self)
else:
timeStr = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print(f"请升级到ws协议{timeStr}")
response = 'HTTP/1.1 400 Bad Request\r\n\r\n'
#如果客户端不支持WebSocket协议,服务器会返回一个HTTP 401 Unauthorized状态码,表示客户端没有权限访问该资源。
with self._send_lock:
self.request.sendall(response.encode())
self.keep_alive = False