Aplicando decorators customizados a um handler HTTP#

É possível escrever seus próprios decorators e aplicá-los a seus handlers, junto com os decorators @app.http.*. No entando temos algumas regras:

Importante: Não é necessário declarar seu decorator com (*args, **kwargs). O asyncworker vai perceber o parametro que seu decorator precisa e chamará sempre passando apenas os parametros declarados na assinatura.

Um exemplo simples de decorator:

from asyncworker.http.wrapper import RequestWrapper
from asyncworker.decorators import wraps

def my_handler_decorator(handler):
    @wraps(handler)
    async def _wrapper(wrapper: RequestWrapper):
        # Código principal do decorator vem aqui
        return await call_http_handler(wrapper.http_request, handler)

    return _wrapper

A razão para isso é que o asyncworker permite que um handler receba parametros dinâmicos (Handlers que recebem mais do que apenas Request) e a função call_http_handler() é quem tem ciência disso e saberá fazer a resolução correta dos parametros necessários para que o handler seja corretamente chamado.

Esse decorator poderia ser aplicado a um handler assim:

@app.http.get(["/"])
@my_handler_decorator
async def handler():
  return web.json_response({})

Escrevendo um decorator que precisa conhecer a assinatura original do handler#

Caso o seu decorator precise saber a assinatura original do handler que está sendo decorado, ela pode ser descoberta usando asyncworker.utils.get_handler_original_typehints(). Essa função deve receber o mesmo parmetro que o @wraps() recebe. O retorno dessa chamada é o dicionário original que estava no atributo __annotations__ do handler original.

Um exemplo:

def simple_deco(handler):
    @wraps(handler)
    async def _wrapper():
        return await handler()

    return _wrapper

def other_deco(handler):
    @wraps(handler)
    async def _wrap():
        return get_handler_original_typehints(handler)

    return _wrap

@other_deco
@simple_deco
async def handler(a: bool, s: str):
      pass

Nesse caso, mesmo o decorator @other_deco() sendo o decorator no topo da lista de decorators, ele é capaz de retornar a assinatura original.