import os import mimetypes from functools import partial from typing import Optional, Mapping from fastapi import Request, Response from fastapi.responses import RedirectResponse from fastapi.responses import PlainTextResponse from fastapi.responses import FileResponse from starlette.background import BackgroundTask from .common import templates def with_redirect( url: str = '/', code: int = 302, **kwargs) -> RedirectResponse: """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. `kwargs` are passed directly to the Response constructor Args: url (str, optional): Target URL, root by default code (int, optional): HTTP response code Returns: FastAPI's RedirectResponse object """ return RedirectResponse( url=url, status_code=code, **kwargs, ) def with_text( content: str, code: int = 200, **kwargs) -> PlainTextResponse: """Return a plain text to the user. `kwargs` are passed directly to the Response constructor Args: content (str): Plain text content code (int, optional): HTTP response code Returns: FastAPI's PlainTextResponse object """ return PlainTextResponse( content=content, status_code=code, **kwargs, ) def with_tmpl( name: str, request: Request, code: int = 200, headers: Optional[Mapping[str, str]] = None, background: Optional[BackgroundTask] = None, **context) -> Response: """Render a Jinja2 template and return Response object. `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`) Args: name (str): Template filename request (Request): FastAPI request object code (int, optional): HTTP response code headers (Optional[Mapping[str, str]], optional): Additional headers, passed to the Response constructor background (Optional[BackgroundTask], optional): Background task, passed to the Response constructor Returns: FastAPI's TemplateResponse object """ return templates.TemplateResponse( name=name, context={ 'request': request, **context, }, status_code=code, headers=headers, background=background, ) def with_file( path: os.PathLike, mime: Optional[str] = None, code: int = 200, **kwargs) -> FileResponse: """Send the file specified in `path` automatically guessing its mimetype if `mime` is None. `kwargs` are passed directly to the Response constructor Args: path (os.PathLike): File path mime (Optional[str], optional): File mimetype code (int, optional): HTTP response code Returns: FastAPI's FileResponse object """ return FileResponse( path=path, media_type=( mime or mimetypes.guess_type(path)[0] ), status_code=code, **kwargs, ) # Aliases with_template = with_tmpl with_redirect_302 = partial( with_redirect, code=302, ) with_redirect_307 = partial( with_redirect, code=307, )