简体   繁体   English

使用 Socket.io 连接时,在 Python 服务器上出现重复 404 错误

[英]Getting repeated 404 errors on Python server when connecting using Socket.io

I have an app that uses standard WebSockets with FastAPI, and that works well.我有一个使用标准 WebSockets 和 FastAPI 的应用程序,效果很好。 Instead of using FastAPI's WebSocket capability, I would like to use Socket.io .我不想使用 FastAPI 的 WebSocket 功能,而是想使用Socket.io I have looked at lots of examples, and while it looks like I have copied the examples almost exactly, I still get a bunch of errors in the command prompt:我查看了很多示例,虽然看起来我几乎完全复制了这些示例,但我仍然在命令提示符下收到一堆错误:

←[32mINFO←[0m:     127.0.0.1:56005 - "←[1mOPTIONS /socket.io/?EIO=4&transport=polling&t=ODINHQk HTTP/1.1←[0m" ←[31m400 Bad Request←[0m
←[32mINFO←[0m:     127.0.0.1:56005 - "←[1mGET /socket.io/?EIO=4&transport=polling&t=ODINHQk HTTP/1.1←[0m" ←[31m404 Not Found←[0m
←[32mINFO←[0m:     127.0.0.1:56005 - "←[1mOPTIONS /socket.io/?EIO=4&transport=polling&t=ODINHq1 HTTP/1.1←[0m" ←[31m400 Bad Request←[0m
←[32mINFO←[0m:     127.0.0.1:56005 - "←[1mGET /socket.io/?EIO=4&transport=polling&t=ODINHq1 HTTP/1.1←[0m" ←[31m404 Not Found←[0m
←[32mINFO←[0m:     127.0.0.1:56005 - "←[1mOPTIONS /socket.io/?EIO=4&transport=polling&t=ODINIDT HTTP/1.1←[0m" ←[31m400 Bad Request←[0m
←[32mINFO←[0m:     127.0.0.1:56005 - "←[1mGET /socket.io/?EIO=4&transport=polling&t=ODINIDT HTTP/1.1←[0m" ←[31m404 Not Found←[0m

It GET requests are all a bunch of 404 errors.它的 GET 请求都是一堆 404 错误。 I have been testing and researching for hours, and nothing seems to work.我已经测试和研究了几个小时,但似乎没有任何效果。 I have tried the fastapi-socketio package, copying the example exactly, but it is still not connecting.我已经尝试过fastapi-socketio package,完全复制示例,但仍然无法连接。 It appears to be a server issue (as opposed to a client issue), since I get these errors when using this tester .这似乎是一个服务器问题(而不是客户端问题),因为我在使用这个 tester时遇到了这些错误。

When I test using my own client (created using Dart), I get 403 errors:当我使用自己的客户端(使用 Dart 创建)进行测试时,出现 403 错误:

←[32mINFO←[0m:     ('127.0.0.1', 57251) - "WebSocket /socket.io/" 403
←[32mINFO←[0m:     connection failed (403 Forbidden)
←[32mINFO←[0m:     connection closed
←[32mINFO←[0m:     ('127.0.0.1', 57253) - "WebSocket /socket.io/" 403
←[32mINFO←[0m:     connection failed (403 Forbidden)
←[32mINFO←[0m:     connection closed

What am I missing?我错过了什么?

Here is my code:这是我的代码:

from fastapi import FastAPI
from fastapi_socketio import SocketManager
from fastapi.middleware.cors import CORSMiddleware

origins = [
  'https://www.piesocket.com',
  # IMPORTANT: Add other endpoints here
]

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

sio = SocketManager(
  app=app,
  cors_allowed_origins=origins
  )

@sio.on('join')
async def handle_join(sid, *args, **kwargs):
  print('Emitting...')
  await sio.emit('test', 'Success!')
  print('Success!')

@sio.on('connect')
async def test(sid, *args, **kwargs):
  print('Emitting...')
  await sio.emit('test', 'Success!')
  print('Success!')

@sio.on('test')
async def test(sid, *args, **kwargs):
    await sio.emit('hey', 'joe')

This appears to be similar to this issue and this issue , but it is in Python instead of JavaScript.这似乎与此问题此问题类似,但它位于 Python 而不是 JavaScript 中。

After doing a ton of research, I finally found the answer, and I hope to save others some time by answering it here.经过大量研究,我终于找到了答案,我希望通过在这里回答来节省其他人的时间。 It turns out, I needed to create a socket app:事实证明,我需要创建一个套接字应用程序:

socket_app = socketio.ASGIApp(sio)

Then mount that to my main app at the end:然后在最后将其安装到我的主应用程序:

app.mount('/', socket_app)

Here is the full code:这是完整的代码:

import socketio
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

origins = [
  'https://www.piesocket.com',
  # IMPORTANT: Add other endpoints here
]

app = FastAPI()

app.add_middleware(
  CORSMiddleware,
  allow_origins=origins,
  allow_credentials=True,
  allow_methods=["*"],
  allow_headers=["*"],
)
    
sio = socketio.AsyncServer(
  async_mode='asgi',
  cors_allowed_origins=origins
  )
socket_app = socketio.ASGIApp(sio)

@sio.on('disconnect')
def test_disconnect(sid):
  print('Client disconnected')

@sio.on('connect')
async def connection(sid, message):
  print('Connected!')
  await sio.emit('Connected!?')

@sio.on('test')
async def test(sid, message):
  print(f'Received data from {sid}: {message}')
  await sio.emit('It worked!')

app.mount('/', socket_app)

To run the server, in the command line (and probably terminal as well), change the directory to the folder this file is in, then run this command:要运行服务器,在命令行(也可能是终端)中,将目录更改为该文件所在的文件夹,然后运行以下命令:

uvicorn main:app --reload

Just replace "main" with the name of the Python file without the .py .只需将“main”替换为不带.py的 Python 文件的名称即可。

For basic testing, I used this tool .对于基本测试,我使用了这个工具 The default URL is http://localhost:8080 , so be sure to replace the 8080 with the port number your running server is using (probably 8000 ), then click Connect .默认的 URL 是http://localhost:8080 ,因此请务必将8080替换为您正在运行的服务器正在使用的端口号(可能是8000 ),然后单击Connect

I was able to solve this based on this comment on GitHub , which I found from here .我能够根据我从这里找到的GitHub 上的评论解决这个问题。

If anyone has any other suggestions or improvements, I'm definitely open to them!如果有人有任何其他建议或改进,我绝对愿意接受他们!

I think I have an idea of why it's not working.我想我知道它为什么不起作用。 You put in your Flask app:你把你的 Flask 应用程序:

app = Flask( name , static_folder="../front/build", static_url_path="/") app = Flask(名称, static_folder="../front/build", static_url_path="/")

which is saying to have the static path as the root path.也就是说将 static 路径作为根路径。 In other words, if there's not an explicit route for it in your app, then it'll try to find and serve a file from../front/build.换句话说,如果您的应用程序中没有明确的路由,那么它会尝试从../front/build..

This would also explain the 502 - Bad Gateway error in your nginx log.这也可以解释 nginx 日志中的 502 - Bad Gateway 错误。

EDIT: I have tested this theory and it seems to not have affected anything.编辑:我已经测试了这个理论,它似乎没有影响任何东西。 However, now I see that you just did然而,现在我看到你刚刚做了

sio = SocketIO() sio = SocketIO()

without passing in app, which could be another reason for why it's not working.没有传入应用程序,这可能是它不起作用的另一个原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM