diff options
Diffstat (limited to 'fatcat_scholar/web.py')
-rw-r--r-- | fatcat_scholar/web.py | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/fatcat_scholar/web.py b/fatcat_scholar/web.py new file mode 100644 index 0000000..dfebe01 --- /dev/null +++ b/fatcat_scholar/web.py @@ -0,0 +1,79 @@ + +""" +This file is the FastAPI web application. +""" + +from enum import Enum + +from fastapi import FastAPI, APIRouter, Request, Depends +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates +from fastapi.responses import HTMLResponse + +I18N_LANG_DEFAULT = "en" +I18N_LANG_OPTIONS = ["en", "de", "zh"] + +class LangPrefix: + """ + Looks for a two-character language prefix. + + If there is no such prefix, in the future it could also look at the + Accept-Language header and try to infer a language from that, while not + setting the prefix code. + """ + + def __init__(self, request: Request): + self.prefix : str = "" + self.code : str = I18N_LANG_DEFAULT + for lang_option in I18N_LANG_OPTIONS: + if request.url.path.startswith(f"/{lang_option}/"): + self.prefix = f"/{lang_option}" + self.code = lang_option + break + +class ContentNegotiation: + """ + Choses a mimetype to return based on Accept header. + + Intended to be used for RESTful content negotiation from web endpoints to API. + """ + + def __init__(self, request: Request): + self.mimetype = "text/html" + if request.headers.get('accept', '').startswith('application/json'): + self.mimetype = "application/json" + +api = APIRouter() + +@api.get("/", operation_id="get_home") +async def home(request: Request): + return {"endpoints": {"/": "this", "/search": "fulltext search"}} + +@api.get("/search", operation_id="get_search") +async def search(request: Request): + return {"message": "search results would go here, I guess"} + +web = APIRouter() +templates = Jinja2Templates(directory="fatcat_scholar/templates") + +@web.get("/", include_in_schema=False) +async def web_home(request: Request, lang: LangPrefix = Depends(LangPrefix), content: ContentNegotiation = Depends(ContentNegotiation)): + if content.mimetype == "application/json": + return await api_home(request) + return templates.TemplateResponse("home.html", {"request": request}) + +@web.get("/search", include_in_schema=False) +async def web_search(request: Request): + if content.mimetype == "application/json": + return await api_search(request) + return templates.TemplateResponse("search.html", {"request": request}) + +app = FastAPI() + + +app.include_router(web) +for lang_option in I18N_LANG_OPTIONS: + app.include_router(web, prefix=f"/{lang_option}") +app.include_router(api) +app.mount("/static", StaticFiles(directory="fatcat_scholar/static"), name="static") + |