Подключить свой HTTP-обработчик#

Собственный обработчик нужен, если готовые адаптеры не поддерживают вашу сетевую библиотеку. Он принимает полностью подготовленный zapros.Request и возвращает zapros.Response.

# examples/docs/integration_custom_handler.py
class UrllibHandler(BaseHandler):
    def handle(self, request: Request) -> Response:
        target = str(request.url)
        if urlsplit(target).scheme not in {"http", "https"}:
            raise ValueError("UrllibHandler accepts only HTTP URLs")
        native_request = UrlRequest(  # noqa: S310 - the scheme is checked above
            target,
            data=request.body if isinstance(request.body, bytes) else None,
            headers=dict(request.headers.items()),
            method=request.method,
        )
        with urlopen(native_request) as native_response:  # noqa: S310
            return Response(
                native_response.status,
                native_response.headers.items(),
                content=native_response.read(),
                request=request,
            )


@dataclass(frozen=True, slots=True)
class Message:
    id: int
    subject: str


@dataclass(frozen=True, slots=True)
class GetMessage(HttpOperation[Message]):
    __http__ = Http.get("/messages/42")


class MessageApi(SyncApi):
    message = op(GetMessage)


def load_message(base_url: str) -> Message:
    with Client(base_url=base_url, handler=UrllibHandler()) as client:
        return MessageApi(client).message()
Файл целиком
"""Runnable custom Zapros handler example for the documentation."""

from __future__ import annotations

from dataclasses import dataclass
from urllib.request import Request as UrlRequest
from urllib.request import urlopen
from urllib.parse import urlsplit

from zapros import BaseHandler, Request, Response

from eazy_sdk import Client, Http, HttpOperation, SyncApi, op

from .guide_site import GuideSite, guide_origin


# docs:integration-custom-handler:start
# examples/docs/integration_custom_handler.py
class UrllibHandler(BaseHandler):
    def handle(self, request: Request) -> Response:
        target = str(request.url)
        if urlsplit(target).scheme not in {"http", "https"}:
            raise ValueError("UrllibHandler accepts only HTTP URLs")
        native_request = UrlRequest(  # noqa: S310 - the scheme is checked above
            target,
            data=request.body if isinstance(request.body, bytes) else None,
            headers=dict(request.headers.items()),
            method=request.method,
        )
        with urlopen(native_request) as native_response:  # noqa: S310
            return Response(
                native_response.status,
                native_response.headers.items(),
                content=native_response.read(),
                request=request,
            )


@dataclass(frozen=True, slots=True)
class Message:
    id: int
    subject: str


@dataclass(frozen=True, slots=True)
class GetMessage(HttpOperation[Message]):
    __http__ = Http.get("/messages/42")


class MessageApi(SyncApi):
    message = op(GetMessage)


def load_message(base_url: str) -> Message:
    with Client(base_url=base_url, handler=UrllibHandler()) as client:
        return MessageApi(client).message()
# docs:integration-custom-handler:end


def main() -> None:
    with guide_origin(GuideSite()) as base_url:
        message = load_message(base_url)
    print(f"message: {message.id} {message.subject}")


if __name__ == "__main__":
    main()
message: 42 План на пятницу

Метод handle(...) не должен сам повторять запрос, переходить по Location, менять cookies или перекодировать готовое тело. Эти решения принимает исполнитель Eazy SDK. Асинхронный вариант реализует AsyncBaseHandler.ahandle(...) и передаётся в AsyncClient.

Если обработчик владеет сетевым ресурсом, реализуйте close() либо aclose(). По умолчанию клиент вызывает его при закрытии. Для внешнего ресурса передайте owns_handler=False и закройте ресурс на уровне владельца.

Без собственного HandlerProfile обработчик получает консервативный профиль. Объявляйте более сильные возможности только после проверки фактических байтов и поведения транспорта.

Предупреждение

Обработчик является последней границей перед сетью. Не записывайте секретные заголовки или открытое тело запроса в журнал диагностики.

Дальше#