Skip to content

trading_agent.gateway.routes.frontend_routes

Serves the built web page, falling back to index.html for the page's own addresses.

The web page is a single-page React application: addresses such as /chat/main are handled in the browser, so the server answers each of them with index.html. Files the build produced, such as scripts and styles, are served as they are. Addresses under /api, /ws and /hooks are never answered with the page, so a mistyped API address gets a clear 404.

This route needs no access token: the page itself holds no data, and every request it makes for data carries the token.

Typical usage example:

application.include_router(FrontendRoutes(Path('frontend/dist')).router())

FrontendRoutes

FrontendRoutes(frontend_directory)

The catch-all route for the web page; it must be the last router added.

Creates the route.

Parameters:

Name Type Description Default
frontend_directory Path

The Vite build output folder.

required
Source code in src/trading_agent/gateway/routes/frontend_routes.py
def __init__(self, frontend_directory: Path):
    """Creates the route.

    Args:
        frontend_directory (Path): The Vite build output folder.
    """
    self._frontend_directory = frontend_directory.resolve()

router

router()

Builds the router holding the catch-all route.

Returns:

Type Description
APIRouter

The router.

Source code in src/trading_agent/gateway/routes/frontend_routes.py
def router(self) -> fastapi.APIRouter:
    """Builds the router holding the catch-all route.

    Returns:
        fastapi.APIRouter: The router.
    """
    router = fastapi.APIRouter()
    router.add_api_route(
        '/{path:path}',
        self.serve,
        methods=[
            'GET',
        ],
        include_in_schema=False,
    )
    return router

serve

serve(path)

Serves a built file, or index.html for any other page address.

Parameters:

Name Type Description Default
path str

The requested path without the leading slash.

required

Returns:

Type Description
Response

The file, index.html, or a page explaining that the web page is not built.

Raises:

Type Description
HTTPException

The address is under /api, /ws or /hooks (status 404).

Source code in src/trading_agent/gateway/routes/frontend_routes.py
def serve(self, path: str) -> fastapi.responses.Response:
    """Serves a built file, or index.html for any other page address.

    Args:
        path (str): The requested path without the leading slash.

    Returns:
        fastapi.responses.Response: The file, index.html, or a page explaining that the web page is not built.

    Raises:
        fastapi.HTTPException: The address is under /api, /ws or /hooks (status 404).
    """
    first_part = path.split('/', 1)[0]
    if first_part in _RESERVED_PREFIXES:
        raise fastapi.HTTPException(status_code=404, detail='Not found')
    index = self._frontend_directory / 'index.html'
    if not index.is_file():
        return fastapi.responses.HTMLResponse(
            _NOT_BUILT_PAGE, status_code=503
        )
    if path:
        candidate = (self._frontend_directory / path).resolve()
        inside = candidate.is_relative_to(self._frontend_directory)
        if inside and candidate.is_file():
            return fastapi.responses.FileResponse(
                candidate, headers=self._cache_headers(path)
            )
    return fastapi.responses.FileResponse(
        index,
        headers={
            'Cache-Control': 'no-cache',
        },
    )