Search code examples
pythonautobahnpython-asyncio

Accessing RPC caller's IP and HTTP connect headers inside ApplicationSession's registered endpoint


I'm using Autobahn 0.9.2 with Python 3.4 with asyncio.

Questions: Using WAMP, is it possible to access the peer acting as a Caller's IP and HTTP connection header from inside an RPC endpoint? Is this information persisted when a connection is established? If not, how would I get started extending some factories to support this?

My objective is rather simple: I want to have an RPC endpoint to Geolocalize the IP of the connected peer (the Caller) and relay the augmented data to Redis. I have read the source and know where the information passes through (autobahn.websocket.protocol.WebSocketServerProtocol -> onConnect(request)) but am having trouble drilling down to it from the ApplicationSession's RPC endpoint defined in the onJoin callback. I tried traversing the transport/router/router session chain and didn't manage to get there. I'm interested in both the Peer's IP and the HTTP headers from the initial connection request.

Here's the distilled Component:

class IncomingComponent(ApplicationSession):

def __init__(self, **params):
    super().__init__()
    self.redis = StrictRedis(host=config["redis"]["host"], port=config["redis"]["port"], db=config["redis"]["databases"]["ailytics"])

def onConnect(self):
    self.join("abc")

@asyncio.coroutine
def onJoin(self, details):

    def geolocalize_and_store_event(event, detail):
        # Geolocalize here! Have access to caller ID through detail
        self.redis.rpush("abc:events", json.dumps(event))

    yield from self.register(
        geolocalize_and_store_event,
        "abc.geolocalize_and_store_event",
        options=RegisterOptions(details_arg='detail', discloseCaller = True)
    )

And the initialization of the server:

    router_factory = wamp.RouterFactory()

    session_factory = wamp.RouterSessionFactory(router_factory)
    session_factory.add(IncomingComponent())

    transport_factory = websocket.WampWebSocketServerFactory(session_factory, debug=False, debug_wamp=False)

    loop = asyncio.get_event_loop()
    coro = loop.create_server(transport_factory, '0.0.0.0', 7788)
    server = loop.run_until_complete(coro)

    try:
        loop.run_forever()
    except KeyboardInterrupt:
        pass
    finally:
        server.close()
        loop.close()

Solution

  • You can access extra session/transport information via the wamp.session.get meta-API in crossbar.io at least:

    @inlineCallbacks
    def onJoin(self, ign):
    
        @inlineCallbacks
        def method(details):
            session = yield self.call('wamp.session.get', details.caller)
            peer = session['transport']['peer']
            print "peer's address", peer
    
            headers = session['transport']['http_headers_received']
            print "headers:"
            print '\n'.join(['{}: {}'.format(k, v) for (k, v) in headers.items()])
    
        yield self.register(
            method, 'some_method',
            types.RegisterOptions(details_arg='details'),
        )