Commit f89b4c0b authored by vertighel's avatar vertighel
Browse files

Unk

parent aa9e23d5
Loading
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -24,6 +24,36 @@ app.register_blueprint(api_blueprint, url_prefix='/api')
app.register_blueprint(web_blueprint, url_prefix='/web')  # Added Web Blueprint
app.register_blueprint(viewer_blueprint, url_prefix='/api')


class _WebSocketCloseRaceMiddleware:
    """Turns a known Quart teardown race into a clean log line.

    When a client abandons a WebSocket without a clean close handshake
    (page reload, tab close, network blip), Quart's own cancel_tasks()
    can end up sending a second 'websocket.close' after the first one
    already went out, and uvicorn raises RuntimeError for it. Harmless
    since switching off wsproto (the client still gets disconnected and
    noctua's ws-client.js reconnects on its own) but without this it
    surfaces as uvicorn's raw "ERROR: Exception in ASGI application" +
    full traceback, indistinguishable in the logs from an actual bug.
    """

    def __init__(self, app):
        self.app = app

    async def __call__(self, scope, receive, send):
        try:
            await self.app(scope, receive, send)
        except RuntimeError as e:
            if scope.get("type") == "websocket" and "after sending 'websocket.close'" in str(e):
                log.error(f"WebSocket: double-close race during teardown ({e})")
                return
            raise


app = _WebSocketCloseRaceMiddleware(app)


def _serve(ws):
    """Run uvicorn with the given websocket implementation until Ctrl-C."""