crossbario / crossbar

Crossbar.io - WAMP application router
https://crossbar.io/
Other
2.05k stars 274 forks source link

Crossbar should have a HTTP/WAMP bridge #58

Closed oberstet closed 9 years ago

oberstet commented 10 years ago

Would be nice to have a Web resource pluggable into Crossbar Web transports that can digest WAMP events via plain HTTP and forward those.

That transport should be able to forward WAMP calls and events in both directions.

oberstet commented 10 years ago

Is there a simple example of a HTTP/WAMP bridge somewhere? I'm trying

Unfortunately not.

What might help getting a better first impression of what's needed for WAMP is looking at the following classes.

The following are for Caller <-> Router communication for issuing RPCs:

https://github.com/tavendo/WAMP/blob/master/spec/basic.md#calling-and-invocations

Instances of the former classes are created and then serialized via the following (JSON variant):

And the serialized bytes then travel the wire.

None of those classes depend on Twisted or asyncio. So I think they should be reusable for a bridge running inside CherryPy.

This reuse would safe a lot of work.

Now, the bytes that come out the serializer need to travel the wire "somehow".

CherryPy is able to receive HTTP GETs or POSTs from Crossbar, and is able to issue outgoing HTTP GETs or POSTs to Crossbar.

We could just let the serialized bytes travel as payload of HTTP/POSTs in both directions. (1)

This is different from WAMP-HTTP/Longpoll (see below): here, the browser can issue HTTP request of course, but it can't receive.

With (1), if we standardize on HTTP/POSTs in both directions with POST body being a serialized byte string, the remainin question is: which HTTP URLs?

Since WAMP messages (as serialized above) don't contain the WAMP session ID itself (since this is implied with WebSocket being a persistent connection, which HTTP isn't), we can't simply use 1 URL per direction.

Means: the WAMP session ID needs to be either part of the URL, or additionally added to the POST body. The former seems simpler, since it doesn't require any change to serialization.

Hence:

could be the receiving endpoint on Crossbar that will accept HTTP/POSTs with WAMP messages for WAMP session 62342 and

could be the receiving endpoint on CherryPy for accepting HTTP/POSTs with WAMP messages for WAMP session 62342 in the other direction.

Doing a WAMP Call from CherryPy would look like

a) CherryPy => HTTP/POST to http://crossbar.example.com/session/62342 b) CherryPy <= result sent by Crossbar for request

And a) contains message.Call serialized, and b) contains message.Result serialized

Receiving a WAMP Event from Crossbar would look like

a) Crossbar => HTTP/POST to http://cherrypy.example.com/session/62342 b) Crossbar <= "ok" sent by CherryPy

Establishing a new WAMP session would need some bootstrapping to dynamically establish the session specific URLs. This would be similar to the long-poll thing below.

I'm pretty sure the Crossbar side of this can work and isn't much work. I have very very little CherryPy knowledge, e.g. each HTTP/POST coming in from Crossbar for a given (session specific) URL: are those handled on the same thread, or each could land on different threads? Not sure what the implications are ..

PS:

There is a "HTTP Long-poll" transport for WAMP for browsers that don't support WebSocket.

https://github.com/tavendo/AutobahnPython/blob/master/autobahn/autobahn/wamp/http.py

works with

https://github.com/tavendo/AutobahnJS/blob/master/package/lib/longpoll.js

This isn't done 100%, not yet released, but I had it working in principle.

Also: it's not a lot code, but it will probably quite hard to follow, since it hooks into all that layered machinery within Autobahn.

And: doing long-poll HTTP request from CherryPy will block a thread.

oberstet commented 9 years ago

implemented now