首页 > 其他分享 >fastapi socketio http cros solved

fastapi socketio http cros solved

时间:2023-01-28 19:56:22浏览次数:42  
标签:username http fastapi app request cros session import

D:\code_gitee\fastapi-socketio-example-main\fastapi-socketio-example-main\app.py


import os
import pathlib
import secrets
import time
from typing import Optional

import socketio
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.param_functions import Cookie, Depends
from fastapi.params import Form
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from starlette.middleware.sessions import SessionMiddleware
from starlette.requests import Request
from starlette.responses import HTMLResponse, JSONResponse, RedirectResponse, Response

SECRET_KEY = os.environ.get("SECRET_KEY", "ef4ac4e2a33e4d9e0bb34200349e3544")

templates = Jinja2Templates(directory=pathlib.Path(__file__).parent / "templates")


fake_users_db = {
    "johndoe": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "[email protected]",
        "hashed_password": "fakehashedsecret",
        "disabled": False,
    },
    "alice": {
        "username": "alice",
        "full_name": "Alice Wonderson",
        "email": "[email protected]",
        "hashed_password": "123",
        "disabled": True,
    },
}


class RequiresLoginException(Exception):
    pass


app = FastAPI()
sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins=[])
app.mount("/ws", socketio.ASGIApp(sio))
app.add_middleware(SessionMiddleware, secret_key=SECRET_KEY)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
app.mount(
    "/static",
    StaticFiles(directory=pathlib.Path(__file__).parent / "templates"),
    name="static",
)


# This is not really required for simple use case, but if we have a lot views
# and want to protect them, a common redirect logic is convenient.
@app.exception_handler(RequiresLoginException)
async def exception_handler(*args, **kwargs) -> Response:
    return RedirectResponse(url="/", status_code=303)


def verify_session_id(request: Request, session_id: Optional[str] = Cookie(...)):
    """Verify the session_id in the fake db.
    If it doesn't exist raise an exception to redirect to Login page"""
    username = request.session.get(session_id)
    if username not in fake_users_db:
        # raise an exception so that we can redirect to the login
        # if there's no `session_id`` passed or wrong `session_id`` is given
        raise RequiresLoginException
    return username


@app.get("/view")
async def view(request: Request, username: str = Depends(verify_session_id)):
    await sio.emit("message", "hello universe")
    return templates.TemplateResponse(
        "view.html",
        {
            "request": request,
            "current_user": username,
            "start_time": request.session.get("start_time", int(time.time())),
            "PORT": os.environ.get("PORT", 8000),
        },
    )


@app.get("/")
def index(request: Request):
    # if there's some session, the user may likely be logged in
    # try redirecting to the /view
    if request.session:
        return RedirectResponse(url="/view", status_code=303)
    return templates.TemplateResponse("index.html", {"request": request})


@app.post("/login")
async def login(request: Request, username: str = Form(...), password: str = Form(...)):
    """Get `username` and `password` from form data and authenticate the user
    If username doesn't exist, redirect to Login page.
    Else continue to `/view` page
    """
    # for simplicity we will only check the `username`` exists
    # we can add a `password` check if required
    if username not in fake_users_db:
        response = RedirectResponse(url="/", status_code=303)
        return response
    # why we need to set the status_code to `303` can be seen in the below git issue comment
    # https://github.com/encode/starlette/issues/632#issuecomment-527258349
    response = RedirectResponse(url="/view", status_code=303)
    session_id = secrets.token_hex(16)
    request.session.update(
        {
            session_id: username,
            "start_time": int(time.time()),
            "username": username,
        }
    )
    response.set_cookie("session_id", session_id)
    return response


@app.get("/logout", name="logout")
async def logout(request: Request, username: str = Depends(verify_session_id)):
    """Logout and redirect to Login screen"""
    request.session.clear()
    response = RedirectResponse(url="/", status_code=303)
    response.set_cookie("session_id", None)
    await sio.emit("logout", username)
    return response

@app.get('/student')
async def student():
    return {'data':'alice'}

@sio.event
async def connect(sid, environ):
    session = environ["asgi.scope"]["session"]
    await sio.emit("new user", session)


@sio.event
async def message(sid, data):
    await sio.emit("message", data, room=sid)

@sio.on('join')
async def ping_message(sid,data):
    print(data)
    await sio.emit("join", 'hello!~~ from server', room=sid)



D:\code_gitee\fastapi-socketio-example-main\fastapi-socketio-example-main\main.py

import uvicorn
if __name__ == '__main__':
    uvicorn.run("app:app",host="127.0.0.1", port=9998, reload=True)

D:\code_gitee\fastapi-socketio-example-main\fastapi-socketio-example-main\templates\index.html

<html>

<head>
    <title>Index</title>
    <style>
    </style>
</head>

<body>
    <div class="form-center">
        <form action="/login" method="post">
            <input type="text" name="username" placeholder="username" required>
            <br/> <br/>
            <input type="password" name="password" placeholder="password" required>
            <br/> <br/>
            <input type="submit" value="Login">
        </form>
    </div>
</body>

</html>

D:\code_gitee\fastapi-socketio-example-main\fastapi-socketio-example-main\templates\view.html

<html>

<head>
    <title>View</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.4.0/socket.io.js" integrity="sha512-nYuHvSAhY5lFZ4ixSViOwsEKFvlxHMU2NHts1ILuJgOS6ptUmAGt/0i5czIgMOahKZ6JN84YFDA+mCdky7dD8A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
    <p>Hello {{ current_user }}</p>
    <span id='ct'></span>
    <br/>
    <button type="button"><a id="logoutBtn" href="{{ url_for('logout') }}" style="text-decoration: none;">Logout</a></button>
    <br />
    <i>Note</i> <br/>
    This msg box is just a convenient way if the web socket works [for testing]
    <br />
    <input id="textInput" placeholder="message">
    <button id="sendBtn">Send</button>

    <ul>
        
    </ul>

</body>
<script defer type="text/javascript">
    const startTime = {{ start_time }}
    const currentUser = '{{ current_user }}'
    const PORT = '{{ PORT }}'
    function display_c() {
        var refresh = 1000;
        mytime = setTimeout('display_ct()', refresh)
    }

    function display_ct() {
        var x = new Date()
        document.getElementById('ct').innerHTML = x;
        display_c();
    }

    // Support TLS-specific URLs, when appropriate.
        if (window.location.protocol == "https:") {
            var ws_scheme = "wss://";
        } else {
            var ws_scheme = "ws://"
        };

    const socket = io(ws_scheme + location.host, {path: '/ws/socket.io/'});

    socket.on('new user', data => {
        socket.user = data.username
        console.log({ data });
    });

    socket.on('message', text => {
        const el = document.createElement('li');
        el.innerHTML = text + socket.user;
        document.querySelector('ul').appendChild(el);
    });


    document.getElementById('sendBtn').onclick = () => {
        const text = document.getElementById('textInput').value;
        socket.emit('message', text)
    }

    const logoutBtn = document.getElementById('logoutBtn')

    socket.on('logout', userName => {
        if ( currentUser === userName) {
            socket.disconnect();
            logoutBtn.click();
        }
    });

    display_ct();
</script>
</html>

标签:username,http,fastapi,app,request,cros,session,import
From: https://www.cnblogs.com/zhuoss/p/17071171.html

相关文章