Connect me!

Connect me!

Ok, so in this instance the blog is just a dumping ground for a working example. There are a couple of different ways to connect up an Autobahn/WAMP client to a Crossbar router, but beyond that many different pattern variations depending on whether you prefer composition or inheritance. This is an example of using the new "Component" mechanism using my currently preferred pattern - please note that is not the "right" way to do this, but neither is it the "wrong" way.

There is a lot to be said for having the code in one place and being able to understand what it does and how it works ...

#!/usr/bin/env python3

from autobahn.twisted.component import run
from autobahn.wamp.types import RegisterOptions
from autobahn.twisted.component import Component
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks


class WAMPClient:

    def __init__(self, url, realm):
        self._url = url
        self._realm = realm
        self._session = None

    def run(self):
        self._connection = Component(
            transports=[{'url': self._url, 'type': 'websocket'}],
            realm=self._realm
        )
        self._connection.on('join', self.on_join)
        self._connection.on('leave', self.on_leave)
        run([self._connection])

    def on_join(self, session, details=None):
        self._session = session
        options = RegisterOptions(details_arg='details')
        session.register(self.my_endpoint, 'my.endpoint', options)
        reactor.callLater(2, self.test_client)

    def on_leave(self, session, details=None):
        pass

    def my_endpoint(self, arg, details=None):
        print(f'Incoming connection from ({details.caller}) with ({arg})')
        return details.caller_authid

    @inlineCallbacks
    def test_client(self):
        result = yield self._session.call('my.endpoint', 'my arg')
        print(f'Endpoint returned: {result}')

if __name__ == '__main__':

    WAMPClient('ws://localhost:8085/ws', 'realm1').run()

So first thing to do, save this as "example.py" and "chmod a+x". Next you'll need a crossbar instance, so install Crossbar via your preferred method, then "crossbar init" - be aware that this will create a ".crossbar" folder which will contain a number of items including "config.json".

Now edit the ".crossbar/config.json", you will need to change two things. Firstly tweak the port to read "8085" instead of "8080", then set "disclose/caller" and "disclose/publisher" to "true". Now you can run up crossbar with "crossbar start".

Hopefully now you can run the example (provided you have autobahn and twisted installed in your environment) with "./example.py" and you should see something like this;

connecting once using transport type "websocket" over endpoint "tcp"
Starting factory <autobahn.twisted.websocket.WampWebSocketClientFactory>
Incoming connection from (444686288565282) with (my arg)
Endpoint returned: M966-59J4-4TAX-JRET-FWNH-5MSW

Notably it's showing how the test client is passing an argument to the RPC endpoint, and how the endpoint is returning a value to the client, and how the endpoint is identifying the caller by session ID, and by authid. In this instance because the connection is anonymous the server generates a random authid for us.

So, just to clarify, this example acts as both server and client. It acts as a server within the context of registering an endpoint and serving an endpoint (i.e. my_endpoint) and a client within the context of "test_client", which then calls that endpoint.