98 lines
No EOL
3.3 KiB
Python
98 lines
No EOL
3.3 KiB
Python
"""
|
|
Caching middleware for the OpenEventDatabase.
|
|
"""
|
|
|
|
from oedb.utils.logging import logger
|
|
|
|
class CacheMiddleware:
|
|
"""
|
|
Middleware that adds caching headers to responses.
|
|
|
|
This middleware adds appropriate Cache-Control headers to responses
|
|
based on the endpoint and request method. It helps reduce server load
|
|
by allowing clients to cache responses for a specified period.
|
|
"""
|
|
|
|
def __init__(self, default_max_age=60):
|
|
"""
|
|
Initialize the middleware with default caching settings.
|
|
|
|
Args:
|
|
default_max_age: Default max-age in seconds for cacheable responses.
|
|
"""
|
|
self.default_max_age = default_max_age
|
|
|
|
# Define caching rules for different endpoints
|
|
# Format: (endpoint_prefix, method, max_age)
|
|
self.caching_rules = [
|
|
# Cache GET requests to /event for 60 seconds
|
|
('/event', 'GET', 60),
|
|
# Cache GET requests to /stats for 300 seconds (5 minutes)
|
|
('/stats', 'GET', 300),
|
|
# Cache GET requests to /demo for 3600 seconds (1 hour)
|
|
('/demo', 'GET', 3600),
|
|
# Don't cache search results
|
|
('/event/search', 'POST', 0),
|
|
]
|
|
|
|
def process_response(self, req, resp, resource, params):
|
|
"""
|
|
Add caching headers to the response.
|
|
|
|
Args:
|
|
req: The request object.
|
|
resp: The response object.
|
|
resource: The resource object.
|
|
params: The request parameters.
|
|
"""
|
|
# Don't add caching headers for error responses
|
|
if resp.status_code >= 400:
|
|
self._add_no_cache_headers(resp)
|
|
return
|
|
|
|
# Check if the request matches any caching rules
|
|
max_age = self._get_max_age(req)
|
|
|
|
if max_age > 0:
|
|
# Add caching headers
|
|
logger.debug(f"Adding caching headers with max-age={max_age} to {req.method} {req.path}")
|
|
resp.set_header('Cache-Control', f'public, max-age={max_age}')
|
|
resp.set_header('Vary', 'Accept-Encoding')
|
|
else:
|
|
# Add no-cache headers
|
|
self._add_no_cache_headers(resp)
|
|
|
|
def _get_max_age(self, req):
|
|
"""
|
|
Determine the max-age value for the current request.
|
|
|
|
Args:
|
|
req: The request object.
|
|
|
|
Returns:
|
|
int: The max-age value in seconds, or 0 for no caching.
|
|
"""
|
|
# Check if the request matches any caching rules
|
|
for endpoint, method, max_age in self.caching_rules:
|
|
if req.path.startswith(endpoint) and req.method == method:
|
|
return max_age
|
|
|
|
# Default: no caching for write operations, default max-age for read operations
|
|
if req.method in ('POST', 'PUT', 'DELETE', 'PATCH'):
|
|
return 0
|
|
elif req.method == 'GET':
|
|
return self.default_max_age
|
|
else:
|
|
return 0
|
|
|
|
def _add_no_cache_headers(self, resp):
|
|
"""
|
|
Add headers to prevent caching.
|
|
|
|
Args:
|
|
resp: The response object.
|
|
"""
|
|
logger.debug("Adding no-cache headers to response")
|
|
resp.set_header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
|
|
resp.set_header('Pragma', 'no-cache')
|
|
resp.set_header('Expires', '0') |