Skip to content

Capítulo 3.6: Tratamento de Erros e Validação

Tempo de estudo: 50 minutos


1. Tratamento de Erros: "Escudos de Emergência" da Nave Espacial

Mesmo na nave mais perfeita, situações imprevistas podem ocorrer:

  • Comando incorreto do Centro de Controle da Missão (CCM): O cliente enviou dados incorretos.
  • Perda de comunicação com o módulo: Recurso não encontrado no banco de dados.
  • Falha no reator: Erro interno do servidor.

O tratamento adequado de erros é um sistema de "escudos de emergência". Ele impede que a nave se desintegre e, em vez disso, envia um sinal claro ao CCM sobre o que deu errado.

💡 Analogia espacial:

Em vez de simplesmente transmitir um sinal de "AVARIA!" ao CCM, um bom computador de bordo enviará um relatório estruturado:

{
  "error_code": "ENGINE_OVERHEAT",
  "message": "A temperatura do motor Nº2 excedeu o normal",
  "suggested_action": "Ligar o sistema de refrigeração"
}
Isso permite que os engenheiros na Terra entendam rapidamente o problema e tomem medidas.


2. Validação Pydantic: O "Computador de Bordo" Integrado

Já encontramos a magia do Pydantic. Se você tentar criar uma nave com um tipo de dado inválido (por exemplo, launch_year como uma string), o FastAPI retornará automaticamente um erro 422 Unprocessable Entity com uma descrição detalhada de qual campo e por que a validação falhou.

Exemplo de requisição para POST /spaceships:

{
  "name": "X-Wing",
  "type": "Caça",
  "launch_year": "há muito tempo",  // <-- Tipo inválido!
  "status": "Em operação"
}

Resposta automática do FastAPI:

{
  "detail": [
    {
      "loc": [
        "body",
        "launch_year"
      ],
      "msg": "value is not a valid integer",
      "type": "type_error.integer"
    }
  ]
}
Isso é incrivelmente poderoso! Você não precisa escrever código para verificar tipos — FastAPI e Pydantic fazem isso por você.


3. Tratamento de "Recurso não Encontrado": Exceção HTTPException

Já usamos isso em operações CRUD. HTTPException é a maneira padrão do FastAPI de interromper a execução de uma requisição e retornar imediatamente uma resposta de erro ao cliente.

Vamos relembrar o código de GET /spaceships/{ship_id}:

# main.py
from fastapi import FastAPI, HTTPException # Certifique-se de que HTTPException esteja importado

# ...

@app.get("/spaceships/{ship_id}", response_model=Spaceship, tags=["Naves Espaciais"])
def get_spaceship(ship_id: int):
    ship = db_spaceships.get(ship_id)
    if not ship:
        # Se a nave não for encontrada, "lançamos" a exceção 404
        raise HTTPException(status_code=404, detail=f"Nave espacial com ID {ship_id} não encontrada")
    return ship

  • raise HTTPException(...): Esta chamada interrompe a execução da função.
  • status_code=404: Define o status HTTP da resposta.
  • detail: Mensagem que será enviada ao cliente no corpo da resposta JSON.

4. Validadores Personalizados: "Verificações Especiais" antes do Lançamento

E se quisermos adicionar nossa própria lógica de negócio, mais complexa? Por exemplo, proibir o lançamento de naves com o nome "Estrela da Morte".

Para isso, o Pydantic oferece uma ferramenta poderosa — validadores.

Passo 1: Adicionar o validador ao modelo SpaceshipCreate

# main.py
from pydantic import BaseModel, Field, validator

class SpaceshipCreate(BaseModel):
    name: str = Field(..., min_length=3, max_length=50)
    type: str
    launch_year: int = Field(..., gt=1950)
    status: str

    @validator('name')
    def name_must_not_be_forbidden(cls, v):
        """Verifica se o nome da nave não está na lista de proibidos."""
        if 'Death Star' in v:
            raise ValueError('Nomes como "Estrela da Morte" são proibidos por decreto Imperial!')
        return v.title() # De quebra, convertemos o nome para maiúsculas

  • @validator('name'): Decorador que "vincula" esta função ao campo name.
  • cls, v: O método recebe a própria classe (cls) e o valor do campo (v).
  • raise ValueError(...): Se a verificação falhar, levantamos uma exceção Python padrão. O FastAPI a interceptará e a transformará em um belo erro 422.
  • return v.title(): Se tudo estiver bem, devemos obrigatoriamente retornar o valor. Podemos até modificá-lo em tempo real (por exemplo, padronizá-lo).

Passo 2: Testar Reinicie o uvicorn e tente criar uma nave com um nome proibido via /docs. Você receberá um erro 422 com sua mensagem personalizada!


5. Tratamento Global de Erros: "Protocolo de Emergência" da Estação

Às vezes, é necessário interceptar erros inesperados (por exemplo, falha na conexão com um banco de dados real) e retornar um formato de resposta unificado e padronizado.

Para isso, o decorador @app.exception_handler é utilizado.

Exemplo: Interceptação de todos os erros ValueError

# main.py
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

# ...

@app.exception_handler(ValueError)
async def value_error_exception_handler(request: Request, exc: ValueError):
    """
    Manipulador global para todos os erros ValueError,
    para retornar JSON padronizado.
    """
    return JSONResponse(
        status_code=400,
        content={"message": f"Erro nos dados: {str(exc)}"},
    )

  • @app.exception_handler(ValueError): Informa ao FastAPI que esta função deve lidar com todos os ValueError que não foram interceptados anteriormente.
  • async def ...: Manipuladores de exceção devem ser assíncronos (async).
  • JSONResponse: Permite controle total sobre o corpo e o status da resposta.

Agora, quando nosso validador personalizado for acionado, a resposta terá um formato mais amigável que definimos.


Quiz para fixação

1. Se o cliente enviar dados de tipo incorreto (string em vez de número), o FastAPI retornará automaticamente o status...

2. `raise HTTPException(status_code=404)` é usado para...

3. O decorador `@validator('field_name')` no Pydantic é necessário para:

4. O que a função validadora no Pydantic deve fazer se os dados estiverem corretos?

5. `@app.exception_handler()` permite...


🚀 Resumo do Capítulo:

Você instalou em sua nave API um poderoso sistema de proteção e protocolos de emergência. Agora ela é capaz de:

  • 🛡️ Rejeitar automaticamente ataques de "dados inválidos" usando Pydantic.
  • 🚨 Notificar corretamente a ausência de recursos (404 Not Found) através de HTTPException.
  • ⚙️ Realizar "verificações especiais" com validadores personalizados.
  • 🧯 Interceptar globalmente falhas inesperadas e fornecer respostas padronizadas.

Seu "hipermotor" não é apenas rápido, mas também incrivelmente confiável!

📌 Verificação:

  • Tente criar uma nave com o nome "Death Star" e verifique se você recebe um erro 400 com sua mensagem personalizada.
  • Tente solicitar GET /spaceships/999 e verifique se você recebe um erro 404.
  • Tente enviar uma solicitação POST com launch_year como uma string e verifique se você recebe um erro 422.

⚠️ Se houver erros:

  • Certifique-se de que todos os módulos necessários (HTTPException, validator, Request, JSONResponse) foram importados.
  • Verifique se os decoradores @validator e @app.exception_handler foram escritos sem erros de digitação.

Parabéns por completar o Capítulo 3! Você construiu e lançou do zero uma API poderosa, documentada e segura com FastAPI. Você está pronto para realizar missões espaciais reais