123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- import asyncio
- import urllib.parse
- from pathlib import Path
- from typing import Dict
- from fastapi import FastAPI, Request
- from fastapi.middleware.gzip import GZipMiddleware
- from fastapi.responses import FileResponse
- from fastapi.staticfiles import StaticFiles
- from fastapi_socketio import SocketManager
- from . import binding, globals, vue
- from .client import Client, ErrorClient
- from .favicon import create_favicon_routes
- from .helpers import safe_invoke
- from .page import page
- from .task_logger import create_task
- globals.app = app = FastAPI()
- globals.sio = sio = SocketManager(app=app)._sio
- app.add_middleware(GZipMiddleware)
- app.mount("/static", StaticFiles(directory=Path(__file__).parent / 'static'), name='static')
- index_client = Client(page('/')).__enter__()
- error_client = ErrorClient(page(''))
- @app.get('/')
- def index():
- return index_client.build_response()
- @app.get('/_vue/dependencies/{path:path}')
- def vue_dependencies(path: str):
- return FileResponse(path, media_type='text/javascript')
- @app.get('/_vue/components/{name}')
- def vue_dependencies(name: str):
- return FileResponse(vue.js_components[name], media_type='text/javascript')
- @app.on_event('startup')
- def on_startup() -> None:
- globals.state = globals.State.STARTING
- globals.loop = asyncio.get_running_loop()
- create_favicon_routes()
- [safe_invoke(t) for t in globals.startup_handlers]
- create_task(binding.loop())
- globals.state = globals.State.STARTED
- print(f'NiceGUI ready to go on http://{globals.host}:{globals.port}')
- @app.on_event('shutdown')
- def shutdown() -> None:
- globals.state = globals.State.STOPPING
- [safe_invoke(t) for t in globals.shutdown_handlers]
- [t.cancel() for t in globals.tasks]
- globals.state = globals.State.STOPPED
- @app.exception_handler(404)
- async def exception_handler(_: Request, exc: Exception):
- return error_client.build_response(404, str(exc))
- @app.exception_handler(Exception)
- async def exception_handler(_: Request, exc: Exception):
- return error_client.build_response(500, str(exc))
- @sio.on('connect')
- async def handle_connect(sid: str, _) -> None:
- client = get_client(sid)
- client.environ = sio.get_environ(sid)
- sio.enter_room(sid, str(client.id))
- @sio.on('disconnect')
- async def handle_disconnect(sid: str) -> None:
- client = get_client(sid)
- if client.id != 0:
- del globals.clients[client.id]
- @sio.on('event')
- def handle_event(sid: str, msg: Dict) -> None:
- client = get_client(sid)
- with client:
- sender = client.elements.get(msg['id'])
- if sender:
- sender.handle_event(msg)
- @sio.on('javascript_response')
- def handle_event(sid: str, msg: Dict) -> None:
- get_client(sid).waiting_javascript_commands[msg['request_id']] = msg['result']
- def get_client(sid: str) -> Client:
- query_bytes: bytearray = sio.get_environ(sid)['asgi.scope']['query_string']
- query = urllib.parse.parse_qs(query_bytes.decode())
- client_id = int(query['client_id'][0])
- return globals.clients[client_id]
|