FastApi教程|Web套接字

发表时间:2020-03-09

您可以将 WebSockets FastAPI 一起 使用

WebSockets客户端

在生产中

在您的生产系统中,您可能已经使用现代框架(如React,Vue.js或Angular)创建了前端。

为了使用WebSockets与您的后端进行通信,您可能会使用前端的实用程序。

或者,您可能有一个本机移动应用程序,以本机代码直接与WebSocket后端通信。

或者,您可能还有任何其他与WebSocket端点进行通信的方式。


但是对于本示例,我们将使用一个非常简单的HTML文档以及一些JavaScript,这些文档都放在一个长字符串中。

当然,这并不是最佳选择,您不会将其用于生产。

在生产中,您将具有上述选择之一。

但这是专注于WebSockets服务器端并提供有效示例的最简单方法:

from fastapi import FastAPI, WebSocket
from fastapi.responses import HTMLResponse

app = FastAPI()

html = """
<!DOCTYPE html>
<html>
    <head>
        <title>Chat</title>
    </head>
    <body>
        <h1>WebSocket Chat</h1>
        <form action="" onsubmit="sendMessage(event)">
            <input type="text" id="messageText" autocomplete="off"/>
            <button>Send</button>
        </form>
        <ul id='messages'>
        </ul>
        <script>
            var ws = new WebSocket("ws://localhost:8000/ws");
            ws.onmessage = function(event) {
                var messages = document.getElementById('messages')
                var message = document.createElement('li')
                var content = document.createTextNode(event.data)
                message.appendChild(content)
                messages.appendChild(message)
            };
            function sendMessage(event) {
                var input = document.getElementById("messageText")
                ws.send(input.value)
                input.value = ''
                event.preventDefault()
            }
        </script>
    </body>
</html>
"""


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


@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(f"Message text was: {data}")

创建 websocket

在您的 FastAPI 应用程序中,创建一个 websocket

from fastapi import FastAPI, WebSocket
from fastapi.responses import HTMLResponse

app = FastAPI()

html = """
<!DOCTYPE html>
<html>
    <head>
        <title>Chat</title>
    </head>
    <body>
        <h1>WebSocket Chat</h1>
        <form action="" onsubmit="sendMessage(event)">
            <input type="text" id="messageText" autocomplete="off"/>
            <button>Send</button>
        </form>
        <ul id='messages'>
        </ul>
        <script>
            var ws = new WebSocket("ws://localhost:8000/ws");
            ws.onmessage = function(event) {
                var messages = document.getElementById('messages')
                var message = document.createElement('li')
                var content = document.createTextNode(event.data)
                message.appendChild(content)
                messages.appendChild(message)
            };
            function sendMessage(event) {
                var input = document.getElementById("messageText")
                ws.send(input.value)
                input.value = ''
                event.preventDefault()
            }
        </script>
    </body>
</html>
"""


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


@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(f"Message text was: {data}")

技术细节

您也可以使用 from starlette.websockets import WebSocket

FastAPI WebSocket 直接为开发人员 提供了同样 的便利。 但它直接来自Starlette。

等待消息并发送消息

在WebSocket路由中,您可以 await 发送消息和发送消息。

from fastapi import FastAPI, WebSocket
from fastapi.responses import HTMLResponse

app = FastAPI()

html = """
<!DOCTYPE html>
<html>
    <head>
        <title>Chat</title>
    </head>
    <body>
        <h1>WebSocket Chat</h1>
        <form action="" onsubmit="sendMessage(event)">
            <input type="text" id="messageText" autocomplete="off"/>
            <button>Send</button>
        </form>
        <ul id='messages'>
        </ul>
        <script>
            var ws = new WebSocket("ws://localhost:8000/ws");
            ws.onmessage = function(event) {
                var messages = document.getElementById('messages')
                var message = document.createElement('li')
                var content = document.createTextNode(event.data)
                message.appendChild(content)
                messages.appendChild(message)
            };
            function sendMessage(event) {
                var input = document.getElementById("messageText")
                ws.send(input.value)
                input.value = ''
                event.preventDefault()
            }
        </script>
    </body>
</html>
"""


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


@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(f"Message text was: {data}")

您可以接收和发送二进制,文本和JSON数据。

使用 Depends 和其他

在WebSocket端点中,您可以导入 fastapi 并使用:

  • Depends
  • Security
  • Cookie
  • Header
  • Path
  • Query

它们的工作方式与其他FastAPI端点/ 路径操作相同

from fastapi import Cookie, Depends, FastAPI, Header, WebSocket, status
from fastapi.responses import HTMLResponse

app = FastAPI()

html = """
<!DOCTYPE html>
<html>
    <head>
        <title>Chat</title>
    </head>
    <body>
        <h1>WebSocket Chat</h1>
        <form action="" onsubmit="sendMessage(event)">
            <label>Item ID: <input type="text" id="itemId" autocomplete="off" value="foo"/></label>
            <button onclick="connect(event)">Connect</button>
            <br>
            <label>Message: <input type="text" id="messageText" autocomplete="off"/></label>
            <button>Send</button>
        </form>
        <ul id='messages'>
        </ul>
        <script>
        var ws = null;
            function connect(event) {
                var input = document.getElementById("itemId")
                ws = new WebSocket("ws://localhost:8000/items/" + input.value + "/ws");
                ws.onmessage = function(event) {
                    var messages = document.getElementById('messages')
                    var message = document.createElement('li')
                    var content = document.createTextNode(event.data)
                    message.appendChild(content)
                    messages.appendChild(message)
                };
            }
            function sendMessage(event) {
                var input = document.getElementById("messageText")
                ws.send(input.value)
                input.value = ''
                event.preventDefault()
            }
        </script>
    </body>
</html>
"""


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


async def get_cookie_or_client(
    websocket: WebSocket, session: str = Cookie(None), x_client: str = Header(None)
):
    if session is None and x_client is None:
        await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
    return session or x_client


@app.websocket("/items/{item_id}/ws")
async def websocket_endpoint(
    websocket: WebSocket,
    item_id: int,
    q: str = None,
    cookie_or_client: str = Depends(get_cookie_or_client),
):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(
            f"Session Cookie or X-Client Header value is: {cookie_or_client}"
        )
        if q is not None:
            await websocket.send_text(f"Query parameter q is: {q}")
        await websocket.send_text(f"Message text was: {data}, for item ID: {item_id}")

信息

在WebSocket中,引发并没有什么意义 HTTPException 。 因此最好直接关闭WebSocket连接。

您可以使用 规范中定义 有效代码中的 结束代码 。

将来, WebSocketException 您将可以 raise 从任何地方进行操作,并为其添加异常处理程序。 这取决于 Starlette中 的 PR#527

更多信息

要了解有关这些选项的更多信息,请查看Starlette的文档以了解:

  • WebSocket
  • 基于类的WebSocket处理

测试

如果文件名为 main.py ,则使用以下命令运行应用程序:

uvicorn main:app --reload

http://127.0.0.1:8000 打开浏览器 。

您将看到一个简单的页面,如下所示:

您可以在输入框中键入消息并发送:

带有WebSockets 的 FastAPI 应用程序将响应:

您可以发送(和接收)许多消息:

它们都将使用相同的WebSocket连接。

文章来源互联网,如有侵权,请联系管理员删除。邮箱:417803890@qq.com / QQ:417803890

微配音

Python Free

邮箱:417803890@qq.com
QQ:417803890

皖ICP备19001818号
© 2019 copyright www.pythonf.cn - All rights reserved

微信扫一扫关注公众号:

联系方式

Python Free