1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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")
|