This commit is contained in:
manya-dogra 2026-08-02 03:57:57 +00:00 committed by GitHub
commit d9e60f2cb7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -33,6 +33,9 @@ Usage:
"""
import logging
import cherrypy
import re
import threading
import time
from cherrypy.process.servers import ServerAdapter
from cheroot.wsgi import Server as WSGIServer
from cheroot.ssl.builtin import BuiltinSSLAdapter
@ -41,6 +44,28 @@ from typing import Any, Tuple, Optional, Dict
logger = logging.getLogger(__name__)
class CherryPyAccessFilter(logging.Filter):
"""Rate-limits access log to one entry per endpoint per 120 s.
Non-200 responses always pass through."""
_PATH_RE = re.compile(r'"[A-Z]+\s+(/[^\s]*)')
def __init__(self, interval: float = 120.0) -> None:
super().__init__()
self.interval = interval
self._last: Dict[str, float] = {}
self._lock = threading.Lock()
def filter(self, record: logging.LogRecord) -> bool:
msg = record.getMessage()
if '" 200 ' not in msg:
return True
key = (m := self._PATH_RE.search(msg)) and m.group(1) or msg
now = time.monotonic()
with self._lock:
if now - self._last.get(key, 0.0) < self.interval:
return False
self._last[key] = now
return True
class CherryPyErrorFilter(logging.Filter):
"""
@ -138,6 +163,18 @@ class CherryPyMgr:
if not has_filter:
error_log.addFilter(CherryPyErrorFilter())
access_filter = CherryPyAccessFilter()
access_log = logging.getLogger('cherrypy.access')
if not any(isinstance(f, CherryPyAccessFilter) for f in access_log.filters):
access_log.addFilter(access_filter)
for name, obj in logging.Logger.manager.loggerDict.items():
if name.startswith('cherrypy.access') and isinstance(obj, logging.Logger):
if not any(isinstance(f, CherryPyAccessFilter) for f in obj.filters):
obj.addFilter(access_filter)
@staticmethod
def create_adapter(
app: Any,