Skip to content

Real-World Examples

This page shows how to use drogue in common production scenarios.


Login Rate Limiting

Prevent brute force attacks on your login endpoint.

Strategy

  • Per-IP limits for unauthenticated requests
  • Per-user limits after authentication
  • Progressive bans after repeated failures

FastAPI Example

from fastapi import FastAPI, Request
from drogue.adapters.fastapi import DrogueLimiter

app = FastAPI()
limiter = DrogueLimiter(app)

@app.post("/login")
@limiter.limit("5/minute")  # 5 attempts per minute per IP
async def login(request: Request):
    # ... authenticate user ...
    pass

@app.post("/login/verify")
@limiter.limit("10/minute")  # More generous after identity is known
async def login_verify(request: Request, user_id: str):
    # ... verify MFA code ...
    pass

Django Example

from drogue.adapters.django import DrogueRateLimiter
from django.http import JsonResponse

limiter = DrogueRateLimiter()

@limiter.limit("5/minute")
def login(request):
    # ... authenticate user ...
    pass

API Key Rate Limiting

Enforce per-key quotas for API access.

Strategy

  • Extract API key from header
  • Different limits per key or plan
  • Cost-based limiting for expensive endpoints

FastAPI Example

from fastapi import FastAPI, Request
from drogue.adapters.fastapi import DrogueLimiter
from drogue.core.identity import HeaderExtractor

app = FastAPI()
limiter = DrogueLimiter(
    app,
    key_func=HeaderExtractor("X-API-Key")  # Extract from API key header
)

@app.get("/api/data")
@limiter.limit("1000/day")  # 1000 requests per day per API key
async def get_data():
    return {"data": "value"}

@app.get("/api/heavy")
@limiter.limit("10/day", cost=10)  # Costs 10x against quota
async def heavy_computation():
    # ... expensive operation ...
    return {"result": "value"}

WebSocket Rate Limiting

Protect WebSocket endpoints from abuse.

Strategy

  • Message rate limits per connection
  • Connection limits per user
  • DDoS protection for upgrade requests

FastAPI Example

from fastapi import FastAPI, WebSocket
from drogue.adapters.fastapi import DrogueLimiter

app = FastAPI()
limiter = DrogueLimiter(app)

@app.websocket("/ws/chat")
@limiter.limit_ws("30/minute")  # 30 messages per minute
async def websocket_chat(websocket: WebSocket):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        # ... process message ...
        await websocket.send_text(f"Echo: {data}")

Reverse Proxy Deployment

Running drogue behind Nginx, Traefik, or Cloudflare.

Strategy

  • Configure trusted proxies
  • Read real client IP from X-Forwarded-For
  • Prevent header spoofing

Nginx Configuration

server {
    listen 80;
    server_name api.example.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Drogue Configuration

from fastapi import FastAPI
from drogue.adapters.fastapi import DrogueLimiter

app = FastAPI()
limiter = DrogueLimiter(
    app,
    trusted_proxies=["127.0.0.1", "10.0.0.0/8"]
)

Cloudflare

When using Cloudflare, configure drogue to trust Cloudflare IP ranges:

# Cloudflare IPv4 ranges
CLOUDFLARE_IPS = [
    "173.245.48.0/20",
    "103.21.244.0/22",
    "103.22.200.0/22",
    "103.31.4.0/22",
    "141.101.64.0/18",
    "108.162.192.0/18",
    "190.93.240.0/20",
    "188.114.96.0/20",
    "197.234.240.0/22",
    "198.41.128.0/17",
    "162.158.0.0/15",
    "104.16.0.0/13",
    "104.24.0.0/14",
    "172.64.0.0/13",
    "131.0.72.0/22",
]

limiter = DrogueLimiter(
    app,
    trusted_proxies=CLOUDFLARE_IPS
)

Microservices Rate Limiting

Rate limiting internal service-to-service communication.

Strategy

  • Per-service rate limits
  • Service identity extraction
  • Centralized or distributed rate limiting

FastAPI Example

from fastapi import FastAPI, Request
from drogue.adapters.fastapi import DrogueLimiter
from drogue.core.identity import HeaderExtractor

app = FastAPI()
limiter = DrogueLimiter(
    app,
    key_func=HeaderExtractor("X-Service-Name")  # Identify by service name
)

@app.get("/api/internal/data")
@limiter.limit("1000/minute")  # 1000 requests per minute per service
async def internal_data():
    return {"data": "value"}

@app.get("/api/internal/heavy")
@limiter.limit("100/minute", cost=5)  # Expensive endpoint
async def heavy_internal():
    # ... complex computation ...
    return {"result": "value"}

Multi-Tenant SaaS

from fastapi import FastAPI, Request
from drogue.adapters.fastapi import DrogueLimiter
from drogue.core.identity import HeaderExtractor

app = FastAPI()
limiter = DrogueLimiter(
    app,
    key_func=HeaderExtractor("X-Tenant-ID")  # Identify by tenant
)

@app.get("/api/tenant/data")
@limiter.limit("5000/hour")  # Per-tenant limit
async def tenant_data():
    return {"data": "value"}

Summary

Scenario Key Extractor Rate Limit Protection Layer
Login IP 5/minute Brute force
API Key Header 1000/day Abuse
WebSocket Connection 30/minute Real-time abuse
Reverse Proxy X-Forwarded-For Per-client Network layer
Microservices Service name Per-service Internal abuse