One of the design patterns that I observed was that people were running their websocket server as a separate process on a separate port, because there are just enough differences between the websocket protocol and HTTP that it’s difficult to get them into a normal web server. That’s crap; if websockets are going to replace xmlhttprequest, it has to be just as easy to write the server part of web sockets as it is to write a web page.
So here’s a websocket implementation that works inside (a slight modification to) WSGI. It requires the latest development version of Eventlet (see sidebar to the right for instructions on getting that). It’s very very rough at this point, but it’s powerful enough that it seemed worth sharing this initial version.
Now, here’s the code for a simple echo server:
def handle(ws): while True: m = ws.wait() if m is None: break ws.send(m)
It shows the basics in a nutshell, which are incredibly simple:
- call wait() to receive a message from the browser
- call send() to send a message to the browser
- wait() returns None when the browser closes the socket
- return from the function to close the socket from the server side
You’re free to spawn off new greenthreads to do complex stuff with reading from and writing to the ws object concurrently; it will just work.
Here’s how you set up the server:
from eventlet.green import socket from eventlet import wsgi listener = socket.socket() listener.bind(('localhost', 7000)) listener.listen(500) wsgi.server(listener, WebSocketWSGI(handle, 'http://localhost:7000'))
That’s it! Most of that is socket creation boilerplate; the WebSocketWSGI class handles the work of converting an incoming WSGI request to a websocket call. The “http://localhost:7000/” is the websocket ORIGIN field, which needs to be hardcoded to some degree in order to prevent XSS attacks.
So, that’s how the code looks, but you want to run something right away. In your copy of the eventlet tree, run this command:
PYTHONPATH=. python examples/websocket.py
Now, fire up Google Chrome and navigate to http://localhost:7000. It should show you a page that looks like this:
It’s a graph that fills in dynamically based on values that it gets from the websocket. The cool thing about this is that the HTML page and the websocket are both served from the same port, and the same WSGI application. It simply dispatches to the websocket handler like any other url-path-based dispatcher. It’s flashy, self-contained, and scalable, and all it took was ~30 lines of code.
Take a look at the code! Have fun with it! I’ll make a post shortly about the slight modifications I had to make to eventlet.wsgi to get this working seamlessly.