Generic Middleware#

blacksmith.PrometheusMetrics, blacksmith.CircuitBreaker, blacksmith.HTTPAddHeadersMiddleware are implementation of the blacksmith.HTTPMiddleware that can be used to create new middlewares.

Note

The middleware pattern is very common on http framework, in blacksmith, this is the same concept.

The middleware is injected after the serialization of the request, before sending the http query, to intercept request and response.

Example of middleware:#

from blacksmith import AsyncHTTPMiddleware, AsyncMiddleware
from blacksmith.domain.model import HTTPRequest, HTTPResponse, HTTPTimeout
from blacksmith.typing import ClientName, Path


class AsyncHTTPPrintMiddleware(AsyncHTTPMiddleware):
    """Inject data in http query on every requests."""

    def __call__(self, next: AsyncMiddleware) -> AsyncMiddleware:
        async def handle(
            req: HTTPRequest,
            client_name: ClientName,
            path: Path,
            timeout: HTTPTimeout,
        ) -> HTTPResponse:
            print(f">>> {req}")
            resp = await next(req, client_name, path, timeout)
            print(f"<<< {resp}")
            return resp

        return handle

Note

blacksmith.AsyncHTTPMiddleware is a base class for all the async middleware, AsyncMiddleware is the signature of the function handle above.

Example of middleware using the synchronous API:#

from blacksmith import SyncHTTPMiddleware, SyncMiddleware
from blacksmith.domain.model import HTTPRequest, HTTPResponse, HTTPTimeout
from blacksmith.typing import ClientName, Path


class SyncHTTPPrintMiddleware(SyncHTTPMiddleware):
    """Inject data in http query on every requests."""

    def __call__(self, next: SyncMiddleware) -> SyncMiddleware:
        def handle(
            req: HTTPRequest, client_name: ClientName, path: Path, timeout: HTTPTimeout
        ) -> HTTPResponse:
            print(f">>> {req}")
            resp = next(req, client_name, path, timeout)
            print(f"<<< {resp}")
            return resp

        return handle