Skip to content

*๏ธโƒฃ

๐Ÿ‘† ๐Ÿ’ช โš™๏ธ ๏ธโƒฃ โฎ๏ธ FastAPI*.

โŽ WebSockets

๐Ÿฅ‡ ๐Ÿ‘† ๐Ÿ’ช โŽ WebSockets:

$ pip install websockets

---> 100%

*๏ธโƒฃ ๐Ÿ‘ฉโ€๐Ÿ’ป

๐Ÿญ

๐Ÿ‘† ๐Ÿญ โš™๏ธ, ๐Ÿ‘† ๐ŸŽฒ โœ”๏ธ ๐Ÿ•ธ โœ โฎ๏ธ ๐Ÿ› ๐Ÿ› ๏ธ ๐Ÿ’– ๐Ÿ˜ฅ, Vue.js โš–๏ธ ๐Ÿ“.

& ๐Ÿ”— โš™๏ธ *๏ธโƒฃ โฎ๏ธ ๐Ÿ‘† ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿ‘† ๐Ÿ”œ ๐ŸŽฒ โš™๏ธ ๐Ÿ‘† ๐Ÿ•ธ ๐Ÿš™.

โš–๏ธ ๐Ÿ‘† ๐Ÿ’ช โœ”๏ธ ๐Ÿ‡ฆ๐Ÿ‡ธ ๐Ÿ“ฑ ๐Ÿˆธ ๐Ÿ‘ˆ ๐Ÿ”— โฎ๏ธ ๐Ÿ‘† *๏ธโƒฃ ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿ”—, ๐Ÿ‡ฆ๐Ÿ‡ธ ๐Ÿ“Ÿ.

โš–๏ธ ๐Ÿ‘† 5๏ธโƒฃ๐Ÿ“† โœ”๏ธ ๐Ÿ™† ๐ŸŽ ๐ŸŒŒ ๐Ÿ”— โฎ๏ธ *๏ธโƒฃ ๐Ÿ”—.


โœ‹๏ธ ๐Ÿ‘‰ ๐Ÿ–ผ, ๐Ÿ‘ฅ ๐Ÿ”œ โš™๏ธ ๐Ÿ“ถ ๐Ÿ™… ๐Ÿ•ธ ๐Ÿ“„ โฎ๏ธ ๐Ÿ•ธ, ๐ŸŒ ๐Ÿ”˜ ๐Ÿ“ ๐ŸŽป.

๐Ÿ‘‰, โ†—๏ธ, ๐Ÿšซ โš– & ๐Ÿ‘† ๐Ÿšซ๐Ÿ”œ โš™๏ธ โšซ๏ธ ๐Ÿญ.

๐Ÿญ ๐Ÿ‘† ๐Ÿ”œ โœ”๏ธ 1๏ธโƒฃ ๐ŸŽ› ๐Ÿ”›.

โœ‹๏ธ โšซ๏ธ ๐Ÿ™… ๐ŸŒŒ ๐ŸŽฏ ๐Ÿ”› ๐Ÿ’ฝ-๐Ÿš„ *๏ธโƒฃ & โœ”๏ธ ๐Ÿ‘ท ๐Ÿ–ผ:

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 ๐Ÿ”— ๐Ÿช ๐Ÿ‘†, ๐Ÿ‘ฉโ€๐Ÿ’ป. โœ‹๏ธ โšซ๏ธ ๐Ÿ‘Ÿ ๐Ÿ”— โšช๏ธโžก๏ธ ๐Ÿ’ƒ.

โŒ› ๐Ÿ“ง & ๐Ÿ“จ ๐Ÿ“ง

๐Ÿ‘† *๏ธโƒฃ ๐Ÿ›ฃ ๐Ÿ‘† ๐Ÿ’ช 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}")

๐Ÿ‘† ๐Ÿ’ช ๐Ÿ“จ & ๐Ÿ“จ ๐Ÿ’ฑ, โœ, & ๐ŸŽป ๐Ÿ’ฝ.

๐Ÿ”„ โšซ๏ธ

๐Ÿšฅ ๐Ÿ‘† ๐Ÿ“ ๐Ÿ“› main.py, ๐Ÿƒ ๐Ÿ‘† ๐Ÿˆธ โฎ๏ธ:

$ uvicorn main:app --reload

<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

๐Ÿ“‚ ๐Ÿ‘† ๐Ÿ–ฅ http://127.0.0.1:8000.

๐Ÿ‘† ๐Ÿ”œ ๐Ÿ‘€ ๐Ÿ™… ๐Ÿ“ƒ ๐Ÿ’–:

๐Ÿ‘† ๐Ÿ’ช ๐Ÿ†Ž ๐Ÿ“ง ๐Ÿ”ข ๐Ÿ“ฆ, & ๐Ÿ“จ ๐Ÿ‘ซ:

& ๐Ÿ‘† FastAPI ๐Ÿˆธ โฎ๏ธ *๏ธโƒฃ ๐Ÿ”œ ๐Ÿ“จ ๐Ÿ”™:

๐Ÿ‘† ๐Ÿ’ช ๐Ÿ“จ (& ๐Ÿ“จ) ๐Ÿ“š ๐Ÿ“ง:

& ๐ŸŒ ๐Ÿ‘ซ ๐Ÿ”œ โš™๏ธ ๐ŸŽ *๏ธโƒฃ ๐Ÿ”—.

โš™๏ธ Depends & ๐ŸŽ

*๏ธโƒฃ ๐Ÿ”— ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ—„ โšช๏ธโžก๏ธ fastapi & โš™๏ธ:

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

๐Ÿ‘ซ ๐Ÿ‘ท ๐ŸŽ ๐ŸŒŒ ๐ŸŽ FastAPI ๐Ÿ”—/โžก ๐Ÿ› ๏ธ:

from typing import Union

from fastapi import (
    Cookie,
    Depends,
    FastAPI,
    Query,
    WebSocket,
    WebSocketException,
    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>
            <label>Token: <input type="text" id="token" autocomplete="off" value="some-key-token"/></label>
            <button onclick="connect(event)">Connect</button>
            <hr>
            <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 itemId = document.getElementById("itemId")
                var token = document.getElementById("token")
                ws = new WebSocket("ws://localhost:8000/items/" + itemId.value + "/ws?token=" + token.value);
                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)
                };
                event.preventDefault()
            }
            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_token(
    websocket: WebSocket,
    session: Union[str, None] = Cookie(default=None),
    token: Union[str, None] = Query(default=None),
):
    if session is None and token is None:
        raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION)
    return session or token


@app.websocket("/items/{item_id}/ws")
async def websocket_endpoint(
    websocket: WebSocket,
    item_id: str,
    q: Union[int, None] = None,
    cookie_or_token: str = Depends(get_cookie_or_token),
):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(
            f"Session cookie or query token value is: {cookie_or_token}"
        )
        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}")

Info

๐Ÿ‘‰ *๏ธโƒฃ โšซ๏ธ ๐Ÿšซ ๐Ÿค™ โš’ ๐Ÿ”‘ ๐Ÿคš HTTPException, โ†ฉ๏ธ ๐Ÿ‘ฅ ๐Ÿคš WebSocketException.

๐Ÿ‘† ๐Ÿ’ช โš™๏ธ ๐Ÿ“ช ๐Ÿ“Ÿ โšช๏ธโžก๏ธ โ˜‘ ๐Ÿ“Ÿ ๐Ÿ”ฌ ๐Ÿ”ง.

๐Ÿ”„ *๏ธโƒฃ โฎ๏ธ ๐Ÿ”—

๐Ÿšฅ ๐Ÿ‘† ๐Ÿ“ ๐Ÿ“› main.py, ๐Ÿƒ ๐Ÿ‘† ๐Ÿˆธ โฎ๏ธ:

$ uvicorn main:app --reload

<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

๐Ÿ“‚ ๐Ÿ‘† ๐Ÿ–ฅ http://127.0.0.1:8000.

๐Ÿ“ค ๐Ÿ‘† ๐Ÿ’ช โš’:

  • "๐Ÿฌ ๐Ÿ†”", โš™๏ธ โžก.
  • "๐Ÿค" โš™๏ธ ๐Ÿ”ข ๐Ÿ”ข.

Tip

๐Ÿ‘€ ๐Ÿ‘ˆ ๐Ÿ”ข token ๐Ÿ”œ ๐Ÿต ๐Ÿ”—.

โฎ๏ธ ๐Ÿ‘ˆ ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ”— *๏ธโƒฃ & โคด๏ธ ๐Ÿ“จ & ๐Ÿ“จ ๐Ÿ“ง:

๐Ÿšš ๐Ÿ”€ & ๐Ÿ’— ๐Ÿ‘ฉโ€๐Ÿ’ป

๐Ÿ•โ” *๏ธโƒฃ ๐Ÿ”— ๐Ÿ“ช, await websocket.receive_text() ๐Ÿ”œ ๐Ÿคš WebSocketDisconnect โš , โ” ๐Ÿ‘† ๐Ÿ’ช โคด๏ธ โœŠ & ๐Ÿต ๐Ÿ’– ๐Ÿ‘‰ ๐Ÿ–ผ.

from typing import List

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

app = FastAPI()

html = """
<!DOCTYPE html>
<html>
    <head>
        <title>Chat</title>
    </head>
    <body>
        <h1>WebSocket Chat</h1>
        <h2>Your ID: <span id="ws-id"></span></h2>
        <form action="" onsubmit="sendMessage(event)">
            <input type="text" id="messageText" autocomplete="off"/>
            <button>Send</button>
        </form>
        <ul id='messages'>
        </ul>
        <script>
            var client_id = Date.now()
            document.querySelector("#ws-id").textContent = client_id;
            var ws = new WebSocket(`ws://localhost:8000/ws/${client_id}`);
            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>
"""


class ConnectionManager:
    def __init__(self):
        self.active_connections: List[WebSocket] = []

    async def connect(self, websocket: WebSocket):
        await websocket.accept()
        self.active_connections.append(websocket)

    def disconnect(self, websocket: WebSocket):
        self.active_connections.remove(websocket)

    async def send_personal_message(self, message: str, websocket: WebSocket):
        await websocket.send_text(message)

    async def broadcast(self, message: str):
        for connection in self.active_connections:
            await connection.send_text(message)


manager = ConnectionManager()


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


@app.websocket("/ws/{client_id}")
async def websocket_endpoint(websocket: WebSocket, client_id: int):
    await manager.connect(websocket)
    try:
        while True:
            data = await websocket.receive_text()
            await manager.send_personal_message(f"You wrote: {data}", websocket)
            await manager.broadcast(f"Client #{client_id} says: {data}")
    except WebSocketDisconnect:
        manager.disconnect(websocket)
        await manager.broadcast(f"Client #{client_id} left the chat")

๐Ÿ”„ โšซ๏ธ ๐Ÿ‘…:

  • ๐Ÿ“‚ ๐Ÿ“ฑ โฎ๏ธ ๐Ÿ“š ๐Ÿ–ฅ ๐Ÿ“‘.
  • โœ ๐Ÿ“ง โšช๏ธโžก๏ธ ๐Ÿ‘ซ.
  • โคด๏ธ ๐Ÿ” 1๏ธโƒฃ ๐Ÿ“‘.

๐Ÿ‘ˆ ๐Ÿ”œ ๐Ÿคš WebSocketDisconnect โš , & ๐ŸŒ ๐ŸŽ ๐Ÿ‘ฉโ€๐Ÿ’ป ๐Ÿ”œ ๐Ÿ“จ ๐Ÿ“ง ๐Ÿ’–:

Client #1596980209979 left the chat

Tip

๐Ÿ“ฑ ๐Ÿ”› โญ & ๐Ÿ™… ๐Ÿ–ผ ๐ŸŽฆ โ” ๐Ÿต & ๐Ÿ“ป ๐Ÿ“ง ๐Ÿ“š *๏ธโƒฃ ๐Ÿ”—.

โœ‹๏ธ โœ”๏ธ ๐Ÿคฏ ๐Ÿ‘ˆ, ๐ŸŒ ๐Ÿต ๐Ÿ’พ, ๐Ÿ‘ ๐Ÿ“‡, โšซ๏ธ ๐Ÿ”œ ๐Ÿ•ด ๐Ÿ‘ท โช ๐Ÿ› ๏ธ ๐Ÿƒ, & ๐Ÿ”œ ๐Ÿ•ด ๐Ÿ‘ท โฎ๏ธ ๐Ÿ‘ ๐Ÿ› ๏ธ.

๐Ÿšฅ ๐Ÿ‘† ๐Ÿ’ช ๐Ÿ•ณ โฉ ๐Ÿ› ๏ธ โฎ๏ธ FastAPI โœ‹๏ธ ๐Ÿ‘ˆ ๐ŸŒ– ๐Ÿ‹๏ธ, ๐Ÿ•โ€๐Ÿฆบ โœณ, โœณ โš–๏ธ ๐ŸŽ, โœ… ๐Ÿ—œ/๐Ÿ“ป.

๐ŸŒ… โ„น

๐Ÿ’ก ๐ŸŒ… ๐Ÿ”ƒ ๐ŸŽ›, โœ… ๐Ÿ’ƒ ๐Ÿงพ: