Skip to content
This repository was archived by the owner on Apr 4, 2024. It is now read-only.

Commit ce02172

Browse files
authored
Merge pull request #1 from pyropy/add-socketio-fastapi-integration
Add basic socketio fastapi integration
2 parents 011c681 + e50ac9b commit ce02172

File tree

7 files changed

+240
-73
lines changed

7 files changed

+240
-73
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ venv
77
.pytest_cache
88
*.egg-info
99
.DS_Store
10+
.vscode/

Pipfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ neovim = "*"
1111
fastapi = "==0.61.1"
1212
netifaces = "==0.10.6"
1313
pydantic = "==1.6.1"
14-
socketio = "==0.2.1"
1514
starlette = "==0.13.6"
15+
python-socketio = "==4.6.0"
16+
python-engineio = "*"
1617

1718
[test]
1819
pytest = "==6.0.1"

Pipfile.lock

Lines changed: 85 additions & 71 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,40 @@ Install this plugin using `pip`:
1414

1515
## Usage
1616

17-
Usage instructions go here.
17+
To add SocketIO support to FastAPI all you need to do is import `SocketManager` and pass it `FastAPI` object.
18+
19+
```python
20+
# app.py
21+
from fastapi import FastAPI
22+
from fastapi_socketio import SocketManager
23+
24+
app = FastAPI()
25+
socket_manager = SocketManager(app=app)
26+
```
27+
28+
29+
Now you can use SocketIO directly from your `FastAPI` app object.
30+
```python
31+
# socket_handlers.py
32+
from .app import app
33+
34+
@app.sio.on('join')
35+
async def handle_join(sid, *args, **kwargs):
36+
await app.sio.emit('lobby', 'User joined')
37+
38+
```
39+
40+
Or you can import `SocketManager` object that exposes most of the SocketIO functionality.
41+
42+
```python
43+
# socket_handlers2.py
44+
from .app import socket_manager as sm
45+
46+
@sm.on('leave')
47+
async def handle_leave(sid, *args, **kwargs):
48+
await sm.emit('lobby', 'User left')
49+
50+
```
1851

1952
## Development
2053

examples/app.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from fastapi import FastAPI
2+
from fastapi_socketio import SocketManager
3+
4+
app = FastAPI()
5+
sio = SocketManager(app=app)
6+
7+
8+
@app.sio.on('join')
9+
async def handle_join(sid, *args, **kwargs):
10+
await sio.emit('lobby', 'User joined')
11+
12+
13+
@sio.on('test')
14+
async def test(sid, *args, **kwargs):
15+
await sio.emit('hey', 'joe')
16+
17+
18+
19+
if __name__ == '__main__':
20+
import logging
21+
import sys
22+
23+
logging.basicConfig(level=logging.DEBUG,
24+
stream=sys.stdout)
25+
26+
import uvicorn
27+
28+
uvicorn.run("examples:app", host='0.0.0.0', port=8000, reload=True, debug=False)

fastapi_socketio/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
from .socket_manager import SocketManager
2+
13
def example_function():
24
return 1 + 1

fastapi_socketio/socket_manager.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import socketio
2+
from fastapi import FastAPI
3+
4+
5+
class SocketManager:
6+
"""
7+
Integrates SocketIO with FastAPI app.
8+
Adds `sio` property to FastAPI object (app).
9+
10+
Default mount location for SocketIO app is at `/ws`
11+
and defautl SocketIO path is `socket.io`.
12+
(e.g. full path: `ws://www.example.com/ws/socket.io/)
13+
14+
SocketManager exposes basic underlying SocketIO functionality
15+
16+
e.g. emit, on, send, call, etc.
17+
"""
18+
19+
def __init__(
20+
self,
21+
app: FastAPI,
22+
mount_location: str = "/ws",
23+
socketio_path: str = "socket.io",
24+
cors_allowed_origins: list = [],
25+
) -> None:
26+
# TODO: Change Cors policy based on fastapi cors Middleware
27+
self._sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*")
28+
self._app = socketio.ASGIApp(
29+
socketio_server=self._sio, socketio_path=socketio_path
30+
)
31+
32+
app.mount(mount_location, self._app)
33+
app.sio = self._sio
34+
35+
def is_asyncio_based(self) -> bool:
36+
return True
37+
38+
@property
39+
def on(self):
40+
return self._sio.on
41+
42+
@property
43+
def attach(self):
44+
return self._sio.attach
45+
46+
@property
47+
def emit(self):
48+
return self._sio.emit
49+
50+
@property
51+
def send(self):
52+
return self._sio.send
53+
54+
@property
55+
def call(self):
56+
return self._sio.call
57+
58+
@property
59+
def close_room(self):
60+
return self._sio.close_room
61+
62+
@property
63+
def get_session(self):
64+
return self._sio.get_session
65+
66+
@property
67+
def save_session(self):
68+
return self._sio.save_session
69+
70+
@property
71+
def session(self):
72+
return self._sio.session
73+
74+
@property
75+
def disconnect(self):
76+
return self._sio.disconnect
77+
78+
@property
79+
def handle_request(self):
80+
return self._sio.handle_request
81+
82+
@property
83+
def start_background_task(self):
84+
return self._sio.start_background_task
85+
86+
@property
87+
def sleep(self):
88+
return self._sio.sleep

0 commit comments

Comments
 (0)