如何在Python Websocket客户端中添加更多的标头

12

我试图通过websocket连接(使用Python websocket客户端)发送会话ID(在与HTTP服务器进行身份验证后获得)。我需要将它作为一个参数传递,其中服务器将读取所有的头并对其进行检查。

问题是:如何在现有的Python Websocket客户端实现中添加头信息?我发现它们都不能做到这一点,或者我在第一步中遵循了错误的方法来进行身份验证吗?

-- 更新 --,以下是我使用的代码模板:

def on_message(ws, message):
    print 'message received ..'
    print message


def on_error(ws, error):
    print 'error happened .. '
    print error


def on_close(ws):
    print "### closed ###"


def on_open(ws):
   
    print 'Opening Websocket connection to the server ... '
    
    ## This session_key I got, need to be passed over websocket header isntad of ws.send.
    ws.send(session_key)

if __name__ == "__main__":
    websocket.enableTrace(True)
    ws = websocket.WebSocketApp("ws://localhost:9999/track",
                                on_open = on_open,
                                on_message = on_message,
                                on_error = on_error,
                                on_close = on_close, 
                                )
    ws.on_open = on_open

    ws.run_forever()

你能在你的问题中添加一些代码吗?如果你能添加一个SSCCE http://sscce.org/,那就更好了。 - Anupam Saini
2个回答

14

看起来自问提出这个问题以后,websocket-client已经更新了以包括websocket头文件。现在你可以简单地将一个字符串列表作为头部参数传递:

custom_protocol = "your_protocol_here"
protocol_str = "Sec-WebSocket-Protocol: " + custom_protocol
ws = websocket.WebSocketApp("ws://localhost:9999/track",
                            on_open = on_open,
                            on_message = on_message,
                            on_error = on_error,
                            on_close = on_close, 
                            header = [protocol_str]
                            )
如果你对有效头部的完整列表感兴趣,请参阅WebSocket RFC6455文档:https://www.rfc-editor.org/rfc/rfc6455#section-4.3。 GitHub源代码:https://github.com/liris/websocket-client/blob/master/websocket.py

这个没有起作用,所以我添加了源代码修改...除非你自己测试过它并且它对你起作用。 - securecurve
是的,我已经成功测试过了。我查看了自从你在一月份回答后对源代码所做的更改,自那时起他们已经修复了不存在的头参数,所以我想留下一个备选答案供未来的观众参考。请参见源代码的773行:https://github.com/liris/websocket-client/blob/master/websocket.py#L773 - IanTheEngineer
4
似乎该函数还接受一个字典作为参数而非格式化字符串列表,因此您可以使用header={'Sec-WebSocket-Protocol': custom_protocol}。这样可能会使编码更简单。 - Huw Walters
@securecurve 虽然你的猴子补丁答案很有启发性(感谢分享),但现在这个答案是正确的接受答案。 - Robino

9

读源代码是最有趣的事情 :))

我对Websocket客户端库的源代码进行了猴子补丁,使其能够像这样将标头作为普通参数在初始化器中接收:

ws = websocket.WebSocketApp("ws://localhost:9999/track",
                                on_open    = on_open,
                                on_message = on_message,
                                on_error   = on_error,
                                on_close   = on_close, 
                                header     = {'head1:value1','head2:value2'} 
                                )

这可以通过编辑库中websocket.py源代码的3行来完成:
1- 添加头参数:
   ## Line 877
   class WebSocketApp(object):
        """
        Higher level of APIs are provided.
        The interface is like JavaScript WebSocket object.
        """
        def __init__(self, url,
                     on_open = None, on_message = None, on_error = None,
                     on_close = None, keep_running = True, get_mask_key = None, header = None):

self.url = url
        self.on_open = on_open
        self.on_message = on_message
        self.on_error = on_error
        self.on_close = on_close
        self.keep_running = keep_running
        self.get_mask_key = get_mask_key
        self.sock = None
        self.header = header 

2- 然后将self.header作为头部参数传递给websocket连接方法,如下所示:

## Line 732
self.sock.connect(self.url, header = self.header) 

实际上,我尝试导入WebSocketApp类,但是它没有起作用,因为整个websocket.py模块是相互依赖的,我发现自己需要导入很多东西才能让它工作,针对这种情况,在这里进行猴子补丁更容易、更稳定。
就这样,享受使用已打补丁的库及其所需的所有标头吧。

我和你一样也在面对类似的问题。能问一下你是如何处理这种情况的吗:当你将会话 ID(从 HTTP 服务器)传递到 WebSocket 服务器时,我想你会在服务器端检查此会话 ID 是否有效。你是如何存储此会话 ID 的?是在数据库中吗?而且我的假设是 HTTP 服务器和 WebSocket 服务器都需要使用相同的 ID 会话池,这个假设正确吗? - maciekm
WebSocketApp构造函数的header参数默认值令人困惑;header=[]。实际上,它不应该是一个列表,而应该是一个字典。 - Marcin Kowalczyk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接