FastAPI middleware-ni noldan oʻrganing. Ushbu chuqur qoʻllanma moslashtirilgan middleware, autentifikatsiya, logging, xatolarni hal qilish va mustahkam API-larni yaratish uchun eng yaxshi amaliyotlarni qamrab oladi.
Python FastAPI Middleware: Soʻrov va Javoblarni Qayta Ishlash boʻyicha Toʻliq Qoʻllanma
Zamonaviy veb-ishlab chiqish dunyosida unumdorlik, xavfsizlik va saqlash qobiliyati muhim ahamiyatga ega. Python-ning FastAPI freymvorki oʻzining ajoyib tezligi va dasturchilar uchun qulay xususiyatlari tufayli tezda mashhurlikka erishdi. Uning eng kuchli, ammo ba'zan notoʻgʻri tushunilgan xususiyatlaridan biri middleware hisoblanadi. Middleware soʻrov va javoblarni qayta ishlash zanjirida muhim bogʻlovchi vazifasini bajaradi, bu esa dasturchilarga soʻrov manzilga yetib borgunga qadar yoki javob mijozga qaytarilishidan oldin kodni bajarish, ma'lumotlarni oʻzgartirish va qoidalarni amalga oshirish imkonini beradi.
Ushbu toʻliq qoʻllanma FastAPI bilan endigina ish boshlaganlardan tortib, tushunchalarini chuqurlashtirishni istagan tajribali mutaxassislargacha boʻlgan dasturchilarning global auditoriyasi uchun moʻljallangan. Biz middleware-ning asosiy tushunchalarini oʻrganamiz, moslashtirilgan yechimlarni qanday yaratishni koʻrsatamiz va amaliy, real dunyo foydalanish holatlarini koʻrib chiqamiz. Oxir-oqibat, siz yanada mustahkam, xavfsiz va samarali API-larni yaratish uchun middleware-dan foydalanishga tayyor boʻlasiz.
Veb-freymvorklar kontekstida Middleware nima?
Kodga shoʻngʻishdan oldin, tushunchani tushunish muhimdir. Ilovangizning soʻrov-javob siklini quvur yoki yigʻish liniyasi sifatida tasavvur qiling. Mijoz sizning API-ga soʻrov yuborganida, u shunchaki sizning endpoint mantiqingizga darhol ta'sir qilmaydi. Buning oʻrniga, u bir qator qayta ishlash bosqichlaridan oʻtadi. Xuddi shunday, sizning endpoint javob yaratganda, u mijozga yetib borishdan oldin ushbu bosqichlardan qaytib oʻtadi. Middleware komponentlari quvurdagi ushbu bosqichlarning oʻzidir.
Mashhur oʻxshatish - bu piyoz modeli. Piyozning yadrosi sizning ilovangizning biznes mantiqi (endpoint). Yadroni oʻrab turgan piyozning har bir qatlami middleware qismidir. Soʻrov yadroga yetib borish uchun har bir tashqi qatlamni oʻtishi kerak va javob xuddi shu qatlamlardan qaytib chiqadi. Har bir qatlam soʻrovni ichkariga va javobni tashqariga yoʻlida tekshirishi va oʻzgartirishi mumkin.
Aslida, middleware - bu soʻrov ob'ektiga, javob ob'ektiga va ilovaning soʻrov-javob siklidagi keyingi middleware-ga kirish huquqiga ega boʻlgan funksiya yoki sinf. Uning asosiy maqsadlari quyidagilardan iborat:
- Kodni bajarish: Har bir kiruvchi soʻrov uchun logging yoki unumdorlik monitoringi kabi amallarni bajaring.
- Soʻrov va javobni oʻzgartirish: Sarlavhalarni qoʻshing, javob tanalarini siqing yoki ma'lumotlar formatlarini oʻzgartiring.
- Siklni qisqartirish: Soʻrov-javob siklini erta yakunlang. Misol uchun, autentifikatsiya middleware autentifikatsiyalanmagan soʻrovni moʻljallangan endpointga yetib borgunga qadar bloklashi mumkin.
- Global muammolarni boshqarish: Xatolarni hal qilish, CORS (Cross-Origin Resource Sharing) va sessiya boshqaruvi kabi kesishgan muammolarni markazlashgan joyda hal qiling.
FastAPI Starlette asboblar toʻplami ustiga qurilgan boʻlib, u ASGI (Asynchronous Server Gateway Interface) standartining mustahkam amalga oshirilishini ta'minlaydi. Middleware ASGI-da fundamental tushuncha boʻlib, uni FastAPI ekotizimida birinchi darajali fuqaroga aylantiradi.
Eng oddiy shakl: Dekorator bilan FastAPI Middleware
FastAPI @app.middleware("http") dekoratoridan foydalanib middleware qoʻshishning toʻgʻri yoʻlini ta'minlaydi. Bu har bir HTTP soʻrovi uchun bajarilishi kerak boʻlgan oddiy, oʻz-oʻzidan mavjud boʻlgan mantiq uchun juda mos keladi.
Keling, klassik misolni yaratamiz: har bir soʻrov uchun qayta ishlash vaqtini hisoblash va uni javob sarlavhalariga qoʻshish uchun middleware. Bu unumdorlik monitoringi uchun juda foydali.
Misol: Jarayon vaqti Middleware
Birinchidan, sizda FastAPI va Uvicorn kabi ASGI serveri oʻrnatilganligiga ishonch hosil qiling:
pip install fastapi uvicorn
Endi kodni main.py fayliga yozaylik:
import time
from fastapi import FastAPI, Request
app = FastAPI()
# Middleware funksiyasini belgilang
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
# Soʻrov kelganida boshlanish vaqtini yozib oling
start_time = time.time()
# Keyingi middleware yoki endpointga oʻting
response = await call_next(request)
# Qayta ishlash vaqtini hisoblang
process_time = time.time() - start_time
# Javobga moslashtirilgan sarlavhani qoʻshing
response.headers["X-Process-Time"] = str(process_time)
return response
@app.get("/")
async def root():
# Ba'zi ishlarni simulyatsiya qiling
time.sleep(0.5)
return {"message": "Salom, Dunyo!"}
Ushbu ilovani ishga tushirish uchun quyidagi buyruqdan foydalaning:
uvicorn main:app --reload
Endi, agar siz http://127.0.0.1:8000 ga cURL kabi vosita yoki Postman kabi API mijozi yordamida soʻrov yuborsangiz, javobda yangi sarlavhani koʻrasiz, X-Process-Time, taxminan 0,5 soniya qiymatiga ega.
Kodni demontaj qilish:
@app.middleware("http"): Ushbu dekorator bizning funksiyamizni HTTP middleware qismi sifatida roʻyxatdan oʻtkazadi.async def add_process_time_header(request: Request, call_next):: Middleware funksiyasi asinxron boʻlishi kerak. U kiruvchiRequestob'ektini va maxsus funksiyani,call_nextni oladi.response = await call_next(request): Bu eng muhim satr.call_nextsoʻrovni quvurdagi keyingi bosqichga (boshqa middleware yoki haqiqiy yoʻl operatsiyasiga) oʻtkazadi. Siz ushbu qoʻngʻiroqni await qilishingiz kerak. Natija - bu endpoint tomonidan yaratilganResponseob'ekti.response.headers[...] = ...: Endpointdan javob olingandan soʻng, biz uni oʻzgartirishimiz mumkin, bu holda moslashtirilgan sarlavhani qoʻshish orqali.return response: Nihoyat, oʻzgartirilgan javob mijozga yuborilishi uchun qaytariladi.
Sinflar bilan oʻz Middleware-ingizni yaratish
Dekorator yondashuvi oddiy boʻlsa-da, u yanada murakkab senariylar uchun cheklaydigan boʻlishi mumkin, ayniqsa sizning middleware-ingiz konfiguratsiyani talab qilsa yoki ba'zi ichki holatni boshqarishi kerak boʻlsa. Ushbu holatlar uchun FastAPI (Starlette orqali) BaseHTTPMiddleware dan foydalangan holda sinfga asoslangan middleware-ni qoʻllab-quvvatlaydi.
Sinfga asoslangan yondashuv yaxshiroq tuzilishni taklif qiladi, uning konstruktorida bogʻliqlik in'ektsiyasiga imkon beradi va umuman olganda murakkab mantiq uchun yanada saqlanadigan. Asosiy mantiq asinxron dispatch usulida joylashgan.
Misol: Sinfga asoslangan API kalit autentifikatsiya Middleware
Keling, bizning API-ni himoya qiladigan yanada amaliy middleware yaratamiz. U maxsus sarlavhani, X-API-Key ni tekshiradi va agar kalit mavjud boʻlmasa yoki yaroqsiz boʻlsa, u darhol 403 Forbidden xato javobini qaytaradi. Bu soʻrovni "qisqartirish" misoli.
main.py da:
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from starlette.responses import Response
# Yaroqli API kalitlari roʻyxati. Haqiqiy ilovada bu ma'lumotlar bazasidan yoki xavfsiz ombordan keladi.
VALID_API_KEYS = ["my-super-secret-key", "another-valid-key"]
class APIKeyMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
api_key = request.headers.get("X-API-Key")
if api_key not in VALID_API_KEYS:
# Soʻrovni qisqartiring va xato javobini qaytaring
return JSONResponse(
status_code=403,
content={"detail": "Forbidden: Invalid or missing API Key"}
)
# Agar kalit yaroqli boʻlsa, soʻrovni davom eting
response = await call_next(request)
return response
app = FastAPI()
# Ilovaga middleware qoʻshing
app.add_middleware(APIKeyMiddleware)
@app.get("/")
async def root():
return {"message": "Xavfsiz hududga xush kelibsiz!"}
Endi, ushbu ilovani ishga tushirganda:
X-API-Keysarlavhasi boʻlmagan soʻrov (yoki notoʻgʻri qiymatga ega) 403 status kodini va JSON xato xabarini oladi.X-API-Key: my-super-secret-keysarlavhasi boʻlgan soʻrov muvaffaqiyatli boʻladi va 200 OK javobini oladi.
Ushbu naqsh juda kuchli. / dagi endpoint kodi API kalitini tekshirish haqida hech narsa bilishi shart emas; bu muammo butunlay middleware qatlamiga ajratilgan.
Middleware uchun umumiy va kuchli foydalanish holatlari
Middleware kesishgan muammolarni hal qilish uchun mukammal vositadir. Keling, eng keng tarqalgan va ta'sirli foydalanish holatlarini oʻrganamiz.
1. Markazlashgan Logging
Toʻliq logging ishlab chiqarish ilovalari uchun muhokama qilinmaydi. Middleware har bir soʻrov va unga mos keladigan javob haqida muhim ma'lumotlarni qayd qiladigan yagona nuqtani yaratishga imkon beradi.
Logging Middleware misoli:
import logging
from fastapi import FastAPI, Request
import time
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = FastAPI()
@app.middleware("http")
async def logging_middleware(request: Request, call_next):
start_time = time.time()
# Soʻrov tafsilotlarini qayd qiling
logger.info(f"Kiruvchi soʻrov: {request.method} {request.url.path}")
response = await call_next(request)
process_time = time.time() - start_time
# Javob tafsilotlarini qayd qiling
logger.info(f"Javob statusi: {response.status_code} | Qayta ishlash vaqti: {process_time:.4f}s")
return response
Ushbu middleware kirish yoʻlida soʻrov usuli va yoʻlini, chiqish yoʻlida esa javob status kodi va umumiy qayta ishlash vaqtini qayd qiladi. Bu sizning ilovangizning trafigiga bebaho koʻrinishni ta'minlaydi.
2. Global xatolarni hal qilish
Odatiy boʻlib, kodingizda hal qilinmagan istisno 500 Internal Server Error xatosiga olib keladi, bu esa potentsial ravishda stek izlarini va amalga oshirish tafsilotlarini mijozga ochib beradi. Global xatolarni hal qilish middleware barcha istisnolarni ushlashi, ularni ichki koʻrib chiqish uchun qayd qilishi va standartlashtirilgan, foydalanuvchilar uchun qulay xato javobini qaytarishi mumkin.
Xatolarni hal qilish Middleware misoli:
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import logging
logger = logging.getLogger(__name__)
app = FastAPI()
@app.middleware("http")
async def error_handling_middleware(request: Request, call_next):
try:
return await call_next(request)
except Exception as e:
logger.error(f"Hal qilinmagan xato yuz berdi: {e}", exc_info=True)
return JSONResponse(
status_code=500,
content={"detail": "Ichki server xatosi yuz berdi. Iltimos, keyinroq qayta urinib koʻring."}
)
@app.get("/error")
async def cause_error():
return 1 / 0 # Bu ZeroDivisionError-ni keltirib chiqaradi
Ushbu middleware oʻrnatilgan boʻlsa, /error ga soʻrov endi serverni ishdan chiqarmaydi yoki stek izini ochib bermaydi. Buning oʻrniga, u 500 status kodini toza JSON tanasi bilan qaytaradi, toʻliq xato esa dasturchilar tekshirish uchun server tomonida qayd etiladi.
3. CORS (Cross-Origin Resource Sharing)
Agar sizning frontend ilovangiz FastAPI backend-ingizdan boshqa domen, protokol yoki portdan xizmat qilsa, brauzerlar Same-Origin Policy tufayli soʻrovlarni bloklaydi. CORS - bu ushbu siyosatni boʻshashtirish mexanizmi. FastAPI aynan shu maqsad uchun maxsus, yuqori darajada sozlanishi mumkin boʻlgan `CORSMiddleware` ni ta'minlaydi.
CORS konfiguratsiyasi misoli:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# Ruxsat etilgan manbalar roʻyxatini belgilang. Ommaviy API-lar uchun "*" dan foydalaning, lekin yaxshiroq xavfsizlik uchun aniq boʻling.
origins = [
"http://localhost:3000",
"https://my-production-frontend.com",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True, # Cross-origin soʻrovlarida cookie fayllarini kiritishga ruxsat bering
allow_methods=["*"], # Barcha standart HTTP usullariga ruxsat bering
allow_headers=["*"], # Barcha sarlavhalarga ruxsat bering
)
Bu ajratilgan frontendga ega boʻlgan har qanday loyihaga qoʻshadigan birinchi middleware qismlaridan biri boʻlib, cross-origin siyosatini bitta, markaziy joydan boshqarishni osonlashtiradi.
4. GZip siqish
HTTP javoblarini siqish ularning hajmini sezilarli darajada kamaytirishi mumkin, bu esa mijozlar uchun yuklanish vaqtini tezlashtiradi va tarmoqli kengligi xarajatlarini kamaytiradi. FastAPI buni avtomatik ravishda hal qilish uchun `GZipMiddleware` ni oʻz ichiga oladi.
GZip Middleware misoli:
from fastapi import FastAPI
from fastapi.middleware.gzip import GZipMiddleware
app = FastAPI()
# GZip middleware-ni qoʻshing. Siqish uchun minimal hajmni oʻrnatishingiz mumkin.
app.add_middleware(GZipMiddleware, minimum_size=1000)
@app.get("/")
async def root():
# Ushbu javob kichik va gzipped boʻlmaydi.
return {"message": "Salom Dunyo"}
@app.get("/large-data")
async def large_data():
# Ushbu katta javob middleware tomonidan avtomatik ravishda gzipped qilinadi.
return {"data": "a_very_long_string..." * 1000}
Ushbu middleware bilan har qanday 1000 baytdan katta javob, agar mijoz GZip kodlashni qabul qilishini koʻrsatsa (buni deyarli barcha zamonaviy brauzerlar va mijozlar qiladi), siqiladi.
Ilgʻor tushunchalar va eng yaxshi amaliyotlar
Middleware bilan yanada yaxshi tanishganingizdan soʻng, toza, samarali va bashoratli kod yozish uchun ba'zi nuanslarni va eng yaxshi amaliyotlarni tushunish muhimdir.
1. Middleware tartibi muhim!
Bu esda tutish kerak boʻlgan eng muhim qoida. Middleware ilovaga qoʻshilgan tartibda qayta ishlanadi. Qoʻshilgan birinchi middleware "piyoz" ning tashqi qatlamidir.
Ushbu sozlamani koʻrib chiqing:
app.add_middleware(ErrorHandlingMiddleware) # Tashqi
app.add_middleware(LoggingMiddleware)
app.add_middleware(AuthenticationMiddleware) # Ichki
Soʻrov oqimi quyidagicha boʻladi:
ErrorHandlingMiddlewaresoʻrovni oladi. U oʻzining `call_next` ni `try...except` bloki ichiga oʻraydi.- U `next` ga qoʻngʻiroq qiladi va soʻrovni `LoggingMiddleware` ga oʻtkazadi.
LoggingMiddlewaresoʻrovni oladi, uni qayd qiladi va `next` ga qoʻngʻiroq qiladi.AuthenticationMiddlewaresoʻrovni oladi, ma'lumotlarni tekshiradi va `next` ga qoʻngʻiroq qiladi.- Soʻrov nihoyat endpoint ga yetib boradi.
- Endpoint javobni qaytaradi.
AuthenticationMiddlewarejavobni oladi va uni yuqoriga oʻtkazadi.LoggingMiddlewarejavobni oladi, uni qayd qiladi va uni yuqoriga oʻtkazadi.ErrorHandlingMiddlewareyakuniy javobni oladi va uni mijozga qaytaradi.
Bu tartib mantiqiy: xato ishlovchisi tashqi tomonda, shuning uchun u boshqa middleware, shu jumladan har qanday keyingi qatlamdagi xatolarni ushlashi mumkin. Autentifikatsiya qatlami chuqur ichkarida, shuning uchun biz rad etiladigan soʻrovlarni qayd qilish yoki qayta ishlashga urinmaymiz.
2. `request.state` bilan ma'lumotlarni oʻtkazish
Ba'zan, middleware endpointga ma'lumot berishi kerak. Misol uchun, autentifikatsiya middleware JWT-ni dekodlashi va foydalanuvchining ID-sini olishi mumkin. U ushbu foydalanuvchi ID-sini yoʻl operatsiyasi funksiyasi uchun qanday qilib mavjud qilishi mumkin?
Notoʻgʻri yoʻl - soʻrov ob'ektini toʻgʻridan-toʻgʻri oʻzgartirish. Toʻgʻri yoʻl - `request.state` ob'ektidan foydalanish. Bu aynan shu maqsad uchun taqdim etilgan oddiy, boʻsh ob'ekt.
Middleware-dan foydalanuvchi ma'lumotlarini oʻtkazish misoli
# Autentifikatsiya middleware-ning dispatch usulida:
# ... tokenni tekshirgandan va foydalanuvchini dekodlagandan soʻng ...
user_data = {"id": 123, "username": "global_dev"}
request.state.user = user_data
response = await call_next(request)
# Endpoint-da:
@app.get("/profile")
async def get_user_profile(request: Request):
current_user = request.state.user
return {"profile_for": current_user}
Bu mantiqni toza saqlaydi va `Request` ob'ektining nomlar maydonini ifloslantirishdan saqlaydi.
3. Unumdorlikni hisobga olish
Middleware kuchli boʻlsa-da, har bir qatlam ozgina yukni qoʻshadi. Yuqori unumdorlikdagi ilovalar uchun ushbu fikrlarni yodda tuting:
- Uni toza tuting: Middleware mantiqi imkon qadar tez va samarali boʻlishi kerak.
- Asinxron boʻling: Agar sizning middleware-ingiz I/U operatsiyalarini (masalan, ma'lumotlar bazasini tekshirish) bajarishi kerak boʻlsa, serverning voqea aylanishini bloklamaslik uchun u toʻliq `async` ekanligiga ishonch hosil qiling.
- Maqsad bilan foydalaning: Sizga kerak boʻlmagan middleware-ni qoʻshmang. Har biri qoʻngʻiroqlar stekining chuqurligiga va qayta ishlash vaqtiga qoʻshiladi.
4. Middleware-ingizni sinovdan oʻtkazish
Middleware sizning ilovangiz mantiqining muhim qismidir va uni toʻliq sinovdan oʻtkazish kerak. FastAPI-ning `TestClient` buni toʻgʻri qiladi. Siz talab qilinadigan shartlar bilan va ularsiz soʻrovlar yuboradigan (masalan, yaroqli API kaliti bilan va usiz) testlar yozishingiz va middleware-ning kutilganidek ishlashini tasdiqlashingiz mumkin.
APIKeyMiddleware uchun test misoli:
from fastapi.testclient import TestClient
from .main import app # FastAPI ilovangizni import qiling
client = TestClient(app)
def test_request_without_api_key_is_forbidden():
response = client.get("/")
assert response.status_code == 403
assert response.json() == {"detail": "Forbidden: Invalid or missing API Key"}
def test_request_with_valid_api_key_is_successful():
headers = {"X-API-Key": "my-super-secret-key"}
response = client.get("/", headers=headers)
assert response.status_code == 200
assert response.json() == {"message": "Xavfsiz hududga xush kelibsiz!"}
Xulosa
FastAPI middleware - bu zamonaviy veb-API-larni yaratuvchi har qanday dasturchi uchun fundamental va kuchli vosita. U kesishgan muammolarni hal qilish, ularni asosiy biznes mantiqingizdan ajratish uchun oqlangan va qayta ishlatiladigan usulni taqdim etadi. Har bir soʻrov va javobni ushlab turish va qayta ishlash orqali middleware sizga mustahkam logging, markazlashgan xatolarni hal qilish, qat'iy xavfsizlik siyosati va siqish kabi unumdorlikni oshirishni amalga oshirish imkonini beradi.
Oddiy @app.middleware("http") dekoratoridan tortib to murakkab, sinfga asoslangan yechimlargacha, siz oʻz ehtiyojlaringiz uchun toʻgʻri yondashuvni tanlash uchun moslashuvchanlikka egasiz. Asosiy tushunchalarni, umumiy foydalanish holatlarini va middleware tartibi va holat boshqaruvi kabi eng yaxshi amaliyotlarni tushunish orqali siz yanada toza, xavfsizroq va oson saqlanadigan FastAPI ilovalarini yaratishingiz mumkin.
Endi navbat sizniki. Keyingi FastAPI loyihangizga moslashtirilgan middleware-ni integratsiya qilishni boshlang va API dizayningizda yangi darajadagi boshqaruv va nafosatni oching. Imkoniyatlar juda katta va bu xususiyatni oʻzlashtirish sizni shubhasiz yanada samarali va tejamkor dasturchiga aylantiradi.