Construindo o tratamento robusto de erros em FASTAPI – e evitando erros de novato

O FASTAPI é uma estrutura incrível para a criação de serviços baseados em HTTP no Python e muito acessível aos recém-chegados. O que, em certa medida, pode incentivar alguns a pular a documentação em favor da velocidade – ou pelo menos uma ilusão dela. Quando comecei a construir com o FASTAPI, cometi meu quinhão de erros quando se trata de manuseio de erros-os traços de pilha vazavam nas respostas do JSON porque meu serviço estava faltando um manipulador de captura ou eu levantaria o FASTAPI HTTPEXCECTIONS profundamente dentro da minha camada de serviço, mistura os detalhes da apresentação com a lógica dos negócios. O resultado foi abstrações com vazamento e cargas úteis de erro inconsistentes. Se você já se encontrou no mesmo barco, este artigo é para você. Vamos percorrer como projetar uma estratégia de manuseio de exceção limpa e sustentável no FASTAPI-que separa preocupações, mantém seus clientes felizes e gera erros amigáveis ​​e previsíveis. Por que o manuseio de erros estruturados é a consistência: os clientes podem confiar em um esquema de erro previsível, independentemente do ponto de extremidade que acertem. Manutenção: Seu código de serviço permanece estrutura-agnóstico-pronta para reutilizar em trabalhos de fundo ou ferramentas da CLI. Segurança: você nunca vaza acidentalmente mensagens internas ou empilham rastreamentos para os usuários finais. Observabilidade: Cada falha inesperada acaba em seus logs com contexto completo, tornando a análise da causa raiz uma brisa. Compreendendo as camadas de aplicativos antes de entrar na implementação e detalhes específicos da estrutura, vamos zoom e olhar para as camadas típicas em um serviço de back-end. Isso deve nos ajudar a entender onde levantar diferentes tipos de erros e como eles são escolhidos você[e transformados em respostas HTTP. Camada de apresentação É daí que as solicitações são recebidas e as respostas são devolvidas aos clientes. Também referido como camada do controlador no FASTAPI, isso é representado pelas rotas e pelo objeto de aplicação. Essa camada é responsável por: Parsing Parâmetros de solicitação (corpo, sequência de consulta, parâmetros de caminho). Retornando respostas HTTP. Pegando exceções e formatando -as para os clientes. No FASTAPI, o Pydantic é responsável por lidar com a validação dos parâmetros de solicitação. As exceções de validação são tratadas internamente pela estrutura. Espera -se que os manipuladores de exceção personalizados sejam implementados nessa camada. Camada de serviço ou (domínio de negócios) É aqui que sua lógica principal de aplicativos ao vivo. Deve ser: estrutura-agnóstico (sem importações de fastapi). Focado na lógica do domínio, por exemplo, busca dados, aplicando regras, acionando fluxos de trabalho. É aqui que as exceções personalizadas são levantadas, como o itemNotFoundError. Estes devem ser descritivos e transportar metadados (código de status, código de erro, mensagem), mas nunca retorne diretamente as respostas HTTP. Camada de infraestrutura Essa camada interage com o mundo exterior, incluindo: Sistemas de Arquivos de Bancos de Dados e Filas de Armazenamento e Notificações de Blob Catch APIs internas e de terceiros Catch e envolva exceções externas nos específicos de domínio. Por exemplo, se uma consulta de banco de dados falhar porque o item não existir, aumente o itemNotFoundError em vez de vazar uma exceção de SQL bruto. Erros pydantic vs. erros de domínio FASTAPI (via pydantic) já prega a validação da solicitação – ausentes de campos, tipos errados, JSON malformado. Todos esses casos se transformam perfeitamente em boas respostas de conteúdo não processáveis, mas restam uma grande lacuna: solicitações sintaticamente válidas que simplesmente não podem ser processadas no domínio do seu aplicativo (devido à violação das regras de negócios), falhas de pesquisa, limites de taxa, autenticações e verificações de autorização – elas estão de acordo. É aí que exceções personalizadas e manipuladores globais entram em jogo. Exceções personalizadas de criação define uma exceção da base leve que carrega todas as informações necessárias: # excepções.py classe appbaseexception (exceção): def __init __ (self, message: str, error_code: str, status_code: int = 400,): self.message = message.error_code = error_code: Modo de tela cheia Exitia Modo de tela cheia Construa casos específicos na parte superior do appbaseexception: # excepções.py # … classe ItemNotFoundError (appbaseexception): def __init __ (self, item_id: int,): super () .__ init __ (message = f “item {item {item_id} não encontrado,): error_code () .__ init __ (message = f” item {item {Item_Id} não encontrado,): Error_code_code (). CasaExcedEdError (AppBaseException): def __init __ (self): super () .__ init __ (message = “cota da api excedida”, error_code = “quota_exceded”, status_code = 429) Digite o modo de tela cheia de tela cheia, essas expectativas ao vivo na lógica comercial. Eles não sabem nada sobre os mecanismos HTTP da FASTAPI, o que os torna perfeitamente reutilizáveis ​​em outros lugares. Mapeamento para respostas HTTP com manipuladores em vez de aumentar profundamente a HttPexception em seus serviços, prefira capturar exceções personalizadas no nível do aplicativo: # excepcion_handlers.py importar log, traceback do fastapi de importação) de faspapi.Responsenses importar JsonResponse de .Exceptions importexexception ° registr_exception_handlers (app): @app.exception_handler (appbaseexception) async def app_exc_handler (solicitação: solicitação, exc: appbaseexception,): retorna jsonResponse (status_code = exc.status_code, content = {“Error”: exc.error_code “” ASYNC def Catch_all_Handler (Solicitação: Solicitação, EXC: Exceção): Logger.error (“UNHLEDLEDEXCECTION: \ n%s”, “” .Join (traceback.format_exception (type (exc), exc, exc .__ traceback__,)) retornar jsonResponse (status_code = 500, “content)” “:” TRACEBack__)) Retornar Tente novamente mais tarde. “,},) Digite o modo de saída de tela cheia de tela cheia, o primeiro manipulador transforma de forma limpa erros de domínio conhecidos no código de status certo e na forma JSON. O segundo é o seu problema. Qualquer nome inesperado, ValueError ou Hiccup de banco de dados ainda produzirá um 500 com uma mensagem genérica e registrará o rastreamento completo. Fiação aqui está como as peças colam juntas em um aplicativo FASTAPI mínimo: # Services.py de .Exceptions Importar ItemNotFoundError, QuotAexcededEdError Def get_item (Item_id: int): “” “É apenas uma camada de serviço dummy. Em um aplicativo real, se deve importar um db ou um terceiro cliente API. ItemNotFoundError (item_id) se item_id == 777: Aumente a cotaExcedEDerror () return {“id”: item_id, “name”: “sample item”} # rotas.py de fASTAPI) itens aPirouter de. read_item (item_id: int): retornar get_item (item_id) # main.py de fastapi importar fASTAPI de .Exception_Handlers Importar Register_Exception_Handlers de .Routes import roteter # seu apirouter com endpoints app = fastapi () app.include_Router (Router, prefix = “ApiPi () Apin). Sair da tela cheia Modo de registro e observabilidade Um manipulador global de erros sem registro é como um alarme de incêndio que você não consegue ouvir. Certifique -se de: use um logger estruturado (por exemplo, saída JSON) para que você possa filtrar por error_code. Inclua uma solicitação ou ID de correlação em todas as linhas de log para rastreamento – que deve ser tratado em um middleware e está fora do escopo deste artigo. Erros de envio para um serviço de observabilidade como Sentry, Datadog ou AWS CloudWatch, onde seus monitores podem desencadear alertas em caso de anomalias. Aumentando mantendo suas exceções focadas no domínio e seus manipuladores focados em HTTP, você acabará com: CÓDIGO DE SERVIÇO mais testável Código de serviço Cargas úteis de erro para cada ponto de extremidade Uma rede de segurança que captura as APIs seguras inesperadas que nunca derramam detalhes internos começam com este esqueleto na próxima vez em que você atinge um projeto FASTAPI. Você (e seus companheiros de plantão) agradecerão a si mesmo quando o alerta do Pager Finalmente ficar em silêncio. Codificação feliz! 🚀

Fonte

Você pode ter perdido