Flask SocketIO with auto-generate Asyncapi documentation
Project description
SIO-AsyncAPI
SIO-AsyncAPI is a Python library built on the top of Flask-SocketIO and driven by AsyncAPI. It allows you to generate an AsyncAPI specification from your SocketIO server and validate messages against it.
Similar to FastAPI, SIO-AsyncAPI allows you to define your SocketIO server using Python type annotations and Pydantic models. It also provides a way to generate an AsyncAPI specification from your SocketIO server.
SIO-AsyncAPI now supports both Pydantic 1.10+ and 2.x, emits AsyncAPI 3.1, and keeps Socket.IO ACKs in the custom x-ack extension.
Installation
pip install sio_asyncapi
Basic Example
# examples/simple.py
from flask import Flask
from sio_asyncapi import AsyncAPISocketIO, ResponseValidationError, RequestValidationError
from pydantic import BaseModel, Field, EmailStr
from typing import Optional
import logging
logger = logging.getLogger(__name__)
app = Flask(__name__)
socketio = AsyncAPISocketIO(
app,
validate=True,
generate_docs=True,
version="1.0.0",
title="Demo",
description="Demo Server",
server_url="http://localhost:5000",
server_name="DEMO_SIO",
)
class UserSignUpRequest(BaseModel):
"""Request model for user sign up"""
email: EmailStr = Field(..., description="User email", example="bob@gmail.com")
password: str = Field(..., description="User password", example="123456")
class UserSignUpResponse(BaseModel):
"""Response model for user sign up"""
success: bool = Field(True, description="Success status")
error: Optional[str] = Field( None, description="Error message if any",
example="Invalid request")
@socketio.on("user_sign_up", get_from_typehint=True)
def user_sign_up(request: UserSignUpRequest) -> UserSignUpResponse:
"""User sign up"""
_ = request
return UserSignUpResponse(success=True, error=None)
@socketio.on_error_default
def default_error_handler(e: Exception):
"""
Default error handler. It called if no other error handler defined.
Handles RequestValidationError and ResponseValidationError errors.
"""
if isinstance(e, RequestValidationError):
logger.error(f"Request validation error: {e}")
return {"success": False, "error": str(e)}
elif isinstance(e, ResponseValidationError):
logger.critical(f"Response validation error: {e}")
raise e
else:
logger.critical(f"Unknown error: {e}")
raise e
if __name__ == '__main__':
socketio.run(app, debug=True)
# import pathlib
# if __name__ == "__main__":
# path = pathlib.Path(__file__).parent / "simple.yml"
# doc_str = socketio.asyncapi_doc.get_yaml()
# with open(path, "w") as f:
# f.write(doc_str)
# print(doc_str)
Here is how validation error looks like in FireCamp:
In order to get the AsyncAPI specification from your SocketIO server instead of running the server, you can do the following:
You can also get a compact agent-friendly event catalog with socketio.get_agent_schema() or socketio.get_agent_schema_json().
See examples/agentic_doc_example.py for a complete example that writes both exports to disk.
import pathlib
if __name__ == "__main__":
path = pathlib.Path(__file__).parent / "simple.yml"
doc_str = socketio.asyncapi_doc.get_yaml()
with open(path, "w") as f:
f.write(doc_str)
print(doc_str)
Example of the AsyncAPI specification generated from the above example:
# examples/simple.yml
asyncapi: 3.1.0
info:
title: Demo
version: 1.0.0
description: 'Demo Server
<br/> This specification targets AsyncAPI 3.1 and keeps Socket.IO ACK values in
the custom `x-ack` message extension.
Socket.IO-specific transport details may still require application-level interpretation.
'
servers:
DEMO_SIO:
host: localhost:5000
protocol: socketio
channels:
root:
address: /
messages:
User_Sign_Up:
$ref: '#/components/messages/User_Sign_Up'
operations:
receive_user_sign_up:
action: receive
channel:
$ref: '#/channels/root'
messages:
- $ref: '#/channels/root/messages/User_Sign_Up'
description: User sign up
components:
messages:
User_Sign_Up:
name: user_sign_up
description: User sign up
payload:
$ref: '#/components/schemas/UserSignUpRequest'
x-ack:
$ref: '#/components/schemas/UserSignUpResponse'
schemas:
NoSpec:
description: Specification is not provided
UserSignUpRequest:
title: UserSignUpRequest
description: Request model for user sign up
type: object
properties:
email:
title: Email
description: User email
example: bob@gmail.com
type: string
format: email
password:
title: Password
description: User password
example: '123456'
type: string
required:
- email
- password
UserSignUpResponse:
title: UserSignUpResponse
description: Response model for user sign up
type: object
properties:
success:
title: Success
description: Success status
default: true
type: boolean
error:
title: Error
description: Error message if any
example: Invalid request
type: string
Rendered version of the above AsyncAPI specification:
Converting from Flask-SocketIO to SIO-AsyncAPI
SIO-AsyncAPI is built on top of Flask-SocketIO and all unit tests of Flask-SocketIO are tested against SIO-AsyncAPI. If you converting your SocketIO server from Flask-SocketIO to SIO-AsyncAPI, you can be sure that your SocketIO server will work as expected. When converting your SocketIO server from Flask-SocketIO to SIO-AsyncAPI, it's as simple as changing the import statement:
# instead of `from flask_socketio import SocketIO`
from sio_asyncapi import AsyncAPISocketIO as SocketIO
...
# There are additional arguments that you can pass to the constructor of AsyncAPISocketIO
socketio = SocketIO(app)
...
Acknowledgements
Most of the implementation follows research done by Dimitrios Dedoussis (https://www.asyncapi.com/blog/socketio-part2) and uses some Pydantic models from here
Missing Features
SIO-AsyncAPI is still in its early stages and there are some features that are not yet implemented. If you are interested in contributing to SIO-AsyncAPI any contribution is welcome. Here is the list of missing features:
- Support of AsycnAPI documentation and validation for
emitmessages - Support of Flask-SocketIO
namespacesandrooms - Authentication and security auto documentation
-
connectanddisconnecthandlers auto documentation
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sio_asyncapi-1.0.0.tar.gz.
File metadata
- Download URL: sio_asyncapi-1.0.0.tar.gz
- Upload date:
- Size: 43.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.3 CPython/3.11.14 Linux/6.14.0-1017-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1c83fd9851f93b299e59abc62ff33c8f7178df6a266c0c7e8e09e5c8cd872143
|
|
| MD5 |
08a3754722e63f0fb01de8406445b82f
|
|
| BLAKE2b-256 |
65944245d59142dcc37e7e206820c42e1adf6ff3b891e616686cfde7fa18f4ed
|
File details
Details for the file sio_asyncapi-1.0.0-py3-none-any.whl.
File metadata
- Download URL: sio_asyncapi-1.0.0-py3-none-any.whl
- Upload date:
- Size: 63.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.3 CPython/3.11.14 Linux/6.14.0-1017-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f398e813c6cc755c73925ae837868c72021d81a11ea23ebbd499d109cab0adf5
|
|
| MD5 |
8280eb7af688e441701475cbbed7599a
|
|
| BLAKE2b-256 |
99056aeabd56dedc3cdef6104b41f71d9a7264e1e17d4b72ca4ad5f3d75b7fd1
|