爲了讓您瞭解我正在嘗試使用Twisted Web和Autobahn websockets完成什麼:我的UI當前發送一個初始HTTP GET請求並升級到websocket在標題中。在Twisted Web中讀取時,連接需要從HTTP切換到Websocket協議以來回傳遞數據。請注意,此websocket升級發生在同一端口上,port 8000
。如何將HTTP請求升級到Websocket(Autobahn&Twisted Web)
有誰知道我可以如何實現我想要做的?非常感謝。
編輯:工作示例的更新代碼。你可以在這裏找到它:Payload from POST Request is Cutoff (Twisted Web)
下面是使用雙絞線網絡我的代碼:
class HttpResource(resource.Resource):
isLeaf = 1
def __init__(self):
self.children = {}
self.ws_port = None
print 'resource invoked'
def render_GET(self, request):
print 'render invoked'
if request.getHeader('Sec-WebSocket-Key'):
# Processing the Key as per RFC 6455
key = request.getHeader('Sec-WebSocket-Key')
h = hashlib.sha1(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
request.setHeader('Sec-WebSocket-Accept', base64.b64encode(h.digest()))
# setting response headers
request.setHeader('Upgrade', 'websocket')
request.setHeader('Connection', 'Upgrade')
request.setResponseCode(101)
return ''
else:
log("Regular HTTP GET request.")
return "<html><body style='margin: 0; overflow: hidden;'><iframe style='width: 100%; height: 100%; border: none;' src='http://tsa-graphiql.herokuapp.com/'></iframe></body></html>"
def render_POST(self,request):
log("POST request")
request.setResponseCode(200)
def handle_single_query(self, queryData):
log("Handle single query data.")
return
class HttpWsChannel(http.HTTPChannel):
def dataReceived(self, data):
log('Data received:\n{}'.format(data))
if data.startswith('GET'):
# This will invoke the render method of resource provided
http.HTTPChannel.dataReceived(self, data)
if data.startswith('POST'):
http.HTTPChannel.dataReceived(self, data)
else:
"""
Pass binary data to websocket class.
"""
ws_protocol = self.site.ws_factory.protocol(self.site.ws_factory.connection_subscriptions)
log(ws_protocol)
#just echo for now
# self.transport.write(data)
class HttpFactory(Site):
"""
Factory which takes care of tracking which protocol
instances or request instances are responsible for which
named response channels, so incoming messages can be
routed appropriately.
"""
def __init__(self, resource):
http.HTTPFactory.__init__(self)
self.resource = resource
self.ws_factory = WsProtocolFactory("ws://127.0.0.1:8000")
self.ws_factory.protocol = WsProtocol
def buildProtocol(self, addr):
try:
channel = HttpWsChannel()
channel.requestFactory = self.requestFactory
channel.site = self
return channel
except Exception as e:
log("Could not build protocol: {}".format(e))
site = HttpFactory(HttpResource())
if __name__ == '__main__':
reactor.listenTCP(8000, site)
reactor.run()
編輯2017年7月8日:這裏是我的嘗試下面的新代碼。 websocket消息通過onMessage
方法成功接收。但是HTTP請求不起作用。當前的錯誤,我在一個GET請求得到的是:
<html>
<head><title>404 - No Such Resource</title></head>
<body>
<h1>No Such Resource</h1>
<p>No such child resource.</p>
</body>
</html>
Python代碼
from twisted.web.server import (
Site,
)
from twisted.internet import reactor
from twisted.web.resource import (
Resource,
)
from autobahn.twisted.websocket import (
WebSocketServerProtocol,
WebSocketServerFactory,
)
from autobahn.twisted.resource import (
WebSocketResource,
)
class WebSocketProtocol(WebSocketServerProtocol):
def onConnect(self, request):
print("WebSocket connection request: {}".format(request))
def onMessage(self, payload, isBinary):
print("onMessage: {}".format(payload))
if __name__ == '__main__':
factory = WebSocketServerFactory()
factory.protocol = WebSocketProtocol
resource = WebSocketResource(factory)
root = Resource()
root.putChild(b"ws", resource)
site = Site(root)
reactor.listenTCP(8000, site)
reactor.run()
我不認爲這段代碼展示瞭如何在與HTTP相同的端口上使用autobahn websocket。我之前已經實現了這個代碼,這不是我想要的。我相信我可能有一個使用扭曲網絡庫的工作示例 – Brian
我已經使用指向正在運行的示例的鏈接更新了描述,但遇到請求被截斷的問題。仍在深入研究這個問題@ jean-paul-calderone – Brian
謝謝!我試過你的例子,我能夠接收websocket消息。然而,當我執行一個GET請求時,我得到了一個404,說明沒有這樣的資源 - 找不到這樣的子資源。 – Brian