Перейти к содержанию

Обработка HTTP-ответов

Раздел объясняет, как в Rapidy управлять HTTP-ответом при возврате Python-объекта из HTTP-обработчика.

Атрибуты

Атрибуты ответа веб-обработчика используются для управления формированием ответа при возврате любого python-объекта из обработчика.

Rapidy позволяет управлять атрибутами во всех типах обработчиков, включая те, что оформлены в стиле aiohttp.

# aiohttp style
from rapidy import web

async def handler() -> dict[str, str]:
    return {'hello': 'rapidy'}

app = web.Application()
app.add_routes([
    web.post(
        '/',
        handler,
        status_code=200,
        response_content_type='application/json',
    ),
])

path

path: str | None = None — путь к обработчику на веб-сервере.

from rapidy.http import get

@get(
    '/',
)
async def handler() -> ...:
    ...

allow_head

allow_head: bool = True — флаг, определяющий, нужно ли добавить метод head к существующему обработчику get.

from rapidy.http import get

@get(
    '/',
    allow_head=True,
)
async def handler() -> ...:
    ...

status_code

status_code: int | HTTPStatus = 200 — код состояния по умолчанию, который будет использоваться для ответа.

from http import HTTPStatus
from rapidy.http import get

@get(
    '/',
    status_code=201,
)
async def handler() -> ...:
    ...

@get(
    '/',
    status_code=HTTPStatus.CREATED,
)
async def handler() -> ...:
    ...

response_validate

response_validate: bool = True — флаг, определяющий, должна ли выполняться валидация ответа обработчика.

from rapidy.http import get

@get(
    '/',
    response_validate=False,
)
async def handler() -> str:  # <-- `str` will be ignored
    return {'hello': 'rapidy'}

response_type

response_type: Type[Any] | None = ... — задаёт тип ответа обработчика. (Если указан, он будет использоваться для создания Pydantic-модели ответа вместо аннотации возврата обработчика.)

from rapidy.http import get

@get(
    '/',
    # `dict[str, str]` will be used for validate and serialize body response data
    response_type=dict[str, str],
)
async def handler() -> str:  # <-- `str` will be ignored
    return {'hello': 'rapidy'}

Этот флаг добавляет гибкость в сериализацию и валидацию тела ответа, но в большинстве случаев вам не потребуется его менять.


response_content_type

response_content_type: str = 'application/json' — определяет заголовок Content-Type и управляет постобработкой ответа.

response_content_type="application/json"

При значении "application/json" данные преобразуются в JSON с использованием jsonify(dumps=True) и кодируются в соответствии с charset.

from rapidy.http import get, ContentType

@get(
    '/',
    response_content_type=ContentType.json,
)
async def handler() -> dict[str, str]:
    return {'hello': 'rapidy!'}  # {"hello": "rapidy!"}

Если переданный объект является строкой (Response(body="string")), то, согласно стандарту JSON, строка будет экранирована дважды:

from rapidy.http import get, ContentType

@get(
    '/',
    response_content_type=ContentType.json,
)
async def handler() -> str:
    return 'hello rapidy!'  # "'hello rapidy!'"

content_type="text/*"

При значении "text/*" (например, text/plain, text/html и т. д.):

  • Если данные имеют тип str, они отправляются без изменений.
  • В противном случае они преобразуются в строку через jsonify(dumps=False).
from rapidy.http import get, ContentType

@get(
    '/',
    response_content_type=ContentType.text_any,
)
async def handler() -> str:
    return 'hello rapidy!'  # "hello rapidy!"

Если после jsonify(dumps=False) объект не является строкой, он дополнительно кодируется с помощью json_encoder во избежание двойного экранирования.

content_type="*"

Для любых других типов (*):

  • Если данные имеют тип bytes, они отправляются без изменений.
  • В противном случае они преобразуются в строку через jsonify(dumps=True) и кодируются в соответствии с charset.

Если content_type не указан, он устанавливается автоматически на основе типа возвращаемого значения:

  • body: dict | BaseModel | dataclasscontent_type="application/json"
  • body: str | Enum | int | float | Decimal | boolcontent_type="text/plain"
  • body: Anycontent_type="application/octet-stream"

response_charset

response_charset: str = 'utf-8' — кодировка, используемая для обработки данных.

from rapidy.http import get, Charset

@get(
    '/',
    response_charset=Charset.utf32,
)
async def handler() -> ...:
    ...

response_zlib_executor

response_zlib_executor: Callable | None = None — функция для сжатия ответа с использованием zlib.

Подробнее о zlib_executor

zlib_executor является частью aiohttp. Подробнее можно узнать здесь.


response_zlib_executor_size

response_zlib_executor_size: int | None = None — размер тела ответа в байтах, при котором будет применяться zlib-сжатие.


response_include_fields

response_include_fields: set[str] | dict[str, Any] | None = None — параметр include для Pydantic-моделей, определяющий, какие поля включать в ответ.

from pydantic import BaseModel, Field
from rapidy.http import get

class Result(BaseModel):
    value: str = Field('data', alias='someValue')
    another_value: str = Field('another_data', alias='someAnotherValue')

@get(
    '/',
    response_include_fields={'value'},
)
async def handler() -> Result:
    return Result()  # {'someValue': 'data'}

response_exclude_fields

response_exclude_fields: set[str] | dict[str, Any] | None = None — параметр exclude для Pydantic-моделей, определяющий, какие поля исключать из ответа.

from pydantic import BaseModel, Field
from rapidy.http import get

class Result(BaseModel):
    value: str = Field('data', alias='someValue')
    another_value: str = Field('another_data', alias='someAnotherValue')

@get(
    '/',
    response_exclude_fields={'value'},
)
async def handler() -> Result:
    return Result()  # {'someAnotherValue': 'another_data'}

response_by_alias

response_by_alias: bool = True — параметр Pydantic by_alias, определяющий, следует ли использовать псевдонимы полей вместо их оригинальных имен.

from pydantic import BaseModel, Field
from rapidy.http import get

class Result(BaseModel):
    value: str = Field('data', alias='someValue')

@get(
    '/',
    response_by_alias=True,  # <-- default
)
async def handler() -> Result:
    return Result()  # {"someValue": "data"}
...
@get(
    '/',
    response_by_alias=False,
)
async def handler() -> Result:
    return Result()  # {"value": "data"}


response_exclude_unset

response_exclude_unset: bool = False — параметр Pydantic exclude_unset, исключающий из ответа поля, не заданные явно (оставшиеся со значениями по умолчанию).

from pydantic import BaseModel, Field
from rapidy.http import get

class Result(BaseModel):
    value: str = Field('data', alias='someValue')
    another_value: str = Field('another_data', alias='someAnotherValue')

@get(
    '/',
    response_exclude_unset=False,  # <-- default
)
async def handler() -> Result:
    return Result(someAnotherValue='new_data')  # {"someValue": "data", "someAnotherValue": "new_data"}
...
@get(
    '/',
    response_exclude_unset=True,
)
async def handler() -> Result:
    return Result(someAnotherValue='new_data')  # {"someAnotherValue": "new_data"}


response_exclude_defaults

response_exclude_defaults: bool = False — параметр Pydantic exclude_defaults, исключающий из ответа поля, чьи значения совпадают с значениями по умолчанию, даже если они были явно установлены.

from pydantic import BaseModel, Field
from rapidy.http import get

class Result(BaseModel):
    value: str = Field('data', alias='someValue')

@get(
    '/',
    response_exclude_defaults=False,  # <-- default
)
async def handler() -> Result:
    return Result()  # {"value": "data"}
...
@get(
    '/',
    response_exclude_defaults=True,
)
async def handler() -> Result:
    return Result()  # {}


response_exclude_none

response_exclude_none: bool = False — параметр Pydantic exclude_none, исключающий из ответа поля со значением None.

from pydantic import BaseModel, Field
from rapidy.http import get

class Result(BaseModel):
    value: str = Field('data', alias='someValue')
    none_value: None = None

@get(
    '/',
    response_exclude_none=False,  # <-- default
)
async def handler() -> Result:
    return Result()  # {"someValue": "data", "none_value": null}
...
@get(
    '/',
    response_exclude_none=True,
)
async def handler() -> Result:
    return Result()  # {"someValue": "data"}


response_custom_encoder

response_custom_encoder: Callable | None = None — параметр Pydantic custom_encoder, задающий пользовательский кодировщик данных.


response_json_encoder

response_json_encoder: Callable = json.dumps — вызываемый объект, принимающий данные и возвращающий их строковое представление в формате JSON. Используется при json_response(dumps=True, ...).

from typing import Any
from rapidy.http import get

def custom_encoder(obj: Any) -> str:
    ...

@get(
    '/',
    response_json_encoder=custom_encoder,
)
async def handler() -> dict[str, str]:
    return {'hello': 'rapidy!'}  # will be converted to a string by Rapidy's internal tools