2017-07-02 485 views
0

爲了讓您瞭解我正在嘗試使用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() 

回答

0

因此,在Google上稍微閱讀一下後,我發現這個網站介紹瞭如何通過Autobahn Twisted:Read and Set request headers via Autobahn Twisted將HTTP連接升級到websocket連接。

我能夠開始工作的代碼如下所示!

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 HttpResource(Resource): 
    isLeaf = True 

    def render_GET(self, 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>" 


class WebSocketProtocol(WebSocketServerProtocol): 

    def onConnect(self, request): 
     custom_header = {} 

     if request.headers['sec-websocket-key']: 
      custom_header['sec-websocket-protocol'] = 'graphql-ws' 
     return (None, custom_header) 

    def onMessage(self, payload, isBinary): 
     print("onMessage: {}".format(payload)) 


if __name__ == '__main__': 

    factory = WebSocketServerFactory() 
    factory.protocol = WebSocketProtocol 
    resource = WebSocketResource(factory) 

    root = Resource() 
    root.putChild("", HttpResource()) 
    root.putChild(b"ws", ws_resource) 

    site = Site(root) 
    reactor.listenTCP(8000, site) 
1

使用WebSocketResource,露出一個WebSocketServerFactory作爲Site的一部分。

from twisted.web.server import (
    Site, 
) 
from twisted.web.resource import (
    Resource, 
) 
from autobahn.twisted.websocket import (
    WebSocketServerProtocol, 
    WebSocketServerFactory, 
) 
from autobahn.twisted.resource import (
    WebSocketResource, 
) 

class YourAppProtocol(WebSocketServerProtocol): 
    def onConnect(self, request): 
     ... 

    ... 

def main(): 
    factory = WebSocketRendezvousFactory() 
    factory.protocol = YourAppProtocol 
    resource = WebSocketResource(factory) 
    root = Resource() 
    root.putChild(b"some-path-segment", resource) 
    root.putChild(...) 
    site = Site(root) 
    reactor.listenTCP(8080, site) 
    reactor.run() 

截斷的請求主體的問題可能是因爲您的升級協議實現有問題。在dataReceived的級別上沒有應用框架,因此您不能期望像startswith("GET")這樣的檢查是可靠的。

使用WebSocketResourceSite讓你從扭曲的Web和高速公路正確的HTTP解析代碼,同時還允許你說話的WebSocket到一個特定的URL和普通的HTTP給他人。

+0

我不認爲這段代碼展示瞭如何在與HTTP相同的端口上使用autobahn websocket。我之前已經實現了這個代碼,這不是我想要的。我相信我可能有一個使用扭曲網絡庫的工作示例 – Brian

+0

我已經使用指向正在運行的示例的鏈接更新了描述,但遇到請求被截斷的問題。仍在深入研究這個問題@ jean-paul-calderone – Brian

+0

謝謝!我試過你的例子,我能夠接收websocket消息。然而,當我執行一個GET請求時,我得到了一個404,說明沒有這樣的資源 - 找不到這樣的子資源。 – Brian

相關問題