Package: sio-asyncapi
SIO-AsyncAPISIO-AsyncAPI is a Python library built on the top ofFlask-SocketIOand driven byAsyncAPI. 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.Installationpipinstallsio_asyncapiBasic Example# examples/simple.pyfromflaskimportFlaskfromsio_asyncapiimportAsyncAPISocketIO,ResponseValidationError,RequestValidationErrorfrompydanticimportBaseModel,Field,EmailStrfromtypingimportOptionalimportlogginglogger=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",)classUserSignUpRequest(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")classUserSignUpResponse(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)defuser_sign_up(request:UserSignUpRequest)->UserSignUpResponse:"""User sign up"""_=requestreturnUserSignUpResponse(success=True,error=None)@socketio.on_error_defaultdefdefault_error_handler(e:Exception):"""Default error handler. It called if no other error handler defined.Handles RequestValidationError and ResponseValidationError errors."""ifisinstance(e,RequestValidationError):logger.error(f"Request validation error:{e}")returnUserSignUpResponse(error=str(e),success=False).json()elifisinstance(e,ResponseValidationError):logger.critical(f"Response validation error:{e}")raiseeelse:logger.critical(f"Unknown error:{e}")raiseeif__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:importpathlibif__name__=="__main__":path=pathlib.Path(__file__).parent/"simple.yml"doc_str=socketio.asyncapi_doc.get_yaml()withopen(path,"w")asf:f.write(doc_str)print(doc_str)Example of the AsyncAPI specification generated from the above example:# examples/simple.ymlasyncapi:2.5.0channels:/:publish:message:oneOf:-$ref:'#/components/messages/User_Sign_Up'subscribe:message:oneOf:[]x-handlers:disconnect:disconnectcomponents:messages:User_Sign_Up:description:User sign upname:user_sign_uppayload:$ref:'#/components/schemas/UserSignUpRequest'deprecated:falsex-ack:description:Response model for user sign upproperties:error:description:Error message if anyexample:Invalid requesttitle:Errortype:stringsuccess:default:truedescription:Success statustitle:Successtype:booleantitle:UserSignUpResponsetype:objectschemas:NoSpec:deprecated:falsedescription:Specification is not providedUserSignUpRequest:description:Request model for user sign upproperties:email:description:User emailexample:bob@gmail.comformat:emailtitle:Emailtype:stringpassword:description:User passwordexample:'123456'title:Passwordtype:stringrequired:-email-passwordtitle:UserSignUpRequesttype:objectUserSignUpResponse:description:Response model for user sign upproperties:error:description:Error message if anyexample:Invalid requesttitle:Errortype:stringsuccess:default:truedescription:Success statustitle:Successtype:booleantitle:UserSignUpResponsetype:objectinfo:description:'DemoServer<br/>AsyncAPIcurrentlydoesnotsupportSocket.IObindingandWebSocketlikesyntaxusedfornow.InordertoaddsupportforSocket.IOACKvalue,AsyncAPIisextendedwithwithx-ackkeyword.Thisdocumentationshould**NOT**beusedforgeneratingcodeduetotheselimitations.'title:Demoversion:1.0.0servers:DEMO_SIO:protocol:socketiourl:http://localhost:5000Rendered version of the above AsyncAPI specification:Converting from Flask-SocketIO to SIO-AsyncAPISIO-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`fromsio_asyncapiimportAsyncAPISocketIOasSocketIO...# There are additional arguments that you can pass to the constructor of AsyncAPISocketIOsocketio=SocketIO(app)...AcknowledgementsMost of the implementation follows research done by Dimitrios Dedoussis (https://www.asyncapi.com/blog/socketio-part2) and uses some Pydantic models fromhereMissing FeaturesSIO-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 foremitmessagesSupport of Flask-SocketIOnamespacesandroomsAuthentication and security auto documentationconnectanddisconnecthandlers auto documentation