forked from cleveragents/cleveragents-core
2f69358dcf
All 3 simulations tested with the fixed generate prompt that passes the original DoD to the LLM. Results: - SIM12 (Rate Limiter): 7 files — algorithms.py, store.py, middleware.py, config.py, example_app.py, requirements.txt, __init__.py - SIM14 (JSON Validator): 6 files — validator.py, types.py, errors.py, cli.py, requirements.txt, __init__.py - SIM17 (API Tester): 7 files — runner.py, assertions.py, variables.py, reporter.py, cli.py, requirements.txt, test_suite_example.yaml All Python files pass compile() syntax check. All DoD files present. Files written directly via --output-dir, no manual cleanup needed.
105 lines
3.3 KiB
Python
105 lines
3.3 KiB
Python
from flask import Flask, jsonify
|
|
from config import RateLimitConfig, LimitType
|
|
from middleware import rate_limit
|
|
|
|
app = Flask(__name__)
|
|
|
|
# Rate limiting configurations
|
|
token_bucket_config = RateLimitConfig(
|
|
limit=10,
|
|
window=60, # 10 requests per minute
|
|
limit_type=LimitType.IP,
|
|
error_message="Token bucket rate limit exceeded"
|
|
)
|
|
|
|
sliding_window_config = RateLimitConfig(
|
|
limit=5,
|
|
window=30, # 5 requests per 30 seconds
|
|
limit_type=LimitType.IP,
|
|
error_message="Sliding window rate limit exceeded"
|
|
)
|
|
|
|
fixed_window_config = RateLimitConfig(
|
|
limit=20,
|
|
window=60, # 20 requests per minute
|
|
limit_type=LimitType.API_KEY,
|
|
api_key_header="X-API-Key",
|
|
error_message="Fixed window rate limit exceeded"
|
|
)
|
|
|
|
|
|
@app.route("/")
|
|
def index():
|
|
"""Home route without rate limiting."""
|
|
return jsonify({
|
|
"message": "Rate Limiting Example API",
|
|
"endpoints": {
|
|
"/token-bucket": "Token bucket algorithm (10 req/min by IP)",
|
|
"/sliding-window": "Sliding window algorithm (5 req/30s by IP)",
|
|
"/fixed-window": "Fixed window algorithm (20 req/min by API key)"
|
|
}
|
|
})
|
|
|
|
|
|
@app.route("/token-bucket")
|
|
@rate_limit(token_bucket_config, algorithm="token_bucket")
|
|
def token_bucket_endpoint():
|
|
"""Endpoint protected by token bucket rate limiting."""
|
|
return jsonify({
|
|
"message": "Token bucket endpoint accessed successfully",
|
|
"algorithm": "token_bucket",
|
|
"limit": "10 requests per minute per IP"
|
|
})
|
|
|
|
|
|
@app.route("/sliding-window")
|
|
@rate_limit(sliding_window_config, algorithm="sliding_window")
|
|
def sliding_window_endpoint():
|
|
"""Endpoint protected by sliding window rate limiting."""
|
|
return jsonify({
|
|
"message": "Sliding window endpoint accessed successfully",
|
|
"algorithm": "sliding_window",
|
|
"limit": "5 requests per 30 seconds per IP"
|
|
})
|
|
|
|
|
|
@app.route("/fixed-window")
|
|
@rate_limit(fixed_window_config, algorithm="fixed_window")
|
|
def fixed_window_endpoint():
|
|
"""Endpoint protected by fixed window rate limiting."""
|
|
return jsonify({
|
|
"message": "Fixed window endpoint accessed successfully",
|
|
"algorithm": "fixed_window",
|
|
"limit": "20 requests per minute per API key"
|
|
})
|
|
|
|
|
|
@app.route("/health")
|
|
def health():
|
|
"""Health check endpoint without rate limiting."""
|
|
return jsonify({"status": "healthy"})
|
|
|
|
|
|
@app.errorhandler(429)
|
|
def rate_limit_handler(e):
|
|
"""Custom handler for rate limit errors."""
|
|
return jsonify({
|
|
"error": "Rate limit exceeded",
|
|
"message": "Please wait before making more requests"
|
|
}), 429
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("Starting Flask app with rate limiting examples...")
|
|
print("\nEndpoints:")
|
|
print("- GET / : Home page with API information")
|
|
print("- GET /token-bucket : Token bucket (10 req/min by IP)")
|
|
print("- GET /sliding-window : Sliding window (5 req/30s by IP)")
|
|
print("- GET /fixed-window : Fixed window (20 req/min by API key - requires X-API-Key header)")
|
|
print("- GET /health : Health check (no rate limiting)")
|
|
print("\nTesting with curl:")
|
|
print("curl http://localhost:5000/token-bucket")
|
|
print("curl -H 'X-API-Key: test-key' http://localhost:5000/fixed-window")
|
|
print()
|
|
|
|
app.run(debug=True, host="0.0.0.0", port=5000) |