Depends: protecting and swapping parts of a service
Anyone who can reach the service can spend your model budget. A dependency that checks a key fixes that, and the same tool swaps the model client in tests.
def require_service_key(x_api_key: Annotated[str | None, Header()] = None):
if x_api_key != os.environ.get("SERVICE_KEY", "team-key-1"):
raise HTTPException(status_code=401, detail="send your team key in X-API-Key")@app.post("/triage", dependencies=[Depends(require_service_key)])require_service_key reads an X-API-Key header. Listed in dependencies=, it runs before the endpoint on every request, and its HTTPException stops the request before the model is called. The X- prefix is the usual start for a header an application makes up.
Swapping the model client
To call the service from Python without starting the model API, replace get_model_client with a function that returns a test client for model_api.app:
from fastapi.testclient import TestClient
import model_api
import service
def fake_model_client():
return TestClient(model_api.app, headers={"Authorization": "Bearer sk-local-123"})
service.app.dependency_overrides[service.get_model_client] = fake_model_client
client = TestClient(service.app)
ticket = {"id": 2, "text": "My parcel has not arrived"}
print(client.post("/triage", json=ticket).status_code)
print(client.post("/triage", json=ticket, headers={"X-API-Key": "team-key-1"}).json())dependency_overrides is a dictionary on the app: whenever an endpoint depends on the key, FastAPI calls the value instead. The endpoint code does not change, and it cannot tell.
The first request had no service key and stopped at 401. The second passed, called the stand-in in memory, and sorted the ticket. The model API's own key and the service's key are separate: one says the service may call the model, the other says a client may call the service.
- Send
X-API-Key: wrongand print the body. - Set
SERVICE_KEYin the environment before starting Python, and send that value. - Make
fake_model_clientreturn a client with a wrong model key. What status does the service send back?
Little by little, you're building something great.