diff --git a/src/proxy_server.py b/src/proxy_server.py
index 7e17b52..93416eb 100644
--- a/src/proxy_server.py
+++ b/src/proxy_server.py
@@ -264,29 +264,68 @@ class ProxyServer:
def _log_response_summary(self, url: str, response: bytes):
status, headers, body = self.fronter._split_raw_response(response)
host = (urlparse(url).hostname or "").lower()
+
if status >= 300 or self._should_trace_host(host):
- location = headers.get("location", "")
- server = headers.get("server", "")
- cf_ray = headers.get("cf-ray", "")
- content_type = headers.get("content-type", "")
+ location = headers.get("location", "") or "-"
+ server = headers.get("server", "") or "-"
+ cf_ray = headers.get("cf-ray", "") or "-"
+ content_type = headers.get("content-type", "") or "-"
body_len = len(body)
+
body_hint = "-"
- if "text/html" in content_type.lower() and body:
- sample = body[:800].decode(errors="replace").lower()
+ rate_limited = False
+
+ # Handle text-like responses (HTML, plain text, JSON…)
+ if ("text" in content_type.lower() or "json" in content_type.lower()) and body:
+ sample = body[:1200].decode(errors="replace").lower()
+
+ # --- Structured HTML title extraction ---
if "
" in sample and "" in sample:
title = sample.split("", 1)[1].split("", 1)[0]
- body_hint = title[:120]
+ body_hint = title.strip()[:120] or "-"
+
+ # --- Known content patterns ---
elif "captcha" in sample:
body_hint = "captcha"
elif "turnstile" in sample:
body_hint = "turnstile"
elif "loading" in sample:
body_hint = "loading"
- log.info(
- "RESP ← %s status=%s type=%s len=%s server=%s location=%s cf-ray=%s hint=%s",
- host or url[:60], status, content_type or "-", body_len,
- server or "-", location or "-", cf_ray or "-", body_hint,
+
+ # --- Rate-limit / quota markers ---
+ rate_limit_markers = (
+ "too many",
+ "rate limit",
+ "quota",
+ "quota exceeded",
+ "request limit",
+ "دفعات زیاد",
+ "بیش از حد",
+ "سرویس در طول یک روز",
+ )
+
+ if any(m in sample for m in rate_limit_markers):
+ rate_limited = True
+ body_hint = "quota_exceeded"
+
+ log_msg = (
+ "RESP ← %s status=%s type=%s len=%s server=%s location=%s cf-ray=%s hint=%s"
)
+ log_args = (
+ host or url[:60],
+ status,
+ content_type,
+ body_len,
+ server,
+ location,
+ cf_ray,
+ body_hint,
+ )
+
+ if rate_limited:
+ log.warning("RATE LIMIT detected! " + log_msg, *log_args)
+ else:
+ log.info(log_msg, *log_args)
async def start(self):
http_srv = await asyncio.start_server(self._on_client, self.host, self.port)