2023-02-18 21:17:16 +04:00
|
|
|
import os
|
|
|
|
import mimetypes
|
2023-02-20 12:41:29 +04:00
|
|
|
from functools import partial
|
2023-02-18 21:17:16 +04:00
|
|
|
from typing import Optional, Mapping
|
|
|
|
|
2023-02-20 12:41:29 +04:00
|
|
|
from fastapi import Request, Response
|
2023-02-20 12:09:43 +04:00
|
|
|
from fastapi.responses import RedirectResponse
|
|
|
|
from fastapi.responses import PlainTextResponse
|
2023-02-18 21:17:16 +04:00
|
|
|
from fastapi.responses import FileResponse
|
2023-02-20 12:09:43 +04:00
|
|
|
|
2023-02-18 21:17:16 +04:00
|
|
|
from starlette.background import BackgroundTask
|
|
|
|
|
|
|
|
from .common import templates
|
|
|
|
|
|
|
|
|
2023-02-20 12:09:43 +04:00
|
|
|
def with_redirect(
|
|
|
|
url: str = '/',
|
|
|
|
code: int = 302,
|
2023-02-27 19:48:34 +04:00
|
|
|
**kwargs) -> RedirectResponse:
|
2023-02-20 12:41:29 +04:00
|
|
|
"""Return a redirect to the page specified in `url`.
|
|
|
|
By default, code is 302 so method is changed to GET.
|
|
|
|
To leave the same HTTP method, use 307 status code
|
|
|
|
or call `with_redirect_307` function.
|
2023-02-27 19:48:34 +04:00
|
|
|
`kwargs` are passed directly
|
2023-03-06 17:34:13 +04:00
|
|
|
to the Response constructor
|
2023-02-20 12:09:43 +04:00
|
|
|
|
|
|
|
Args:
|
2023-02-20 12:41:29 +04:00
|
|
|
url (str, optional): Target URL, root by default
|
2023-02-20 12:09:43 +04:00
|
|
|
code (int, optional): HTTP response code
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
FastAPI's RedirectResponse object
|
|
|
|
"""
|
|
|
|
|
|
|
|
return RedirectResponse(
|
|
|
|
url=url,
|
|
|
|
status_code=code,
|
2023-02-27 19:48:34 +04:00
|
|
|
**kwargs,
|
2023-02-20 12:09:43 +04:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def with_text(
|
|
|
|
content: str,
|
|
|
|
code: int = 200,
|
2023-02-27 19:48:34 +04:00
|
|
|
**kwargs) -> PlainTextResponse:
|
2023-02-20 12:41:29 +04:00
|
|
|
"""Return a plain text to the user.
|
2023-02-27 19:48:34 +04:00
|
|
|
`kwargs` are passed directly
|
2023-03-06 17:34:13 +04:00
|
|
|
to the Response constructor
|
2023-02-20 12:09:43 +04:00
|
|
|
|
|
|
|
Args:
|
|
|
|
content (str): Plain text content
|
|
|
|
code (int, optional): HTTP response code
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
FastAPI's PlainTextResponse object
|
|
|
|
"""
|
|
|
|
|
|
|
|
return PlainTextResponse(
|
|
|
|
content=content,
|
|
|
|
status_code=code,
|
2023-02-27 19:48:34 +04:00
|
|
|
**kwargs,
|
2023-02-20 12:09:43 +04:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2023-02-18 21:17:16 +04:00
|
|
|
def with_tmpl(
|
|
|
|
name: str,
|
2023-02-20 12:41:29 +04:00
|
|
|
request: Request,
|
2023-02-18 21:17:16 +04:00
|
|
|
code: int = 200,
|
|
|
|
headers: Optional[Mapping[str, str]] = None,
|
|
|
|
background: Optional[BackgroundTask] = None,
|
|
|
|
**context) -> Response:
|
|
|
|
"""Render a Jinja2 template and return Response object.
|
2023-02-22 21:39:50 +04:00
|
|
|
`response_class` parameter is not needed.
|
|
|
|
A small explanation about the `request` function argument:
|
|
|
|
```python
|
|
|
|
from fastapi import Request
|
|
|
|
from . import respond
|
|
|
|
|
|
|
|
@app.get('/')
|
|
|
|
async def main_page(req: Request): # <--
|
|
|
|
return respond.with_tmpl(
|
|
|
|
'index.html',
|
|
|
|
request=req, # <--
|
|
|
|
...
|
|
|
|
)
|
|
|
|
```
|
|
|
|
FastAPI will automatically pass the Request object
|
|
|
|
to your function if you specify
|
|
|
|
the correct type hint (`: Request`)
|
2023-02-18 21:17:16 +04:00
|
|
|
|
|
|
|
Args:
|
|
|
|
name (str): Template filename
|
2023-02-20 12:41:29 +04:00
|
|
|
request (Request): FastAPI request object
|
2023-02-18 21:17:16 +04:00
|
|
|
code (int, optional): HTTP response code
|
|
|
|
headers (Optional[Mapping[str, str]], optional):
|
2023-02-22 21:39:50 +04:00
|
|
|
Additional headers, passed to the Response constructor
|
2023-02-18 21:17:16 +04:00
|
|
|
background (Optional[BackgroundTask], optional):
|
2023-02-22 21:39:50 +04:00
|
|
|
Background task, passed to the Response constructor
|
2023-02-18 21:17:16 +04:00
|
|
|
|
|
|
|
Returns:
|
|
|
|
FastAPI's TemplateResponse object
|
|
|
|
"""
|
|
|
|
|
|
|
|
return templates.TemplateResponse(
|
|
|
|
name=name,
|
2023-02-20 12:41:29 +04:00
|
|
|
context={
|
|
|
|
'request': request,
|
|
|
|
**context,
|
|
|
|
},
|
2023-02-18 21:17:16 +04:00
|
|
|
status_code=code,
|
|
|
|
headers=headers,
|
|
|
|
background=background,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def with_file(
|
|
|
|
path: os.PathLike,
|
|
|
|
mime: Optional[str] = None,
|
|
|
|
code: int = 200,
|
2023-02-27 19:48:34 +04:00
|
|
|
**kwargs) -> FileResponse:
|
2023-02-22 21:39:50 +04:00
|
|
|
"""Send the file specified in `path`
|
|
|
|
automatically guessing its mimetype if `mime` is None.
|
2023-02-27 19:48:34 +04:00
|
|
|
`kwargs` are passed directly
|
2023-03-06 17:34:13 +04:00
|
|
|
to the Response constructor
|
2023-02-18 21:17:16 +04:00
|
|
|
|
|
|
|
Args:
|
|
|
|
path (os.PathLike): File path
|
|
|
|
mime (Optional[str], optional): File mimetype
|
|
|
|
code (int, optional): HTTP response code
|
|
|
|
|
|
|
|
Returns:
|
2023-02-22 21:39:50 +04:00
|
|
|
FastAPI's FileResponse object
|
2023-02-18 21:17:16 +04:00
|
|
|
"""
|
|
|
|
|
|
|
|
return FileResponse(
|
|
|
|
path=path,
|
|
|
|
media_type=(
|
2023-02-27 19:05:57 +04:00
|
|
|
mime or
|
2023-02-18 21:17:16 +04:00
|
|
|
mimetypes.guess_type(path)[0]
|
|
|
|
),
|
|
|
|
status_code=code,
|
2023-02-27 19:48:34 +04:00
|
|
|
**kwargs,
|
2023-02-18 21:17:16 +04:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2023-02-20 12:41:29 +04:00
|
|
|
# Aliases
|
2023-02-18 21:17:16 +04:00
|
|
|
with_template = with_tmpl
|
2023-02-20 12:41:29 +04:00
|
|
|
with_redirect_302 = partial(
|
|
|
|
with_redirect, code=302,
|
|
|
|
)
|
|
|
|
with_redirect_307 = partial(
|
|
|
|
with_redirect, code=307,
|
|
|
|
)
|