Skip to content

KeyError: 'upgrade' #63

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Darth-Carrotpie opened this issue Aug 24, 2018 · 7 comments
Open

KeyError: 'upgrade' #63

Darth-Carrotpie opened this issue Aug 24, 2018 · 7 comments

Comments

@Darth-Carrotpie
Copy link

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'

@kristofen
Copy link

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..

@Darth-Carrotpie
Copy link
Author

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.

@Jawmo
Copy link

Jawmo commented Mar 24, 2019

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.

@AsgJeold
Copy link

Same problem here. :(
Has anybody found a solution, yet?

@netsesame
Copy link

    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协议")

修改库文件代码

@netsesame
Copy link

    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
                

@emileindik
Copy link

Yes, it seems to occur if the user accidentally sends an http request to the websocket host and port.
For example, make sure your client request is to ws://localhost:5000 instead of http://localhost:5000

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants