Skip to content

tzelleke/aws-sam-fastapi

Repository files navigation

AWS SAM FastAPI app

This is a demo project that deploys a FastAPI application to AWS Lambda using AWS SAM.

The frontend of the application is a Vue 3 single-page application that is served from the root path of the FastAPI backend.

The backend also includes Powertools for AWS Lambda for enhanced logging and tracing in AWS.

Poetry is used for Python dependency management.

You can view the live version at:

https://3digtt1sjd.execute-api.eu-central-1.amazonaws.com/Prod/docs.

Project layout

The SAM CLI builds and packages the app from the contents of the /src directory as specified in template.yaml in the project root.

The /src directory contains the FastAPI app in /src/app and a requirements.txt file that specifies the Python runtime dependencies.

Since the frontend is served from FastAPI, frontend build artifacts are generated in /src/frontend in order to be included in the SAM build.

The /frontend folder contains the Vue 3 frontend as a self-contained project created with npm create vue@latest.

/frontend            # Vue 3 frontend
/src
  /app
    main.py          # FastAPI app
  /frontend          # frontend build artifacts
  requirements.txt   # Python dependencies
/tests

Frontend integration

The frontend is a Vite-powered Vue 3 single-page application.

Frontend build

The build npm script in /frontend/package.json is configured to output the build artifacts to /src/frontend so that they can be included in the SAM build.

You can run the frontend build manually with:

cd frontend
npm run build

Frontend runtime integration

The frontend is served from the root path of the FastAPI app.

This runtime integration is implemented in /src/app/frontend.py:

def mount_frontend(app: FastAPI, build_dir: Path, assets_folder="assets") -> FastAPI:
    """Serves a frontend application at the root path `/`

    Args:
        app: FastAPI application instance
        build_dir: Frontend build directory
            (generated by `yarn build` or `npm run build`)

    Returns:
        FastAPI: instance with the frontend application mounted
    """
    app.mount(
        f"/{assets_folder}/",
        StaticFiles(directory=(build_dir / assets_folder), html=True),
        name="assets",
    )

    templates = Jinja2Templates(directory=build_dir)

    @app.get("/{_full_path:path}", include_in_schema=False)
    async def serve_frontend(request: Request, _full_path: str) -> HTMLResponse:
        return templates.TemplateResponse("index.html", {"request": request})

    return app

Therein, the index.html file is served from the root path / as a Jinja2Templates.TemplateResponse and the frontend build assets are statically mounted at /assets/ using FastAPI/Starlette's StaticFiles class.

The approach is taken from this answer on StackOverflow: https://stackoverflow.com/a/70065066/733291.

Python dependency management with Poetry

This project uses Poetry for dependency management.

Poetry organize dependencies in groups and this project distinguishes following groups:

  • main - dependencies for the FastAPI app
  • dev - dependencies specifically for development
  • test - dependencies for running tests with pytest
  • code-qa - dependencies for code quality checks

The main group is the only one that is needed for the deployed app.

Therefore, the requirements.txt file in the /src directory is a direct dependency of the poetry.lock file.

As such, it is generated from the poetry.lock file with only dependencies from the main group using the poetry export command.

This happens automatically as part of pre-commit hooks (see /pre-commit-config.yaml).

You can update it manually with:

poetry export -f requirements.txt --only main --output src/requirements.txt --without-hashes

Local development

During development, you can run the frontend build and the backend concurrently in separate processes.

Frontend

Start the frontend build in watch mode:

cd frontend

npm install

# runs the frontend build with --watch flag
npm run watch

Backend

Start the FastAPI app in dev mode using uvicorn:

poetry install

cd src

python -m app.main

Deployment to AWS

Deploy from local machine

You can manually deploy the app to AWS using the AWS SAM CLI.

sam build --use-container
sam deploy --guided

Deploy from CD pipeline

You can also deploy the app from a GitHub Actions workflow to AWS.

sam pipeline init --bootstrap

This command will initiate an interactive assistant that guides you through creating the necessary AWS infrastructure resources.