Rumah >pembangunan bahagian belakang >Tutorial Python >Bagaimana untuk Mencatat Badan Permintaan dan Respons HTTP Mentah dengan Cekap dalam FastAPI?
Cara Merekod Permintaan dan Respons HTTP Mentah dalam Python FastAPI
Pengenalan:
Dalam untuk memenuhi keperluan pengauditan untuk perkhidmatan web berasaskan Python FastAPI anda, anda perlu mengekalkan badan JSON mentah bagi kedua-dua permintaan dan respons pada laluan tertentu. Panduan ini akan membentangkan dua penyelesaian yang berdaya maju untuk mencapainya tanpa menjejaskan masa tindak balas yang ketara, walaupun semasa bekerja dengan saiz badan yang lebih kurang 1MB.
Pilihan 1: Penggunaan Middleware
Mekanik Perisian Tengah:
Perisian Tengah berfungsi sebagai penjaga pintu untuk permintaan memasuki aplikasi. Ia membenarkan untuk mengendalikan permintaan sebelum pemprosesan titik akhir dan respons sebelum kembali kepada pelanggan. Anda boleh mewujudkan middleware menggunakan @app.middleware penghias pada fungsi:
Permintaan dan Pengurusan Badan Respons:
Untuk mengakses badan permintaan daripada strim dalam middleware ( menggunakan request.body() atau request.stream()), anda perlu menyediakannya kemudian dalam kitaran permintaan-tindak balas. Siaran yang dipautkan membincangkan penyelesaian ini, yang kini tidak diperlukan untuk FastAPI versi 0.108.0 dan ke atas.
Untuk badan respons, anda boleh meniru teknik yang digariskan dalam siaran ini untuk menggunakan dan mengembalikan badan secara langsung, memberikan status kod, pengepala dan jenis media bersama-sama dengan respons asal.
Pengelogan Data:
Gunakan BackgroundTask untuk log data, memastikan pelaksanaannya selepas respons selesai. Ini menghapuskan klien menunggu untuk tugasan pengelogan dan mengekalkan integriti masa tindak balas.
Pilihan 2: Pelaksanaan APIRoute Tersuai
Laluan API Tersuai:
Pilihan ini melibatkan penciptaan kelas APIRoute tersuai untuk memanipulasi badan permintaan dan tindak balas sebelum memproses titik akhir atau mengembalikan keputusan kepada pelanggan. Ia membolehkan pengasingan pengendalian laluan tersuai ke titik akhir tertentu dengan menggunakan APIRouter khusus:
Pertimbangan:
Kekangan Memori:
Kedua-dua pendekatan mungkin menghadapi cabaran dengan permintaan atau badan tindak balas yang besar melebihi RAM pelayan yang tersedia. Menstrim respons besar boleh memperkenalkan kelewatan pihak klien atau ralat proksi terbalik. Hadkan penggunaan perisian tengah kepada laluan tertentu atau kecualikan titik akhir dengan respons penstriman yang besar untuk mengelakkan isu yang berpotensi.
Kod Contoh (Pilihan 1):
from fastapi import FastAPI, APIRouter, Response, Request from starlette.background import BackgroundTask from fastapi.routing import APIRoute from starlette.types import Message from typing import Dict, Any import logging app = FastAPI() logging.basicConfig(filename='info.log', level=logging.DEBUG) def log_info(req_body, res_body): logging.info(req_body) logging.info(res_body) # Not required for FastAPI >= 0.108.0 async def set_body(request: Request, body: bytes): async def receive() -> Message: return {'type': 'http.request', 'body': body} request._receive = receive @app.middleware('http') async def some_middleware(request: Request, call_next): req_body = await request.body() await set_body(request, req_body) # Not required for FastAPI >= 0.108.0 response = await call_next(request) res_body = b'' async for chunk in response.body_iterator: res_body += chunk task = BackgroundTask(log_info, req_body, res_body) return Response(content=res_body, status_code=response.status_code, headers=dict(response.headers), media_type=response.media_type, background=task) @app.post('/') def main(payload: Dict[Any, Any]): return payload
Contoh Kod (Pilihan 2):
from fastapi import FastAPI, APIRouter, Response, Request from starlette.background import BackgroundTask from starlette.responses import StreamingResponse from fastapi.routing import APIRoute from starlette.types import Message from typing import Callable, Dict, Any import logging import httpx def log_info(req_body, res_body): logging.info(req_body) logging.info(res_body) class LoggingRoute(APIRoute): def get_route_handler(self) -> Callable: original_route_handler = super().get_route_handler() async def custom_route_handler(request: Request) -> Response: req_body = await request.body() response = await original_route_handler(request) tasks = response.background if isinstance(response, StreamingResponse): res_body = b'' async for item in response.body_iterator: res_body += item task = BackgroundTask(log_info, req_body, res_body) response = Response(content=res_body, status_code=response.status_code, headers=dict(response.headers), media_type=response.media_type) else: task = BackgroundTask(log_info, req_body, response.body) # Check if the original response had background tasks already attached to it if tasks: tasks.add_task(task) # Add the new task to the tasks list response.background = tasks else: response.background = task return response return custom_route_handler app = FastAPI() router = APIRouter(route_class=LoggingRoute) logging.basicConfig(filename='info.log', level=logging.DEBUG) @router.post('/') def main(payload: Dict[Any, Any]): return payload @router.get('/video') def get_video(): url = 'https://storage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4' def gen(): with httpx.stream('GET', url) as r: for chunk in r.iter_raw(): yield chunk return StreamingResponse(gen(), media_type='video/mp4') app.include_router(router)
Penyelesaian ini menyediakan kaedah yang cekap untuk pembalakan permintaan HTTP mentah dan badan tindak balas dalam FastAPI tanpa menjejaskan masa respons dengan ketara.
Atas ialah kandungan terperinci Bagaimana untuk Mencatat Badan Permintaan dan Respons HTTP Mentah dengan Cekap dalam FastAPI?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!