Isso é um exemplo de brincadeira para demonstrar como funciona, se você precisar de suporte para Gzip, você pode usar o GzipMiddleware fornecido.
Primeiro, criamos uma classe GzipRequest, que irá sobrescrever o método Request.body() para descomprimir o corpo na presença de um cabeçalho apropriado.
Se não houver gzip no cabeçalho, ele não tentará descomprimir o corpo.
Dessa forma, a mesma classe de rota pode lidar com requisições comprimidas ou não comprimidas.
A única coisa que a função retornada por GzipRequest.get_route_handler faz de diferente é converter o Request para um GzipRequest.
Fazendo isso, nosso GzipRequest irá cuidar de descomprimir os dados (se necessário) antes de passá-los para nossas operações de rota.
Depois disso, toda a lógica de processamento é a mesma.
Mas por causa das nossas mudanças em GzipRequest.body, o corpo da requisição será automaticamente descomprimido quando for carregado pelo FastAPI quando necessário.
Acessando o corpo da requisição em um manipulador de exceção¶
Dica
Para resolver esse mesmo problema, é provavelmente muito mais fácil usar o body em um manipulador personalizado para RequestValidationError (Tratando Erros).
Mas esse exemplo ainda é valido e mostra como interagir com os componentes internos.
Também podemos usar essa mesma abordagem para acessar o corpo da requisição em um manipulador de exceção.
Tudo que precisamos fazer é manipular a requisição dentro de um bloco try/except:
você também pode definir o parametro route_class de uma APIRouter;
importtimefromtypingimportCallablefromfastapiimportAPIRouter,FastAPI,Request,Responsefromfastapi.routingimportAPIRouteclassTimedRoute(APIRoute):defget_route_handler(self)->Callable:original_route_handler=super().get_route_handler()asyncdefcustom_route_handler(request:Request)->Response:before=time.time()response:Response=awaitoriginal_route_handler(request)duration=time.time()-beforeresponse.headers["X-Response-Time"]=str(duration)print(f"route duration: {duration}")print(f"route response: {response}")print(f"route response headers: {response.headers}")returnresponsereturncustom_route_handlerapp=FastAPI()router=APIRouter(route_class=TimedRoute)@app.get("/")asyncdefnot_timed():return{"message":"Not timed"}@router.get("/timed")asyncdeftimed():return{"message":"It's the time of my life"}app.include_router(router)
Nesse exemplo, as operações de rota sob o router irão usar a classe TimedRoute personalizada, e terão um cabeçalho extra X-Response-Time na resposta com o tempo que levou para gerar a resposta:
importtimefromtypingimportCallablefromfastapiimportAPIRouter,FastAPI,Request,Responsefromfastapi.routingimportAPIRouteclassTimedRoute(APIRoute):defget_route_handler(self)->Callable:original_route_handler=super().get_route_handler()asyncdefcustom_route_handler(request:Request)->Response:before=time.time()response:Response=awaitoriginal_route_handler(request)duration=time.time()-beforeresponse.headers["X-Response-Time"]=str(duration)print(f"route duration: {duration}")print(f"route response: {response}")print(f"route response headers: {response.headers}")returnresponsereturncustom_route_handlerapp=FastAPI()router=APIRouter(route_class=TimedRoute)@app.get("/")asyncdefnot_timed():return{"message":"Not timed"}@router.get("/timed")asyncdeftimed():return{"message":"It's the time of my life"}app.include_router(router)