Hi, I'm trying to get browsers to communicate with an AMP API. Right now I'm trying to do that using WebSockets with Corbin SImpson's txWS. Eventually I'll try to write a Twisted implementation of SockJS, which is basically portable websockets all the way down to IE6.
The issue is that while AMP is inherently a binary protocol, WebSockets transfer text (well, that's a lie: there's a binary version, but it's even less widely supported than WebSockets themselves -- and SockJS doesn't support it at all, although it's on the roadmap). So, I need an alternative, preferably 7-bit, serialization for AMP boxes. My first attempt at that serialization is JSON -- widely supported in browsers, and should map pretty closely to what AMP can do: - AMPLIsts are objects - ListOfs are arrays - numeric types and strings are more or less natively supported (except JSON is always text, never bytes) - booleans are booleans Right now I have something that almost works, but is really a crude, cheap, untested hack. I'm wondering if there's a better integration point. """ AMP over WebSockets support. """ import json import txws from twisted.internet import defer, protocol from twisted.python import log class Bridge(protocol.Protocol): """ Two-way AMP over WebSockets bridge. """ def __init__(self, amp): self._amp = amp amp.startReceivingBoxes(self) amp.boxSender = self def sendBox(self, box): """ Sends a box over the WebSocket as JSON. """ log.msg("Sending box: {}".format(box)) self.transport.write(json.dumps(box)) def jsonObjectReceived(self, obj): """ Hands the JSON object (dict) over to ampBoxReceived. """ log.msg("JSON object received: {}".format(obj)) self._amp.boxReceiver.ampBoxReceived(obj) def dataReceived(self, data): """ Calls jsonObjectReceived. This assumes that JSON objects will always arrive as 1 chunk. """ self.jsonObjectReceived(json.loads(data)) class BridgeFactory(protocol.Factory): """ A factory for AMP over WebSockets bridges. """ def __init__(self, ampFactory): self._ampFactory = ampFactory def buildProtocol(self, addr): """ Builds a bridge and associates it with an AMP protocol instance. """ return Bridge(self._ampFactory.buildProtocol(addr)) def makeFactory(ampFactory): """ Makes a WebSocket factory that bridges AMP messages. """ return txws.WebSocketFactory(BridgeFactory(ampFactory)) An issue I'm running into is an AMP ListOf. With the above code, ListOf still gets translated to a string, and obviously I want it to be a list. When that ListOf has actual data in it, I get the binary representation. The other issues that I predict will happen but haven't ran into yet (because I don't use that functionality) are: - booleans -- expects "True" or "False" but gets True or False (true and false in JSON) -- can be fixed both on the client and the server side, not sure where the optimal place would be - AMPList -- same reason as ListOf ints, floats… will magically work, but it's a bit ugly: the only reason it works is that the factory for them is int and float, and, well, int(5) == 5 == int("5"), so it doesn't actually matter if it's already an int or a str. In my Command implementation, I'm returning {"k": anAxiomQuery} -- so it's iterable but not a list. I can write a custom JSON encoder that can take arbitrary iterables, of course. cheers lvh _______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python