4 changed files with 129 additions and 0 deletions
@ -0,0 +1,30 @@ |
|||
from typing import Optional |
|||
|
|||
from fastapi import FastAPI, HTTPException, Security, status |
|||
from fastapi.security import APIKeyHeader |
|||
|
|||
app = FastAPI() |
|||
|
|||
API_KEY = "supersecret" |
|||
API_KEY_NAME = "X-API-Key" |
|||
|
|||
api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False) |
|||
|
|||
|
|||
async def get_api_key(api_key: Optional[str] = Security(api_key_header)) -> str: |
|||
if api_key is None: |
|||
raise HTTPException( |
|||
status_code=status.HTTP_403_FORBIDDEN, |
|||
detail="Not authenticated", |
|||
) |
|||
if api_key != API_KEY: |
|||
raise HTTPException( |
|||
status_code=status.HTTP_403_FORBIDDEN, |
|||
detail="Invalid API key", |
|||
) |
|||
return api_key |
|||
|
|||
|
|||
@app.get("/protected-route") |
|||
async def protected_route(api_key: str = Security(get_api_key)): |
|||
return {"message": "You are authorized"} |
|||
@ -0,0 +1,33 @@ |
|||
import pytest |
|||
from fastapi.testclient import TestClient |
|||
|
|||
|
|||
@pytest.fixture(name="client") |
|||
def get_client() -> TestClient: |
|||
from docs_src.security.tutorial_api_key_header import app |
|||
|
|||
return TestClient(app) |
|||
|
|||
|
|||
def test_no_api_key(client: TestClient) -> None: |
|||
response = client.get("/protected-route") |
|||
assert response.status_code == 403, response.text |
|||
assert response.json() == {"detail": "Not authenticated"} |
|||
|
|||
|
|||
def test_invalid_api_key(client: TestClient) -> None: |
|||
response = client.get( |
|||
"/protected-route", |
|||
headers={"X-API-Key": "wrong"}, |
|||
) |
|||
assert response.status_code == 403, response.text |
|||
assert response.json() == {"detail": "Invalid API key"} |
|||
|
|||
|
|||
def test_valid_api_key(client: TestClient) -> None: |
|||
response = client.get( |
|||
"/protected-route", |
|||
headers={"X-API-Key": "supersecret"}, |
|||
) |
|||
assert response.status_code == 200, response.text |
|||
assert response.json() == {"message": "You are authorized"} |
|||
Loading…
Reference in new issue