diff --git a/CHANGELOG.md b/CHANGELOG.md index ad61965..eb2c97a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.32.1 - 2026-05-17 + +- Suppressed stdout request logging for routine polling endpoints such as `/api/queue` and `/api/watchlist/refresh-status`, reducing noisy access-log spam during normal browser use. + ## 0.32.0 - 2026-05-17 - Changed bulk `Refresh All` processing to pace requests with a configurable delay between shows, reducing the chance of flooding upstream episode sources on large watchlists. diff --git a/README.md b/README.md index 361ac17..861dd38 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A local web UI for a system-wide `ani-cli` install. -Current version: `0.32.0` +Current version: `0.32.1` ## Project Layout @@ -159,6 +159,7 @@ The app currently includes: - Background `Refresh All` execution with status polling, no inline thumbnail downloads during the bulk job, and a configurable delay between shows to reduce upstream request bursts. - Optional scheduled background watchlist refreshes with Config page controls for enable/disable and refresh period. - Scheduled background refresh runs now log queue, start, and completion status to stdout so container logs show whether they finished successfully, with errors, or failed. +- Routine browser polling endpoints such as the search-page queue poll and watchlist refresh-status poll now stay quiet in stdout request logs to reduce log spam. - Search and Watchlist polling now use a shared serial browser polling helper so slow responses do not cause overlapping poll requests to pile up in the background. - That shared browser polling helper now also tears itself down on page unload and uses chained `setTimeout` scheduling instead of a bare repeating interval. - Controlled shutdown and runtime reset now cancel active download workers when waiting for teardown, reducing the chance of orphaned background downloads outliving the web process. diff --git a/VERSION b/VERSION index 9eb2aa3..fd9620c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.32.0 +0.32.1 diff --git a/app_support.py b/app_support.py index 4482bbc..2ec4b09 100644 --- a/app_support.py +++ b/app_support.py @@ -16,7 +16,7 @@ from uuid import uuid4 PROJECT_ROOT = Path(__file__).resolve().parent ANI_CLI = os.environ.get("ANI_CLI_BIN") or shutil.which("ani-cli") or "ani-cli" APP_NAME = "ani-cli-web" -VERSION = "0.32.0" +VERSION = "0.32.1" ALLANIME_BASE = "allanime.day" ALLANIME_API = f"https://api.{ALLANIME_BASE}" ALLANIME_REFERER = "https://allmanga.to" diff --git a/http_handler.py b/http_handler.py index fa063ef..e057a20 100644 --- a/http_handler.py +++ b/http_handler.py @@ -70,6 +70,7 @@ def dependency_status(): class Handler(BaseHTTPRequestHandler): server_version = "AniCliWeb/1.0" remote_token_cookie_name = "ani_cli_web_token" + quiet_poll_paths = {"/api/queue", "/api/watchlist/refresh-status"} def _context(self): context = getattr(self, "handler_context", None) or getattr(type(self), "handler_context", None) @@ -467,6 +468,9 @@ class Handler(BaseHTTPRequestHandler): self.error(HTTPStatus.INTERNAL_SERVER_ERROR, "Internal server error.") def log_message(self, fmt, *args): + parsed = urlparse(getattr(self, "path", "") or "") + if self.command == "GET" and parsed.path in Handler.quiet_poll_paths: + return print(f"{self.address_string()} - {fmt % args}") diff --git a/test_app.py b/test_app.py index a926a12..cf72557 100644 --- a/test_app.py +++ b/test_app.py @@ -1408,6 +1408,28 @@ class HandlerRouteTests(unittest.TestCase): class TemplateHelperTests(unittest.TestCase): + def test_log_message_skips_queue_poll_requests(self): + handler = object.__new__(APP.Handler) + handler.path = "/api/queue?page=1&per_page=10" + handler.command = "GET" + handler.address_string = lambda: "127.0.0.1" + + with mock.patch("builtins.print") as print_mock: + APP.Handler.log_message(handler, '"GET /api/queue?page=1&per_page=10 HTTP/1.1" %s -', 200) + + print_mock.assert_not_called() + + def test_log_message_keeps_non_poll_requests(self): + handler = object.__new__(APP.Handler) + handler.path = "/api/config" + handler.command = "GET" + handler.address_string = lambda: "127.0.0.1" + + with mock.patch("builtins.print") as print_mock: + APP.Handler.log_message(handler, '"GET /api/config HTTP/1.1" %s -', 200) + + print_mock.assert_called_once() + def test_page_links_marks_active_page(self): markup = APP.render_page_links("config") self.assertIn('class="page-link active" href="/config"', markup)