pyropy / fastapi-socketio

Easily integrate socket.io with your FastAPI app 🚀
Apache License 2.0
328 stars 31 forks source link

Error: Get socket.io 404 error #12

Closed msyazwan closed 2 years ago

msyazwan commented 3 years ago

I try to run the package but received this error:

127.0.0.1:51474 - "GET /socket.io/?EIO=3&transport=polling&t=NOi5NZ- HTTP/1.1" 404 Not Found

This is my code

from fastapi import FastAPI
from fastapi_socketio import SocketManager

app = FastAPI()

sio = SocketManager(app=app, cors_allowed_origins=["*"])

@app.get("/")
def read_root():
    return {"Hello": "World"}

@sio.on('connect')
async def connect():
    print('connect')

if __name__ == '__main__':
    import logging
    import sys

    logging.basicConfig(level=logging.DEBUG,
                        stream=sys.stdout)

    import uvicorn

    uvicorn.run("main:app", host='127.0.0.1',
                port=8000, reload=True, debug=False)
pyropy commented 3 years ago

Hey @msyazwan thanks for reporting. Mount location. for socket.io is on /ws so what you could actually do is change a resource on the clientside like so:

var io = require('socket.io').listen(app, { resource: '/ws/socket.io' });

You can also change mount location on the SocketManager, but they may be some conflicts with FastAPI routes (that's why the default mount location is set to /ws).

i.e. sio = SocketManager(app=app, cors_allowed_origins=["*"], mount_location='/')

NOTE: Be careful with changing the mount location.

makusudi commented 3 years ago

got the same issue with the similar code =\ i think problem is on the FastAPI side... routes are exactly right

msyazwan commented 3 years ago

got the same issue with the similar code =\ i think problem is on the FastAPI side... routes are exactly right

Yeah I'm still can't get this working. My frontend is just a simple HTML file and I call socket io from CDN. Most probably the issue is from FastAPI side.

pyropy commented 3 years ago

@msyazwan @makusudi Can you share your client code where you're connecting to websocket using socket.io library?

makusudi commented 3 years ago

@pyropy @msyazwan finally i did it, see this comment and versions of required libraries

yellowMtn commented 3 years ago

I build a little demo to tryout bidirectional communication via websockets in FLASK, which worked ok. Now I am trying to do the same setup with FastAPI (and fastapi-socketio instead of flask-socketio) which fails to connect, displaying the same error. Can someone please explain what I am doing wrong? Thank you in advance!

index.html:

<!DOCTYPE html>
<html>

<head>
  <script src="//code.jquery.com/jquery-3.3.1.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.3/socket.io.js"
    integrity="sha512-2RDFHqfLZW8IhPRvQYmK9bTLfj/hddxGXQAred2wNZGkrKQkLGj8RCkXfRJPHlDerdHHIzTFaahq4s/P4V6Qig=="
    crossorigin="anonymous"></script>
  <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>

<body>

  <script type="text/javascript">

    $(document).ready(function () {

      //var socket = io.connect('http://' + document.domain + ':' + location.port);
      var socket = io('http://localhost:8000/ws', {path: 'ws/socket.io'});

      socket.on('connect', function (event) {
        console.log('user is connected now');
        socket.emit('client_connect_event', { data: 'User connected' });
      });

      socket.on('server_antwort_01', function (msg, cb) {
        $('#log0').append('<br>' + $('<div/>').text('logs #' +  ': ' + msg.data).html());
        if (cb)
          cb();
      });

      $('form#start').submit(function (event) {
        socket.emit('client_start_event', { data: 'Start doing something' });
        return false;
      });

      $('form#stop').submit(function (event) {
        socket.emit('client_stop_event', { data: 'Stop doing something' });
        return false;
      });
    });
  </script>

  <h1>Websocket Demo</h1>

  <h2> Press below to display something send from Server</h2>
  <form id="start" method="post" action="#">
    <input type="submit" value="Start">
  </form>

  <form id="stop" method="post" action="#">
    <input type="submit" value="Stop">
  </form>

  <h3> Log </h3>
  <div id="log0"></div>
</body>
</html>

mainSocket.py

from fastapi import FastAPI
from fastapi_socketio import SocketManager
from fastapi.responses import HTMLResponse

app = FastAPI()
socket_manager = SocketManager(app=app)

html = ""
with open('index.html', 'r') as f:
    html = f.read()

@app.get("/")
async def get():
    return HTMLResponse(html)

@app.sio.on('client_connect_event')
async def handle_client_connect_event(message):
    print(message)
    await app.sio.emit('server_antwort01', {'data': 'connection was successful'})    

@app.sio.on('client_start_event')
async def handle_client_start_event(message):
    print('Server says: start_event worked')
    print(message)
    await app.sio.emit('server_antwort01',{'data':'start event worked'}) 
pyropy commented 3 years ago

@yellowMtn Hi there, I took a look at your code and here's some changes that I made in order to get it working.

I've updated your mainSocket.py file with proper argument for socket.io handler functions. Here's an updated example.

from fastapi import FastAPI
from fastapi_socketio import SocketManager
from fastapi.responses import HTMLResponse

app = FastAPI()
socket_manager = SocketManager(app=app)

html = ""
with open('index.html', 'r') as f:
    html = f.read()

@app.get("/")
async def get():
    return HTMLResponse(html)

@app.sio.on('client_connect_event')
async def handle_client_connect_event(sid, *args, **kwargs):
    await app.sio.emit('server_antwort01', {'data': 'connection was successful'})    

@app.sio.on('client_start_event')
async def handle_client_start_event(sid, *args, **kwargs):
    print('Server says: start_event worked')
    await app.sio.emit('server_antwort01',{'data':'start event worked'}) 

In the client code I've changed connection string from http://localhost:8000/ws to ws://localhost:8000. Here's an full updated example:

<!DOCTYPE html>
<html>

<head>
    <script src="//code.jquery.com/jquery-3.3.1.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.3/socket.io.js"
        integrity="sha512-2RDFHqfLZW8IhPRvQYmK9bTLfj/hddxGXQAred2wNZGkrKQkLGj8RCkXfRJPHlDerdHHIzTFaahq4s/P4V6Qig=="
        crossorigin="anonymous"></script>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>

<body>
    <h1>Websocket Demo</h1>

    <h2> Press below to display something send from Server</h2>
    <form id="start" method="post" action="#">
        <input type="submit" value="Start">
    </form>

    <form id="stop" method="post" action="#">
        <input type="submit" value="Stop">
    </form>

    <h3> Log </h3>
    <div id="log0"></div>
</body>

<script type="text/javascript">

    $(document).ready(function () {

        var socket = io('ws://localhost:8000', {
            path: '/ws/socket.io'
        });

        socket.on('connect', function (event) {
            console.log('user is connected now');
            socket.emit('client_connect_event', { data: 'User connected' });
        });

        socket.on('server_antwort_01', function (msg, cb) {
            $('#log0').append('<br>' + $('<div/>').text('logs #' + ': ' + msg.data).html());
            if (cb)
                cb();
        });

        $('form#start').submit(function (event) {
            socket.emit('client_start_event', { data: 'Start doing something' });
            return false;
        });

        $('form#stop').submit(function (event) {
            socket.emit('client_stop_event', { data: 'Stop doing something' });
            return false;
        });
    });
</script>

</html>

Let me know if you have more questions. To all other people involved in the conversation I would like to apologise for not being active recently.

jonra1993 commented 2 years ago

If someone is facing a problem connecting the client with the server despite everything being correctly configured do not forget to add transportation property on the client as is mentioned here https://github.com/miguelgrinberg/python-socketio/issues/205#issuecomment-647045744.

transports: ['websocket', 'polling', 'flashsocket']