Skip to content

Instantly share code, notes, and snippets.

@evnchn
Created March 14, 2025 13:42
Show Gist options
  • Select an option

  • Save evnchn/bcd713061c77e9071dc78db34e7724ea to your computer and use it in GitHub Desktop.

Select an option

Save evnchn/bcd713061c77e9071dc78db34e7724ea to your computer and use it in GitHub Desktop.
# Pieced together from:
# (1) https://github.com/Vizonex/Winloop?tab=readme-ov-file#how-to-use-winloop-with-fastapi
# (2) https://www.reddit.com/r/nicegui/comments/1dlx3or/fastapi_nicegui_integration/
# (3) https://github.com/pgjones/hypercorn?tab=readme-ov-file#quickstart
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
import winloop
from hypercorn.config import Config
from hypercorn.asyncio import serve
import asyncio
import datetime
from nicegui import ui
app = FastAPI()
@app.on_event("startup")
def make_assertion():
# Check to make sure that we bypassed the original eventloop Policy....
assert isinstance(asyncio.get_event_loop_policy(), winloop.EventLoopPolicy)
# not WinLoopPolicy. (1) is outdated. I'll see when I can update it.
@app.get("/test")
async def test_get_request():
return HTMLResponse("<html><body><h1>FAST API WORKS WITH WINLOOP!</h1></body></html>")
@app.get("/date")
def test_dynamic_response():
return str(datetime.datetime.now())
@app.get("/str")
def test_str_response():
return str(asyncio.get_event_loop_policy())
def init(fastapi_app: FastAPI) -> None:
@ui.page("/")
def index():
ui.label("Hello, world!") #
ui.label(str(asyncio.get_event_loop_policy()))
ui.run_with(
fastapi_app,
storage_secret='hmm',
)
TRY_HTTP2_TLS = False
TRY_HTTP3 = False
if __name__ == "__main__":
init(app)
winloop.install()
config = Config()
config.bind = ["127.0.0.1:4004"]
if TRY_HTTP2_TLS:
# NOTE: WebSocket fails 3 times and works the 4th time?
# Invalid websocket upgrade (further occurrences of this error will be logged with level INFO)
config.certfile = r"C:\Users\User\mycert.crt"
config.keyfile = r"C:\Users\User\mykey.key"
if TRY_HTTP2_TLS and TRY_HTTP3:
# NOTE: this does not work, connection refused?
config.quic_bind = ["127.0.0.1:4099"]
asyncio.run(serve(app, config))
# Conclusion of NiceGUI + WinLoop + Hypercorn:
# HTTP 1.1: Works fine.
# HTTP 2: WebSocket fails 3 times and works the 4th time.
# HTTP 3: Connection refused.
# It's the same without WinLoop.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment