Вобастагиҳо ва дастрасӣ
Чаро вобастагиҳо лозиманд
Агар даҳ масир як сарлавҳаро санҷанд, даҳ нусхаи санҷиш дер ё зуд аз ҳам фарқ мекунанд. Як масир маҳдудиятро фаромӯш мекунад, дигарӣ рамзи хатои дигар медиҳад. Вобастагӣ функсияи ҷудоест, ки қимати лозимро омода мекунад ё дархостро пеш аз амали асосӣ бозмедорад.
Дар FastAPI вобастагиҳо query ва сарлавҳаҳоро мехонанд, корбарро мегиранд ва метавонанд аз вобастагиҳои дигар истифода кунанд. Ин имкон медиҳад, ки қоидаи умумӣ дар як ҷой тағйир ёбад. Ҳар мисоли поён мустақил аст; калидҳои мисоли таълимӣ низоми тайёри шиносоӣ барои хидмати воқеӣ нестанд.
Depends натиҷаи функсияро медиҳад
Depends(prepare) худи функсияро ба FastAPI медиҳад. Ҳангоми дархост фреймворк онро даъват карда, натиҷаашро ба аргументи масир мегузорад. Баъди номи вобастагӣ дар ин ҷо қавс лозим нест: Depends(prepare()) онро ҳангоми сохтани барнома даъват карданӣ мешавад. Дар мисол ададеро ҳисоб мекунем, ки ду масир истифода мебаранд.
from fastapi import FastAPI, Depends, Query
from fastapi.testclient import TestClient
app = FastAPI()
def prepare(n: int = Query(2, ge=1)):
return n * 10
@app.get("/first")
def first(value: int = Depends(prepare)):
return {"value": value}
@app.get("/second")
def second(value: int = Depends(prepare)):
return {"value": value + 1}
client = TestClient(app)
print(client.get("/first?n=3").json())
print(client.get("/second").json())
print(client.get("/first?n=0").status_code)
Баромад:
{'value': 30}
{'value': 21}
422
Header маълумоти иловагии дархостро мехонад
Сарлавҳа қимати номдорест, ки берун аз роҳ ва танаи JSON ҷой дорад. Header онро аз query-параметр фарқ мекунад. Зерхатҳои номи Python одатан ба дефис табдил меёбанд: x_trace_id сарлавҳаи X-Trace-Id-ро мехонад. Калон ё хурд будани ҳарфҳои номи сарлавҳа муҳим нест, вале ин маънои озодона иваз кардани ҳарфҳои қиматро надорад. Header(None) набуданро иҷозат дода, None медиҳад.
from fastapi import FastAPI, Header
from fastapi.testclient import TestClient
app = FastAPI()
@app.get("/trace")
def trace(x_trace_id: str | None = Header(None)):
return {"trace": x_trace_id}
client = TestClient(app)
print(client.get("/trace").json())
print(client.get("/trace", headers={"x-trace-id": "AB-7"}).json())
Баромад:
{'trace': None}
{'trace': 'AB-7'}
Боздоштани дархост дар вобастагӣ
Санҷиш метавонад пеш аз масир HTTPException ба вуҷуд орад. Дар мисол сарлавҳаи ҳатмии хидматиро худамон санҷида, 400 интихоб мекунем. Агар Header()-и ҳатмии бе пешфарз менавиштем, FastAPI барои набудани он пеш аз санҷиши мо 422 медод. Рӯйхати даъватҳо нишон медиҳад, ки дархости номуваффақ амали асосиро иҷро намекунад.
from fastapi import FastAPI, Depends, Header, HTTPException
from fastapi.testclient import TestClient
app = FastAPI()
calls = []
def require_trace(x_trace_id: str | None = Header(None)):
if x_trace_id is None:
raise HTTPException(400, detail={"header": "X-Trace-Id"})
return x_trace_id
@app.get("/work")
def work(trace: str = Depends(require_trace)):
calls.append(trace)
return {"accepted": True}
client = TestClient(app)
print(client.get("/work").status_code, len(calls))
print(client.get("/work", headers={"X-Trace-Id": "T1"}).status_code)
print(calls)
Баромад:
400 0
200
['T1']
Занҷир ва кеш дар ҳудуди дархост
Худи вобастагӣ ҳам метавонад Depends қабул кунад. FastAPI аввал сатҳи поёнии занҷирро ҳисоб мекунад. Агар чанд шоха як вобастагиро талаб кунанд, бо пешфарз натиҷааш дар ҳудуди як дархост дубора истифода мешавад. Ин кеши умумии байни корбарон нест: дархости нав функсияро аз нав даъват мекунад. Мисол нишон медиҳад, ки base барои ҳар дархост як бор иҷро мешавад.
from fastapi import FastAPI, Depends
from fastapi.testclient import TestClient
app = FastAPI()
calls = []
def base():
calls.append(1)
return 4
def doubled(value: int = Depends(base)):
return value * 2
@app.get("/pair")
def pair(a: int = Depends(base), b: int = Depends(doubled)):
return [a, b]
client = TestClient(app)
print(client.get("/pair").json(), len(calls))
print(client.get("/pair").json(), len(calls))
Баромад:
[4, 8] 1
[4, 8] 2
Дар дохил чӣ рӯй медиҳад: аввал шахсият, баъд ҳуқуқ
Вобастагиҳо графи омодасозии дархостро ташкил медиҳанд. FastAPI сигнатураҳоро дида, параметрҳоро аз манбаъҳои лозим мехонад, вобастагиҳои дохилиро ҳисоб мекунад ва натиҷаҳои тайёрро ба сатҳи боло медиҳад. Истисно амали минбаъдаро бозмедорад. Ин ба гузаргоҳ монанд аст: аввал ҳуҷҷат, баъд ҳуқуқи даромадан ба ҳуҷраи муайянро месанҷанд.
Шиносоӣ (authentication) ба «шумо кӣ ҳастед?» ва иҷозатдиҳӣ (authorization) ба «чӣ кор карда метавонед?» ҷавоб медиҳад. Дар масъалаҳои курс калиди номаълум ё набуда ба 401 ва корбари шинохташудаи бе нақши лозим ба 403 меорад. Танҳо баъд аз ин амали захира иҷро мешавад. X-Api-Key созиши барнома аст; FastAPI чунин калидро худкор намесанҷад. Барои тарҳҳои воқеии Bearer/OAuth2 воситаҳои fastapi.security ҳастанд, вале нигоҳдорӣ ва санҷиши токенҳо тарҳрезии алоҳида мехоҳанд.
Хатоҳои маъмул ва ислоҳи онҳо
Depends(prepare())функсияро хеле барвақт даъват мекунад. Худи функсияро диҳед:Depends(prepare).x_trace_id: str = ""беHeaderquery-ро мехонад, на сарлавҳаро. Манбаъро боHeader(...)ошкор нишон диҳед.x_api_key: str = Header()ҳангоми набудан 422 медиҳад. Агар шартнома 401-и худро талаб кунад, набуданро иҷозат дода, дар дохили вобастагӣ санҷед.key.lower()пеш аз муқоиса сирро тағйир медиҳад. Фарқи ҳарфҳои номи сарлавҳаро нодида гирифтан мумкин, вале қимати калидро дақиқ муқоиса кунед.Depends(current_user)бе санҷиши нақш шахсиятро тасдиқ мекунад, на ҳуқуқро. Вобастагии алоҳидае илова кунед, ки натиҷаи санҷиши корбарро истифода барад.
Ёддошт
| Вазифа | Восита |
|---|---|
| Омода кардани аргумент | value = Depends(func) |
| Гирифтани сарлавҳа | Header(...) |
| Иҷозати набудани сарлавҳа | Header(None) ва навъи мувофиқ |
| Боздоштан пеш аз масир | raise HTTPException(...) дар вобастагӣ |
| Истифодаи дубораи санҷиш | вобастагӣ дар дохили вобастагӣ |
| Фарқ кардани радкуниҳо | 401 — шахсият, 403 — ҳуқуқ |