from typing import Annotated import asyncio from datetime import datetime, timedelta from fastapi import FastAPI, Request, Depends from fastapi.responses import HTMLResponse from fastapi.staticfiles import StaticFiles from starlette.templating import Jinja2Templates from jinja2 import Environment, FileSystemLoader from pydantic import BaseModel from utils import get_avatar_urls, get_client_geo from app.tasks import restricted_exec_task templates = Jinja2Templates(directory="templates") app = FastAPI() app.mount("/static", StaticFiles(directory="static"), name="static") @app.get("/", response_class=HTMLResponse) async def index( request: Request, avatar_urls: Annotated[list[str], Depends(get_avatar_urls)], ): static_env = Environment( loader=FileSystemLoader('./static'), autoescape=True ) return templates.TemplateResponse( "index.html", { "request": request, "avatar_urls": avatar_urls, "header": static_env.get_template('/header.html').render(), "footer": static_env.get_template('/footer.html').render() }, ) @app.get("/client_geo", response_class=HTMLResponse) async def client_addr( request: Request, client_geo: Annotated[dict, Depends(get_client_geo)], ): return templates.TemplateResponse( "partials/client_geo.html", {"request": request, "client_geo": client_geo}, ) class RestrictedExecBase(BaseModel): code: str @app.post('/restricted_exec') async def post_restricted_exec( body: RestrictedExecBase ): result = restricted_exec_task.delay(body.code) start_time = datetime.now() while datetime.now() - start_time < timedelta(seconds=5): if result.ready(): return result.get() await asyncio.sleep(0.1) result.revoke(terminate=True, signal='SIGTERM') return [ 'Execution timeout, task revoked' ]