Передать зависимость запроса#
Зависимость подходит для значения, которым владеет приложение, а не вызывающий код. Автор SDK объявляет тип и назначение, приложение регистрирует provider, а runtime разрешает значение перед подготовкой запроса.
# examples/docs/dependencies.py
DEVICE = dependency(
Device,
name="device",
apply=(field("id").to_header("X-Device-Id"),),
)
@dataclass(frozen=True, slots=True, kw_only=True)
class GetDevice(HttpOperation[Result]):
__http__ = Http.get("/device", requires=(DEVICE,))
device_id: Annotated[Omittable[str], markers.Header("X-Device-Id")] = UNSET
class DeviceApi(SyncApi):
get = op(GetDevice)
def main() -> None:
registry = DependencyRegistry()
registry.register(DEVICE.dependency, DeviceProvider(Device("device-7")))
identity = Identity(dependencies=registry)
with guide_client(GuideSite()) as client:
result = DeviceApi(client, identity=identity).get()
print(f"device: {result.value}")
DEVICE выбирает поле id результата и пишет его в объявленный X-Device-Id. Поле операции
имеет UNSET по умолчанию, поэтому provider заполняет его только тогда, когда вызывающий не
передал значение сам.
DependencyRegistry принадлежит Identity и обслуживает все роутеры корня. Отсутствующий
обязательный provider останавливает вызов до сети.
Файл целиком
"""Provide application-owned request data through Identity."""
from dataclasses import dataclass
from typing import Annotated
from pydantic import BaseModel
from eazy_sdk import Http, HttpOperation, Identity, Omittable, SyncApi, UNSET, op
from eazy_sdk.dependencies import DependencyContext, DependencyRegistry, dependency, field
from eazy_sdk.request import markers
from examples.docs.guide_site import GuideSite, guide_client
class Result(BaseModel):
value: str
@dataclass(frozen=True, slots=True)
class Device:
id: str
@dataclass(frozen=True, slots=True)
class DeviceProvider:
device: Device
def resolve(self, context: DependencyContext) -> Device:
return self.device
# region docs: dependencies
# examples/docs/dependencies.py
DEVICE = dependency(
Device,
name="device",
apply=(field("id").to_header("X-Device-Id"),),
)
@dataclass(frozen=True, slots=True, kw_only=True)
class GetDevice(HttpOperation[Result]):
__http__ = Http.get("/device", requires=(DEVICE,))
device_id: Annotated[Omittable[str], markers.Header("X-Device-Id")] = UNSET
class DeviceApi(SyncApi):
get = op(GetDevice)
def main() -> None:
registry = DependencyRegistry()
registry.register(DEVICE.dependency, DeviceProvider(Device("device-7")))
identity = Identity(dependencies=registry)
with guide_client(GuideSite()) as client:
result = DeviceApi(client, identity=identity).get()
print(f"device: {result.value}")
# endregion docs: dependencies
if __name__ == "__main__":
main()
device: device-7
Выбрать способ применения#
Способ |
Когда использовать |
|---|---|
|
Значение целиком занимает новый header, query, cookie или поле тела |
|
Значение заполняет уже объявленный слот операции |
|
Значение нужно внутри private wire-документа |
Выбрать срок кэша#
Политика |
Когда provider вызывается снова |
|---|---|
|
При каждом обращении к зависимости |
|
После создания нового роутера |
|
Для нового логического вызова |
|
Для каждой попытки, включая retry и redirect |
Nonce и timestamp обычно требуют ATTEMPT, а неизменяемый device context можно хранить с
CLIENT. Маркер secret=True скрывает значение из диагностики.
Примечание
Access token относится к авторизации, captcha к защите, а ключ HMAC к key_provider. У этих
значений другой жизненный цикл, поэтому не оформляйте их как обычные зависимости.