from __future__ import annotations from fastapi import APIRouter, Request from fastapi.responses import HTMLResponse, PlainTextResponse, RedirectResponse, Response from starlette.concurrency import run_in_threadpool from ..dependencies import ServiceDep, SettingsDep from ..security import client_ip from ..web.forms import request_form from ..web.templates_public import _render_api_docs_page, _render_privacy_page, _render_public_home router = APIRouter() @router.get("/", response_class=HTMLResponse, include_in_schema=False) def index(request: Request, settings: SettingsDep) -> str: return _render_public_home(settings, None, client_ip(request, settings)) @router.post("/", response_class=HTMLResponse, include_in_schema=False) async def create_hostname(request: Request, settings: SettingsDep, service: ServiceDep) -> RedirectResponse: await request_form(request, settings) account = await run_in_threadpool(service.create_managed_account) return RedirectResponse(service.dashboard_url(account), status_code=303) @router.get("/healthz", response_class=PlainTextResponse, include_in_schema=False) def healthz() -> str: return "ok" @router.get("/privacy", response_class=HTMLResponse, include_in_schema=False) def privacy(settings: SettingsDep) -> str: return _render_privacy_page(settings) @router.get("/docs", response_class=HTMLResponse, include_in_schema=False) def api_docs(request: Request, settings: SettingsDep) -> str: return _render_api_docs_page(settings, client_ip(request, settings)) @router.get("/robots.txt", response_class=PlainTextResponse, include_in_schema=False) def robots_txt(settings: SettingsDep) -> str: base_url = settings.public_base_url.rstrip("/") admin_path = settings.admin_path.rstrip("/") return "\n".join( [ "User-agent: *", f"Disallow: {admin_path}/", "Disallow: /m/", "Disallow: /api/", "Disallow: /redoc", "Disallow: /openapi.json", f"Sitemap: {base_url}/sitemap.xml", "", ] ) @router.get("/sitemap.xml", include_in_schema=False) def sitemap_xml(settings: SettingsDep) -> Response: base_url = settings.public_base_url.rstrip("/") body = f""" {base_url}/ weekly 1.0 {base_url}/privacy monthly 0.3 """ return Response(body, media_type="application/xml")