Elegant WebSockets for your Flask apps.

Overview

Flask-Sockets

Elegant WebSockets for your Flask apps.

http://farm4.staticflickr.com/3689/9755961864_577e32a106_c.jpg

Simple usage of route decorator:

from flask import Flask
from flask_sockets import Sockets


app = Flask(__name__)
sockets = Sockets(app)


@sockets.route('/echo')
def echo_socket(ws):
    while not ws.closed:
        message = ws.receive()
        ws.send(message)


@app.route('/')
def hello():
    return 'Hello World!'


if __name__ == "__main__":
    from gevent import pywsgi
    from geventwebsocket.handler import WebSocketHandler
    server = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler)
    server.serve_forever()

Usage of Flask blueprints:

from flask import Flask, Blueprint
from flask_sockets import Sockets


html = Blueprint(r'html', __name__)
ws = Blueprint(r'ws', __name__)


@html.route('/')
def hello():
    return 'Hello World!'

@ws.route('/echo')
def echo_socket(socket):
    while not socket.closed:
        message = socket.receive()
        socket.send(message)


app = Flask(__name__)
sockets = Sockets(app)

app.register_blueprint(html, url_prefix=r'/')
sockets.register_blueprint(ws, url_prefix=r'/')


if __name__ == "__main__":
    from gevent import pywsgi
    from geventwebsocket.handler import WebSocketHandler
    server = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler)
    server.serve_forever()

Combining WebSockets with Ajax (XHR) endpoints also comes handy with the support of session handling built-in to sockets as well. As an example you could use an Ajax login call which would create a new session and accordingly set a secure HttpOnly cookie to the browser. After authorization, you can connect to the WebSocket endpoint and reuse the session handling from Flask there as well (as shown here: https://pythonhosted.org/Flask-Session/). Access to other custom cookies is also possible via Flasks request.cookies property.

Serving WebSockets in Python was really difficult. Now it's not.

Installation

To install Flask-Sockets, simply:

$ pip install Flask-Sockets

Deployment

A custom Gunicorn worker is included to make deployment as friendly as possible:

$ gunicorn -k flask_sockets.worker hello:app

Production services are provided by gevent and gevent-websocket.

The given example can run standalone as main.

Anything that inserts wsgi.websocket into the WSGI environ is supported, but gevent-websocket is recommended.

Development / Testing

Because the Werkzeug development server cannot provide the WSGI environ with a websocket interface, it is not possible to run a Flask app using the standard app.run().

If you try to, Flask will still try to serve on all the specified routes, and throw a KeyError whenever a client tries to connect to a websocket route.

Instead, just use the included gunicorn worker (explained above), or anything that can insert wsgi.websocket into the WSGI environ.

WebSocket Interface

The websocket interface that is passed into your routes is provided by gevent-websocket. The basic methods are fairly straightforward — send, receive, send_frame, and close.

Release History

v0.2.1

v0.2.0

  • Add request context into the socket handler.
  • Fallback to Flask logic if websocket environment is not available.
  • Use Flask routing to allow for variables in URL

v0.1.0

  • Initial release.
Comments
  • Use werkzeug URL routing (like Flask does) / get rid of middleware.

    Use werkzeug URL routing (like Flask does) / get rid of middleware.

    ...ers.

    This allows the use of parameters in URLs, for example a route of

    @sockets.route("/chat/<name>/")
    def chat_channel(name):
       # ...
    

    properly gets passed the channel name.

    opened by mbr 13
  • The example code gives me an error?

    The example code gives me an error?

    I'm trying to use Flask-Sockets with the example code:

    sockets = Sockets(app)
    
    @sockets.route('/echo')
    def echo_socket(ws):
        while True:
            message = ws.receive()
            ws.send(message)
    

    Unfortunately it gives me an error saying:

        File "/Library/Python/2.7/site-packages/Flask-0.10-py2.7.egg/flask/app.py", line 1836, in __call__
        return self.wsgi_app(environ, start_response)
        File "/Library/Python/2.7/site-packages/flask_sockets.py", line 37, in __call__
        environment = environ['wsgi.websocket']
        KeyError: 'wsgi.websocket'
    

    Anybody any ideas what I'm doing wrong? All tips are welcome!

    opened by kramer65 12
  • Any kind of connection is tried to be upgraded to WS connection

    Any kind of connection is tried to be upgraded to WS connection

    Hello,

    I am using both flask router and flash-sockets. That means, my server has both http and websocket end points. After flash-socket integration, any calls to my http router also try to upgrade the request. And getting following error.

    Initializing WebSocket Sep 25 04:12:32 surcle app/web.1: Validating WebSocket request Sep 25 04:12:32 surcle app/web.1: Can only upgrade connection if using GET method.

    This is how I register blueprint in init.py

    from router import router, ws
    app.register_blueprint(router)
    
    sockets = Sockets(app)
    sockets.register_blueprint(ws)
    

    And in router.py

    router = Blueprint('router', __name__)
    ws = Blueprint('ws', __name__)
    @ws.route('/socket')
    def web_socket(socket):
        logging.debug('inside web_socket')
        while not socket.closed:
            message = socket.receive()
            socket.send(message)
    
    @router.route('/status', methods=['POST'])
    def status():
        print "inside status"
    

    What went wrong?

    opened by winster 11
  • add werkzeug routing: allows '/endpoint/<some_id>' style routing

    add werkzeug routing: allows '/endpoint/' style routing

    This adds support for variable url paths just like with Flask's app.route decorator, so you can now do things like:

    @sockets.route('/submit/<game_id>')
    def submit(ws, game_id):
        ...
    

    I hadn't seen pull requests #7 and #14 before I wrote this, this is essentially the same thing but done differently (and with less changes) so maybe you'll like this better? I used werkzeug since this is what Flask is using. This works fine for me although I only tested it in the context of my project. If you think this doesn't make sense I'm happy to take suggestions and improve it, seems like this is a feature a lot of people want.

    opened by jolleon 9
  • AttributeError: 'WebSocket' object has no attribute 'socket'

    AttributeError: 'WebSocket' object has no attribute 'socket'

    my flask version is 0.10. When I type gunicorn -k flask_sockets.worker chat:app, there is an error: AttributeError: 'WebSocket' object has no attribute 'socket' why?

    opened by no13bus 8
  • add support for cookies in the websocket

    add support for cookies in the websocket

    if cookies are used for session handling, please note that you have to persist your session manually.

    something like self.app.save_session(session, make_response("")) after messages are received does the trick.

    opened by robertaistleitner 5
  • Using sockets with route pattern

    Using sockets with route pattern

    I've got the following code, and it will open and immediately close the websocket connection.

    @sockets.route('/sockets/<channel>')
    def echo_socket(ws):
        while True:
            message = ws.receive()
            ws.send(message)
    

    Not quite sure if this is a feature request or a bug, but I think that WS routes should be able to accept flask route patterns.

    opened by issackelly 4
  • Send a message to a single client

    Send a message to a single client

    How could I send a message to a single client that is connected? I'm looking for something to send a notification to a logged in user that something is ready or so. Ideas?

    opened by wiesson 4
  • Documentation on sending binary data?

    Documentation on sending binary data?

    I'd like to send binary data using this library, but I have no idea how to get there. So far I'm only getting encoding errors - probably because it's assumed that I'm sending ASCII strings. How to get around that?

    opened by d33tah 3
  • blueprint issue

    blueprint issue

    In my router.py, when I tried to create sockets object, it failed with following error

    AttributeError: 'Blueprint' object has no attribute 'wsgi_app'
    

    This is how I tried to create sockets object.

    router = Blueprint('router', __name__)
    sockets = Sockets(router)
    

    Since above statements didnt work, I also tried to put the following code in __init.py__:

    from router import router
    app.register_blueprint(router)
    sockets = Sockets(router)
    sockets.register_blueprint(router)
    

    How to fix this?

    opened by winster 3
  • Just added a small patch to make the flask_sockets.worker play nicely with gunicorn's access-logformat

    Just added a small patch to make the flask_sockets.worker play nicely with gunicorn's access-logformat

    Basically, this small patch makes flask_sockets.worker work with gunicorn's access log configuration (rather than the hard-coded .log_request() and .format_request() in pywsgi.WSGIHandler).

    Happy to do some polishing :)

    opened by tkrajca 3
  • Project Status?

    Project Status?

    I noticed that the last commit is from May 2017 and that the description includes [DEPRECATED]. @edmorley is this project still being maintained? If not, is there an up to date fork? Or should we just use WebSocket more directly as described here. Thank you!

    opened by davidhariri 5
  • how to get a websockets address with gunicorn

    how to get a websockets address with gunicorn

    when i run gunicorn -k flask_sockets.worker hello:app, I get a http address like http://0.0.0.0:3000, how I get a websockets address like ws://0.0.0.0:3000

    opened by v-yunbin 0
  • TypeError: register() takes 3 positional arguments but 4 were given

    TypeError: register() takes 3 positional arguments but 4 were given

    When running the main I'm facing this TypeError.The source of the error is while registering the sockets in blueprint

    app.register_blueprint(html, url_prefix=r'/')
    sockets.register_blueprint(ws, url_prefix=r'/')
    

    app.register_blueprint seems to be working fine.

    opened by AlbinDavid 3
  • Set websocket=True for Rule, fixes #81

    Set websocket=True for Rule, fixes #81

    This fixes the WebsocketMismatch which appears with Werkzeug 2.0.0.

    The cause is a websocket request hits a rule which Werkzeug doesn't think is a websocket endpoint.

    opened by tomviner 5
  • Incompatible with Werkzueg>=2.0

    Incompatible with Werkzueg>=2.0

    I'm experiencing werkzeug.routing.WebsocketMismatch: 400 Bad Request after the recent release of werkzueg and flask. I'm not really sure why this is, but the docs state:

    you receive a WebsocketMismatch exception if the only match is a WebSocket rule but the bind is an HTTP request, or if the match is an HTTP rule but the bind is a WebSocket request.

    Here's the traceback I'm observing:

    Traceback (most recent call last):
      File "/venv/lib/python3.9/site-packages/gevent/pywsgi.py", line 999, in handle_one_response
        self.run_application()
      File "/venv/lib/python3.9/site-packages/geventwebsocket/handler.py", line 75, in run_application
        self.run_websocket()
      File "/venv/lib/python3.9/site-packages/geventwebsocket/handler.py", line 52, in run_websocket
        list(self.application(self.environ, lambda s, h, e=None: []))
      File "/venv/lib/python3.9/site-packages/flask/app.py", line 2464, in __call__
        return self.wsgi_app(environ, start_response)
      File "/venv/lib/python3.9/site-packages/flask_sockets.py", line 40, in __call__
        handler, values = adapter.match()
      File "/venv/lib/python3.9/site-packages/werkzeug/routing.py", line 2026, in match
        raise WebsocketMismatch()
    
    opened by rmorshea 20
  • Incompatibility with Flask 2.0

    Incompatibility with Flask 2.0

    Flask 2.0, which has been recently released, changes the prototype of Blueprint.register

    This triggers an exception on this line: https://github.com/heroku-python/flask-sockets/blob/003660b70bbe16e218fb8b28377603e86e9d1b36/flask_sockets.py#L100

    opened by mcejp 1
Owner
Heroku Python Team
Python projects owned by Heroku.
Heroku Python Team
Chat app for Django, powered by Django Channels, Websockets & Asyncio

Django Private Chat2 New and improved https://github.com/Bearle/django-private-chat Chat app for Django, powered by Django Channels, Websockets & Asyn

Bearle 205 Dec 30, 2022
WebSocket implementation in Python built on top of websockets python library. Similar to Node.js's ws.

ws WebSocket implementation in Python built on top of websockets python library. Similar to Node.js's ws. Basic usage. server.py import ws server = w

AceExpert 7 Jun 27, 2022
Library for easily creating and managing websockets.

Documentation coming in version 0.1.4 GitHub PyPI Discord Features Easy to use with object oriented syntax. Intellisense support with typehints and do

ZeroIntensity 0 Aug 27, 2022
Connects microservices through a mesh of websockets

WebMesh WebMesh is a WebSocket based communication library for microservices. It uses a WebSocket server based on wsproto that distributes clients on

Charles Smith 9 Apr 29, 2022
A Security Tool for Enumerating WebSockets

STEWS: Security Testing and Enumeration of WebSockets STEWS is a tool suite for security testing of WebSockets This research was first presented at OW

null 175 Jan 1, 2023
An IPC based on Websockets, fast, stable, and reliable

winerp An IPC based on Websockets. Fast, Stable, and easy-to-use, for inter-communication between your processes or discord.py bots. Key Features Fast

Black Thunder 5 Aug 9, 2022
Socket.IO integration for Flask applications.

Flask-SocketIO Socket.IO integration for Flask applications. Installation You can install this package as usual with pip: pip install flask-socketio

Miguel Grinberg 4.9k Jan 3, 2023
Get realtime updates in your mobile/web app from frappe and erpnext

Fsocket Extend frappe's websocket server using socket.io and redis Installation Use frappe bench to add fsocket in your project $ bench get-app https:

null 21 Sep 25, 2022
A fast and durable Pub/Sub channel over Websockets. FastAPI + WebSockets + PubSub == ⚡ 💪 ❤️

⚡ ??️ FastAPI Websocket Pub/Sub A fast and durable Pub/Sub channel over Websockets. The easiest way to create a live publish / subscribe multi-cast ov

null 8 Dec 6, 2022
Burgeramt-appointments-websockets - Fetch Bürgeramt appointments and broadcast them via websockets

Bürgeramt appointment finder This server looks for Bürgeramt appointment every f

null 74 Dec 19, 2022
Width-customizer-for-streamlit-apps - Width customizer for Streamlit Apps

?? Width customizer for Streamlit Apps As of now, you can only change your Strea

Charly Wargnier 5 Aug 9, 2022
Fast, asynchronous and elegant Python web framework.

Warning: This project is being completely re-written. If you're curious about the progress, reach me on Slack. Vibora is a fast, asynchronous and eleg

vibora.io 5.7k Jan 8, 2023
AkShare is an elegant and simple financial data interface library for Python, built for human beings! 开源财经数据接口库

Overview AkShare requires Python(64 bit) 3.7 or greater, aims to make fetch financial data as convenient as possible. Write less, get more! Documentat

Albert King 5.8k Jan 3, 2023
Simple, elegant, Pythonic functional programming.

Coconut Coconut (coconut-lang.org) is a variant of Python that adds on top of Python syntax new features for simple, elegant, Pythonic functional prog

Evan Hubinger 3.6k Jan 3, 2023
A simple, yet elegant HTTP library.

Requests Requests is a simple, yet elegant HTTP library. >>> import requests >>> r = requests.get('https://api.github.com/user', auth=('user', 'pass')

Python Software Foundation 48.8k Jan 5, 2023
An elegant mirai-api-http v2 Python SDK.

Ariadne 一个适用于 mirai-api-http v2 的 Python SDK。 本项目适用于 mirai-api-http 2.0 以上版本。 目前仍处于开发阶段,内部接口可能会有较大的变化。 安装 poetry add graia-ariadne 或 pip install graia

Graia Project 259 Jan 2, 2023
an elegant datasets factory

rawbuilder an elegant datasets factory Free software: MIT license Documentation: https://rawbuilder.readthedocs.io. Features Schema oriented datasets

Mina Farag 7 Nov 12, 2022
Dominate is a Python library for creating and manipulating HTML documents using an elegant DOM API

Dominate Dominate is a Python library for creating and manipulating HTML documents using an elegant DOM API. It allows you to write HTML pages in pure

Tom Flanagan 1.5k Jan 9, 2023
A simple, elegant Python based web templating engine (part of web.py).

Templator Simple, elegant Python based web templating (part of web.py). If you are familiar with Python, there is no new syntax to learn. This is a st

Dan 1 Dec 13, 2021
Plot toolbox based on Matplotlib, simple and elegant.

Elegant-Plot Plot toolbox based on Matplotlib, simple and elegant. 绘制效果 绘制过程 数据准备 每种图标类型的目录下有data.csv文件,依据样例数据填入自己的数据。

null 3 Jul 15, 2022