hhuuggoo / ZmqWebBridge

99 stars 11 forks source link

============ ZmqWebBridge

The point of this project is to allow javascript client code to interact with arbitrary zeromq services in the backend, with minimal server side configuration. In general, when people write websocket code, they write alot of application specific web socket code in whichever web framework they are using. We want to push most of the application logic into generic zmq processes, with the only application code running in the web server being the code necessary to authenticate users and decide who can access which resources.

Zmq Web Bridge, is a project that allows javascript running in the browser to connect to zmq.REP and zmq.PUB sockets running on a server, via a python gevent proxy. The javascript client code sets up a websocket, which communicates with the python gevent proxy, which forwards communications to various zmq backends. This package also provides a basic framework for authentication, to determine who can access which zmq resources.

Syntax

js reqrep

::

context = new zmq.Context('wss://localhost:8000/data'); reqrep = context.Socket(zmq.REQ); reqrep.connect('tcp://127.0.0.1:10001', {});

reqrep2 = context.Socket(zmq.REQ); reqrep2.connect('tcp://127.0.0.1:10001', {}); reqrep.send('hello', function(x){ //callback for request console.log(x) } ); reqrep2.send('hello', function(x){ //callback for request console.log(x + 'sdf'); console.log(x + 'sfsf'); });

js pub sub:

::

sub = context.Socket(zmq.SUB); sub.onmessage = function(x){ console.log(['sub', x]); } sub.connect("tcp://127.0.0.1:10002", {});

sever side python: generic, zmq code, which is not apart of this framework:

python : your application bridge

::

from gevent import pywsgi from geventwebsocket.handler import WebSocketHandler import bridge import simplejson

logging.basicConfig(level=logging.DEBUG) class MyBridgeClass(bridge.BridgeWebProxyHandler): def zmq_allowed(self, params): params = simplejson.loads(params) zmq_conn_string = params['zmq_conn_string'] socket_type = params['socket_type'] return params['username'] == 'hugo'

class MyWsgiHandler(bridge.WsgiHandler): bridge_class = MyBridgeClass HWM = 100 #zmq HWM must be set here, and on your server def websocket_allowed(self, environ):

you can add logic here to do auth

  return True

app = MyWsgiHandler() server = pywsgi.WSGIServer(('0.0.0.0', 8000), app.wsgi_handle,

keyfile='/etc/nginx/server.key',

             # certfile='/etc/nginx/server.crt',
             handler_class=WebSocketHandler)

server.serve_forever()

python req rep server, and pub server

::

(this has nothing to do with the bridge, it's just a generic zmq process) import zmq import time

c = zmq.Context() s = c.socket(zmq.REP) s.bind('tcp://127.0.0.1:10001')

while True: msg = s.recv_multipart() print 'received', msg s.send_multipart(['goober'])


import zmq import time

c = zmq.Context() s = c.socket(zmq.PUB) s.bind('tcp://127.0.0.1:10002') while(True): for c in range(100): print c s.send(str(c)) time.sleep(1)

bridge code structure

ZmqGatewayFactory - returns an existing zeromq gateway if we have one, otherwise constructs a new onew

WebProxyHandler - generic handler which works with proxy objects, proxies can register with WebProxyHandler, and deregister with them

============= RPC Interface

We've also built in an RPC interface

Request Reply

Pub Sub

Pub sub allows the server, to remotely call functions on the client - though since the communciation is one way, there is no return value. Also since JS does not support key word args, we only support positional arguments