Skip to main content

SocketIO framework driven by the AsyncAPI specification. Built on top of Flask-SocketIO. Inspired by Connexion.

Project description

Asynction

Tests Status codecov

SocketIO python framework driven by the AsyncAPI specification. Built on top of Flask-SocketIO. Inspired by Connexion.

The purpose of Asynction is to empower a specification first approach when developing SocketIO APIs in Python.

Disclaimer: Asynction is still at a very early stage and should not be used in production codebases.

Features

  • Payload validation (for both incoming and outgoing events), based on the message schemata within the API specification.
  • HTTP request validation, upon connection, based on the channel binding schemata within the API specification.
  • Automatic registration of all event and error handlers defined within the API specification.
  • AsyncAPI playground (coming soon)
  • Authentication à la Connexion (coming soon)

Prerequisites

  • Python 3.7 (or higher)

Install

$ pip install asynction

Usage

Example event and error handler callables located at ./my_api/handlers.py:

# /user namespace

def user_sign_up(data):
    logger.info("Signing up user...")
    emit("metrics", "signup", namespace="/admin")

def user_log_in(data):
    logger.info("Logging in user...")
    emit("metrics", "login", namespace="/admin")

def user_error(e):
    logger.error("Error: %s", e)


# /admin namespace

def authenticated_connect():
    token = request.args["token"]

def admin_error(e):
    logger.error("Admin error: %s", e)

Example specification located at ./docs/asyncapi.yaml:

asyncapi: 2.0.0

info:
  title: User Account Service
  version: 1.0.0
  description: This service is in charge of processing user accounts

servers:
  production:
    url: my-company.com/api/socket.io  # Customizes the `path` kwarg that is fed into the `SocketIO` constructor
    protocol: wss

channels:
  /user:  # A channel is essentially a SocketIO namespace
    publish:
      message:
        oneOf:  # The oneOf Messages relationship expresses the supported events that a client may emit under the `/user` namespace
          - $ref: '#/components/messages/UserSignUp'
          - $ref: '#/components/messages/UserLogIn'
    x-handlers:  # Default namespace handlers (such as connect, disconnect and error)
      error: my_api.handlers.user_error  # Equivelant of: `@socketio.on_error("/user")
  /admin:
    subscribe:
      message:
        oneOf:
          - '#/components/messages/Metrics'
    x-handlers:
      connect: my_api.handlers.authenticated_connect  # Equivelant of: `@socketio.on("connect", namespace="/admin")
      error: my_api.handlers.admin_error
    bindings:  # Bindings are used to validate the HTTP request upon connection
      $ref: '#/components/channelBindings/AuthenticatedWsBindings'

components:
  messages:
    UserSignUp:
      name: sign up  # The SocketIO event name. Use `message` or `json` for unnamed events.
      payload:  # Asynction uses payload JSON Schemata for message validation
        type: object
      x-handler: my_api.handlers.user_sign_up  # The handler that is to be registered. Equivelant of: `@socketio.on("sign up", namespace="/user")
    UserLogIn:
      name: log in
      payload:
        type: object
      x-handler: my_api.handlers.user_log_in
    Metrics:
      name: metrics
      payload:
        type: string
        enum: [signup, login]

  channelBindings:
    AuthenticatedWsBindings:
      ws:  
        query:
          type: object
          properties:
            token:
              type: string
          required: [token]

Bootstrap the AsynctionSocketIO server:

from asynction import AsynctionSocketIO
from flask import Flask

flask_app = Flask(__name__)

asio = AsynctionSocketIO.from_spec(
    spec_path="./docs/asyncapi.yaml",
    app=flask_app,
    message_queue="redis://",
    # any other kwarg that the flask_socketio.SocketIO constructor accepts
)

The AsynctionSocketIO class extends the SocketIO class of the Flask-SocketIO library.
The above asio server object has all the event and error handlers registered, and is ready to run.
Validation of the message payloads and the channel bindings is also enabled by default.
Without Asynction, one would need to add additional boilerplate to register the handlers (as shown here) and implement the respective validators.

Specification Extentions

Asynction has extended the AsyncAPI 2.0.0 specification to provide support for coupling SocketIO entities (such as namespaces and events) to python objects (handlers). The extentions introduced adhere to the Specification Extention guidelines of the AsyncAPI spec.

Event handler

The x-handler field MAY be defined as an additional property of the Message Object. The value of this field MUST be of string type, expressing a dot joint path to a python callable (the event handler).

Message Objects listed under a subscribe operation MUST include the x-handler field.
Message Objects listed under a publish operation SHOULD NOT include the x-handler field.

Default namespace handlers

The x-handlers field MAY be defined as an additional property of the Channel Item Object. The value of this field SHOULD be a Channel Handlers Object.

Channel Handlers Object

Field Name Type Description
connect string Dot joint path to the python connect handler callable
disconnect string Dot joint path to the python disconnect handler callable
error string Dot joint path to the python error handler callable

Limitations / Thoughts

  1. How can the spec express event handler return types (that are to be passed as args to the client callbacks)?

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

asynction-0.0.9.tar.gz (9.0 kB view details)

Uploaded Source

Built Distribution

asynction-0.0.9-py3-none-any.whl (9.7 kB view details)

Uploaded Python 3

File details

Details for the file asynction-0.0.9.tar.gz.

File metadata

  • Download URL: asynction-0.0.9.tar.gz
  • Upload date:
  • Size: 9.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/4.0.1 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.60.0 CPython/3.9.4

File hashes

Hashes for asynction-0.0.9.tar.gz
Algorithm Hash digest
SHA256 2569a2e79e22d6ff748c66c8303dd88161f3d7cbdd92f3a2810c1e8149fe7596
MD5 690da9975ce0338a03cd00408c2709bf
BLAKE2b-256 0e5c2561fde98370a1a767c6c121bebd9746472b921e8427aa7996f7dd4216fd

See more details on using hashes here.

File details

Details for the file asynction-0.0.9-py3-none-any.whl.

File metadata

  • Download URL: asynction-0.0.9-py3-none-any.whl
  • Upload date:
  • Size: 9.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/4.0.1 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.60.0 CPython/3.9.4

File hashes

Hashes for asynction-0.0.9-py3-none-any.whl
Algorithm Hash digest
SHA256 a8e9db0405e590170b4fc91dd710fc26b3b77699d245d5ab22698dec44419216
MD5 684454fbb7db57bd7a2beb4810e45f6e
BLAKE2b-256 3e60cac2127398dfb3ccd25d80d8cd833eae3da72dcde9bc3d97a39e96b6546c

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page