In my earlier post, I referred to some minor changes that I had to make to the wsgi server to seamlessly support a websocket client. I think these changes are generic and simple enough that they, or something similar in spirit, should make it into the WSGI standard someday. Being able to support websockets from within WSGI applications is just too powerful of a use case to ignore.
Get the Socket Out of the Environment
The first change I made was to add a get_socket() method to the file-like object that appears in 'wsgi.input'. This method returns the underlying socket object directly, which is then used in the WebSocket object to handle message transfer.
One reason that this might not be the most ideal of implementations is buffering. It happens that eventlet.wsgi is implemented such that when calling the wsgi application, the very next byte to be read off the socket is the first byte of the first websocket messsage. It seems plausible that other WSGI servers might not have this property.
Cancel Post-Application Processing
The second change is that when eventlet.wsgi sees that the application returned a special flag value ALREADY_HANDLED, it aborts all post-application processing and skips straight to closing the socket. Normally it would write the headers and return value to the socket, but since the application has already handled that stuff, we don’t want the WSGI server throwing junk on the line (or complaining that the app didn’t call start_response).
The downside of this approach is that most middleware would have to be changed (slightly) to support ALREADY_HANDLED. Raising a special exception seems to have the same problem. But then again, changing the behavior of middleware is kinda the point.
So, those are my two changes. I’m certain that there is a way to do this that is even more seamless with the intent of the WSGI standard, but these changes required three lines of code to implement, and work today. :)



