17

I'm working on a scientific experiment where about two dozen test persons play a turn-based game with/against each other. Right now, it's a Python web app with a WSGI interface. I'd like to augment the usability with websockets: When all players have finished their turns, I'd like to notify all clients to update their status. Right now, everyone has to either wait for the turn timeout, or continually reload and wait for the "turn is still in progress" error message not to appear again (busy waiting, effectively).

I read through multiple websocket libraries' documentation and I understand how websockets work, but I'm not sure about the architecture for mixing WSGI and websockets: Can I have a websockets and a WSGI server in the same process (and if so, how, using really any websockets library) and just call my_websocket.send_message() from a WSGI handler, or should I have a separate websockets server and do some IPC? Or should I not mix them at all?

edit, 6 months later: I ended up starting a separate websockets server process (using Autobahn), instead of integrating it with the WSGI server. The reason was that it's much easier and cleaner to separate the two of them, and talking to the websockets server from the WSGI process (server to server communication) was straight forward and worked on the first attempt using websocket-client.

Simon
  • 12,018
  • 4
  • 34
  • 39

2 Answers2

15

Here is an example that does what you want:

It runs a WSGI web app (Flask-based in this case, but can be anything WSGI conforming) plus a WebSocket server under 1 server and 1 port.

You can send WS messages from within Web handlers. Autobahn also provides PubSub on top of WebSocket, which greatly simplifies the sending of notifications (via WampServerProtocol.dispatch) like in your case.

Disclosure: I am author of Autobahn and work for Tavendo.

oberstet
  • 21,353
  • 10
  • 64
  • 97
  • Awesome, that's exactly what I was looking for! Also, I didn't know about protocols on top of Websockets yet. – Simon Oct 30 '12 at 16:52
  • For a quick intro to WAMP (=RPC+PubSub over WebSocket), check out http://wamp.ws/ – oberstet Oct 30 '12 at 18:22
  • I deployed as an Azure app service and get this error message: (index):20 Mixed Content: The page at 'https://MYAPP.azurewebsites.net/' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://MYAPP.azurewebsites.net:8080/ws'. This request has been blocked; this endpoint must be available over WSS. window.onload @ (index):20 (index):20 Uncaught DOMException: Failed to construct 'WebSocket': An insecure WebSocket connection may not be initiated from a page loaded over HTTPS. at window.onload (https://MYAPP.azurewebsites.net/:20:23) – siddarfer Sep 22 '20 at 16:09
  • it is explicitly disallowed by the websocket spec (rfc6455) for a web browser acting as a websocket client to have the HTML page with the JS opening the websocket connection to have been loaded over HTTPS (that is secure) in non-secure mode (WS rather than WSS). solution: either host your HTML/JS etc on a HTTP endpoint OR connected over WSS to your websocket servver – oberstet Oct 04 '20 at 09:06
2

but I'm not sure about the architecture for mixing WSGI and websockets

I made it

use WSocket

Simple WSGI HTTP + Websocket Server, Framework, Middleware And App.

Includes

  • Server(WSGI) included - works with any WSGI framework
  • Middleware - adds Websocket support for any WSGI framework
  • Framework - simple Websocket WSGI web application framework
  • App - Event based app for Websocket communication When external server used, some clients like Firefox requires http 1.1 Server. for Middleware, Framework, App
  • Handler - adds Websocket support to wsgiref(python builtin WSGI server)
  • Client -Coming soon...

Common Features

  • only single file less than 1000 lines
  • websocket sub protocol supported
  • websocket message compression supported (works if client asks)
  • receive and send pong and ping messages(with automatic pong sender)
  • receive and send binary or text messages
  • works for messages with or without mask
  • closing messages supported
  • auto and manual close

example using bottle web framework and WSocket middleware

from bottle import request, Bottle
from wsocket import WSocketApp, WebSocketError, logger, run
from time import sleep

logger.setLevel(10)  # for debugging

bottle = Bottle()
app = WSocketApp(bottle)
# app = WSocketApp(bottle, "WAMP")

@bottle.route("/")
def handle_websocket():
    wsock = request.environ.get("wsgi.websocket")
    if not wsock:
        return "Hello World!"

    while True:
        try:
            message = wsock.receive()
            if message != None:
                print("participator : " + message)
                
            wsock.send("you : "+message)
            sleep(2)
            wsock.send("you : "+message)
            
        except WebSocketError:
            break
            
run(app)