Skip to content

Dependencies

Dependencies allow modifying requests before sending.

What Are Dependencies?

A dependency is a function that runs before each request and can modify the request configuration. This is useful for:

  • Adding authentication headers
  • Adding trace IDs
  • Modifying request parameters
  • Logging

Basic Example

from fasthttp import FastHTTP, Depends
from fasthttp.response import Response

app = FastHTTP()


async def add_auth(route, config):
    """Adds authorization token."""
    config.setdefault("headers", {})["Authorization"] = "Bearer my-token"
    return config


@app.get(
    url="https://api.example.com/protected",
    dependencies=[Depends(add_auth)]
)
async def protected_request(resp: Response) -> dict:
    return resp.json()

Dependency Function Signature

A dependency function receives two parameters:

async def my_dependency(route, config):
    # route - information about the request
    # config - request configuration

    # Modify config
    config["headers"]["X-Custom"] = "value"

    # Return modified config
    return config

Route Attributes

route.method      # HTTP method: "GET", "POST", etc.
route.url         # Full request URL
route.params      # Query parameters
route.json        # JSON body
route.data        # Raw data
route.tags        # Request tags

Config Keys

config.get("headers", {})      # Request headers
config.get("timeout", 30.0)    # Timeout in seconds
config.get("allow_redirects", True)

Multiple Dependencies

Dependencies execute in order:

async def add_auth(route, config):
    config.setdefault("headers", {})["Authorization"] = "Bearer token"
    return config


async def add_trace(route, config):
    config.setdefault("headers", {})["X-Trace-ID"] = "123"
    return config


@app.get(
    url="https://api.example.com/data",
    dependencies=[Depends(add_auth), Depends(add_trace)]
)
async def handler(resp: Response) -> dict:
    return resp.json()

Use Cache

Use use_cache to cache expensive operations:

async def get_token(route, config):
    # Expensive operation - fetch from auth server
    token = await fetch_token()
    config["headers"]["Authorization"] = f"Bearer {token}"
    return config


# Token will be obtained once and reused
@app.get(url="/api/data", dependencies=[Depends(get_token, use_cache=True)])
async def handler1(resp): ...


@app.get(url="/api/other", dependencies=[Depends(get_token, use_cache=True)])
async def handler2(resp): ...

Practical Examples

Dynamic Token

import os


async def add_auth(route, config):
    token = os.getenv("API_TOKEN")
    config.setdefault("headers", {})["Authorization"] = f"Bearer {token}"
    return config

Conditional Headers

async def add_api_version(route, config):
    headers = config.setdefault("headers", {})

    if "/v2/" in route.url:
        headers["X-API-Version"] = "v2"
    else:
        headers["X-API-Version"] = "v1"

    return config

Without Depends()

You can omit Depends():

# Both work the same
@app.get(url="/test1", dependencies=[Depends(add_auth)])
async def test1(resp): ...


@app.get(url="/test2", dependencies=[add_auth])
async def test2(resp): ...

Comparison with Middleware

Feature Middleware Dependencies
Global application Yes No
Specific request No Yes
Can modify response Yes No
Simpler to use No Yes