-
Description How can I use socket.io instead of the plain websocket integration? I guess this is more a question belonging to starlette. Currently migrating from a flask application using flask-socketio / python-socketio Any hint is appreciated. Thx. |
Beta Was this translation helpful? Give feedback.
Replies: 52 comments
-
Socket-IO has an ASGI compatible app: https://python-socketio.readthedocs.io/en/latest/server.html#uvicorn-daphne-and-other-asgi-servers You should be able to mount that app like if it was a FastAPI sub-application: https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/#mount-the-sub-application |
Beta Was this translation helpful? Give feedback.
-
Hi, Also have a question regarding python-socketio, Ive tried:
Which does indeed seem to work, but only partially. Only GET requests seems to get through
Is there a way to also allow POST on Thanks |
Beta Was this translation helpful? Give feedback.
-
I am unable to get this to work at all, even with the snippet above. |
Beta Was this translation helpful? Give feedback.
-
I see, here is my complete example,
Where the
I then run uvicorn with the It seems that the routing mechanism in either FastAPI ot Starlette somehow only allows GET requests, but I might be wrong and I'm maybe doing something else wrong. @BlackHoleFox: it did not work at all for me either until I noticed that second parameter of |
Beta Was this translation helpful? Give feedback.
-
Finally, sio = socketio.AsyncServer(async_mode='asgi')
sio_asgi_app = socketio.ASGIApp(sio, app, socketio_path="/api/socket.io")
sio.register_namespace(ws.ConnectNS('/')) Works just fine if you use the |
Beta Was this translation helpful? Give feedback.
-
@marcus-oscarsson I ended up with the same results. I can directly use the |
Beta Was this translation helpful? Give feedback.
-
@BlackHoleFox I see, I simply removed the |
Beta Was this translation helpful? Give feedback.
-
So are we giving up on |
Beta Was this translation helpful? Give feedback.
-
@kientt86 I would say that its up to the maintainer, @tiangolo, to decide exactly what to do with app.mount. I'm not sure if I used it correctly in my example so it could also simply be that I'm missing some option. It would be nice if it worked with Using the |
Beta Was this translation helpful? Give feedback.
-
Thanks for all the reports guys. I want to check how to integrate Socket.IO and integrate it directly in the docs, I haven't had the time though, but I'll do it hopefully soon. |
Beta Was this translation helpful? Give feedback.
-
I´m looking forward for this integrate. It would be great for the project. cheers! |
Beta Was this translation helpful? Give feedback.
-
This is more of a feature request but related to using Hoping this can be implemented on top of the general |
Beta Was this translation helpful? Give feedback.
-
I'm struggling with getting this to work with FastAPI. I've tried this code: fast_app = FastAPI(
openapi_url='/api/notifications/openapi.json',
docs_url='/api/notifications/docs',
redoc_url='/api/notifications/redoc'
)
sio = socketio.AsyncServer(
async_mode='asgi',
cors_allowed_origins='*'
)
app = socketio.ASGIApp(
socketio_server=sio,
other_asgi_app=fast_app,
socketio_path='/api/notifications/socket.io/'
) Which allows me to connect to the socket.io endpoint, but when I attempt to connect to a FastAPI defined endpoint, it'll raise a traceback from python-engineio:
As best I can tell, engineio is attempting to call FastAPI with 4 parameters ('self', 'scope', 'receive', and 'send') .. while 0.33 version of FastAPI is simply using the Starlette call method that only accepts ('self' and 'scope'). I'm interested to learn what version other people (@marcus-oscarsson ) are using where this works inside FastAPI app. I've managed to hack around it with this helper class: from fastapi import FastAPI
from starlette.types import ASGIInstance, Scope, Receive, Send
class FastAPISocketIO(FastAPI):
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> ASGIInstance:
fn = super(FastAPISocketIO, self).__call__(scope=scope)
return await fn(receive=receive, send=send) But it seems the problem is an incompatibility with Starlette and python-socketio? |
Beta Was this translation helpful? Give feedback.
-
Turns out my problem was with Starlette. Starlette version 0.11.1 needed the above hack, while version 0.12.0 doesn't have the problem and works without the above hack. |
Beta Was this translation helpful? Give feedback.
-
A bit more complete example, based on @szelenka's work that might help other people.
|
Beta Was this translation helpful? Give feedback.
-
I have integrated socketio with the fastapi core. pip install "fastapi[socketio] @ git+https://github.com/bnnk/fastapi" Then, after installation, to use: from fastapi.websocketio import SocketIOMerger
<... code here ...>
app = SocketIOMerger(app, <... socketio instance variable ...>) |
Beta Was this translation helpful? Give feedback.
-
i get recursion error as soon as i do |
Beta Was this translation helpful? Give feedback.
-
I got this implemented like this. |
Beta Was this translation helpful? Give feedback.
-
Will it be merged with core?? |
Beta Was this translation helpful? Give feedback.
-
@includeamin Thanks for solution, I have to correct js client for newer versions: (for python-socketio = 5.x and js socketio=4.x) <script>
socket = io('http://localhost:3001', { // <- url parameter is not 'http://localhost:3001/ws'
path: '/ws/socket.io'
});
</script> Otherwise, client thinks /ws is a namespace and altough connection is succesful, server side does not respond to client requests, since namespace doesn't exist on the server side. For custom namespaces : <script>
socket = io('http://localhost:3001/GreyRook', { // <-to connect GreyRook namespace
path: '/ws/socket.io'
});
</script> |
Beta Was this translation helpful? Give feedback.
-
can anybody say any simple implementation of fastApi (uvicorn server ) with simple python client . |
Beta Was this translation helpful? Give feedback.
-
Do you know how to add Fastapi Dependencies on socketio endpoints similar to default Fastapi websockets? |
Beta Was this translation helpful? Give feedback.
-
This one should works for you. |
Beta Was this translation helpful? Give feedback.
-
You could check this one integrated into authx |
Beta Was this translation helpful? Give feedback.
-
Thanks @kosciej16 @yezz123 I am going to check your links |
Beta Was this translation helpful? Give feedback.
-
Hey, I dont get it working with the URL path and I dont know why. There is always the Thanks for you help in advanced So this is my code in a nutshell: socket_server.py # File socket_server.py
import socketio
sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*")
asgi = socketio.ASGIApp(sio)
@sio.on("connect")
def connect(sid, environ, auth) -> None:
print(f"Socket connected: {sid}") application.py (mount at the bottom) # File application.py where you get the FastAPI app
from sockets.socket_server import asgi
def get_app() -> FastAPI:
app = FastAPI(
docs_url="/api/docs",
redoc_url="/api/redoc",
openapi_url="/api/openapi.json",
default_response_class=UJSONResponse,
)
# Disable Docs
if settings.environment != "dev":
app.openapi_url = None
# Adds startup and shutdown events.
register_startup_event(app) # Just create folders if not exist
register_shutdown_event(app)
# Main router for the API.
app.include_router(router=api_router, prefix="/api")
# add static files
app.mount("/static", StaticFiles(directory="/static"), name="static")
app.mount("/", StaticFiles(directory="/pages"), name="pages")
# add websocket
app.mount("/ws", asgi, name="socket")
return app JS const socket = io.connect('http://' + document.domain + ':' + location.port, {
path: '/ws/socket.io'
}); And this is my error:
Client:
Versions I use:
|
Beta Was this translation helpful? Give feedback.
-
Hello @Floskinner you can try with this configuration at client side.
|
Beta Was this translation helpful? Give feedback.
-
Hello @jonra1993 thanks for your help! I got it woking now :) ...but I also got another error and if anyone gets the same error, here is my solution / hint: Error message:
With loguru i can see
Solution:I also have to change the order of my route mounts: # Main router for the API.
app.include_router(router=api_router, prefix="/api")
# add static files
app.mount("/static", StaticFiles(directory="/static"), name="static")
app.mount("/", StaticFiles(directory="/pages"), name="pages")
# add websocket
app.mount("/ws", asgi, name="socket") After: # Main router for the API.
app.include_router(router=api_router, prefix="/api")
# add websocket
app.mount("/ws", asgi, name="socket")
# add static files
app.mount("/static", StaticFiles(directory="/static"), name="static")
app.mount("/", StaticFiles(directory="/pages"), name="pages") Ref: encode/starlette#1548 and https://www.starlette.io/routing/#route-priority |
Beta Was this translation helpful? Give feedback.
-
Hi,
I've tried using Depends, but it's not working
|
Beta Was this translation helpful? Give feedback.
-
@tiangolo When I use the fastapi_socketio with FastAPI version 0.75.2 it works fine, but when I go to latest fastapi like 0.110.0, it starts giving me error on connecting to my socket : My configuration: app = FastAPI() |
Beta Was this translation helpful? Give feedback.
Socket-IO has an ASGI compatible app: https://python-socketio.readthedocs.io/en/latest/server.html#uvicorn-daphne-and-other-asgi-servers
You should be able to mount that app like if it was a FastAPI sub-application: https://fastapi.tiangolo.com/tutorial/sub-applications-proxy/#mount-the-sub-application