Python Falcon - Websocket



A WebSocket is a persistent connection between a client and server to provide a bidirectional, full-duplex communication between the two. The communication takes place over HTTP through a single TCP/IP socket connection. It can be seen as an upgrade of HTTP instead of a protocol itself.

One of the limitations of HTTP is that it is a strictly half-duplex or unidirectional protocol. With WebSockets, on the other hand, we can send message-based data, similar to UDP, but with the reliability of TCP. WebSocket uses HTTP as the initial transport mechanism, but keeps the TCP connection alive the connection after the HTTP response is received. Same connection object it can be used two-way communication between client and server. Thus, real-time applications can be built using WebSocket APIs.

Falcon's Websocket support is available only for ASGI applications. To provide Websocket capability, the resource class should have on_websocket() responder coroutine.

async def on_websocket(self, req, ws):
   . . .

Websocket requests can also be intercepted by hooks and middleware. Instead of the Response object, a falcon.asgi.WebSocket object is passed.

How Does a WebSocket Function in Falcon?

The following example demonstrates the functioning of WebSocket in Falcon application. First we have an on_get() responder that renders a template.

Example

The client browser displays a form with a text field and a button, When the button is clicked, a websocket object is created, and the on_websocket() responder is fired. It accepts the message input by the user and echoes it back to the client with a prefix “The message text was”.

import falcon
import falcon.asgi
import jinja2
html = """
<!DOCTYPE html>
<html>
   <head>
      <title>Chat</title>
   </head>
   <body>
      <script>
         var ws = new WebSocket("ws://localhost:8000/hello");
         ws.onmessage = function(event) {
            var messages =document.getElementById('messages')
            var message = document.createElement('li')
            var content = document.createTextNode(event.data)
            message.appendChild(content)
            messages.appendChild(message)
         };
         function sendMessage(event) {
            var input = document.getElementById("messageText")
            ws.send(input.value)
            input.value = ''
            event.preventDefault()
         }
      </script>
      <h1>WebSocket Chat</h1>
      <form action="" onsubmit="sendMessage(event)">
         <input type="text" id="messageText" autocomplete="off"/>
         <button>Send</button>
      </form>
      <ul id='messages'></ul>
   </body>
</html>
"""
class HelloResource:
   async def on_get(self, req, resp):
      """Handles GET requests"""
      resp.status = falcon.HTTP_200
      resp.content_type = 'text/html'
      template=jinja2.Template(html)
      resp.body=template.render()
   async def on_websocket(self, req, websocket):
      await websocket.accept()
      while True:
         data = await websocket.receive_text()
         await websocket.send_text(f"Message text was: {data}")
app = falcon.asgi.App()
hello = HelloResource()
app.add_route('/hello', hello)
import uvicorn
if __name__ == "__main__":
   uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)

Output

Start the Uvicorn server and visit http://localhost:8000/ws URL to display the chat form.

Websocket Image

Enter some text and press the Send button.

Websocket Example
Advertisements