fix: Enhance Apps Script language handling and improve response parsing logic

This commit is contained in:
Abolfazl
2026-05-13 05:44:22 +03:30
parent 45c39af110
commit 00edfe95c2
2 changed files with 35 additions and 12 deletions
+30 -9
View File
@@ -110,6 +110,7 @@ class DomainFronter:
"sec-fetch-site",
)
_SAFE_RETRY_METHODS = {"GET", "HEAD", "OPTIONS"}
_APPS_SCRIPT_DEFAULT_LANG = "en"
def __init__(self, config: dict):
self.connect_host = config.get("google_ip", "216.239.38.120")
@@ -128,6 +129,9 @@ class DomainFronter:
self._script_idx = 0
self.script_id = self._script_ids[0] # backward compat / logging
self._dev_available = False # True if /dev endpoint works (no redirect, ~400ms faster)
self._apps_script_lang = str(
config.get("apps_script_lang", self._APPS_SCRIPT_DEFAULT_LANG)
).strip().lower() or self._APPS_SCRIPT_DEFAULT_LANG
# Simple execution monitor: log total consumed Apps Script executions.
self._execution_report_interval = 5.0
@@ -597,10 +601,13 @@ class DomainFronter:
payload = json.dumps(
{"m": "GET", "u": "http://example.com/", "k": self.auth_key}
).encode()
path = f"/macros/s/{sid}/exec?hl={self._apps_script_lang}"
request = (
f"POST /macros/s/{sid}/exec HTTP/1.1\r\n"
f"POST {path} HTTP/1.1\r\n"
f"Host: {self.http_host}\r\n"
"Content-Type: application/json\r\n"
"Accept: application/json,text/plain,*/*\r\n"
"Accept-Language: en-US,en;q=0.9\r\n"
f"Content-Length: {len(payload)}\r\n"
"Connection: close\r\n\r\n"
).encode() + payload
@@ -952,7 +959,17 @@ class DomainFronter:
def _exec_path_for_sid(self, sid: str) -> str:
"""Build the /macros/s/<sid>/(dev|exec) path for a specific script ID."""
return f"/macros/s/{sid}/{'dev' if self._dev_available else 'exec'}"
endpoint = "dev" if self._dev_available else "exec"
# Force Google Apps Script UI/errors to English for stable diagnostics.
return f"/macros/s/{sid}/{endpoint}?hl={self._apps_script_lang}"
def _apps_script_headers(self) -> dict[str, str]:
"""Headers for Apps Script relay calls (control-plane, not target origin)."""
return {
"content-type": "application/json",
"accept": "application/json,text/plain,*/*",
"accept-language": "en-US,en;q=0.9",
}
async def _flush_pool(self):
"""Close all pooled connections (they may be stale after errors)."""
async with self._pool_lock:
@@ -1140,13 +1157,13 @@ class DomainFronter:
payload = json.dumps(
{"m": "GET", "u": "http://example.com/", "k": self.auth_key}
).encode()
hdrs = {"content-type": "application/json"}
hdrs = self._apps_script_headers()
sid = self._script_ids[0]
# Test /dev endpoint — returns data inline (no 302 redirect).
# If it works, saves ~400ms per request by eliminating one round trip.
try:
dev_path = f"/macros/s/{sid}/dev"
dev_path = f"/macros/s/{sid}/dev?hl={self._apps_script_lang}"
t0 = time.perf_counter()
self._record_execution(sid)
status, _, body = await asyncio.wait_for(
@@ -1167,7 +1184,7 @@ class DomainFronter:
# Fallback: warm up with /exec
try:
exec_path = f"/macros/s/{sid}/exec"
exec_path = f"/macros/s/{sid}/exec?hl={self._apps_script_lang}"
t0 = time.perf_counter()
self._record_execution(sid)
await asyncio.wait_for(
@@ -1233,7 +1250,7 @@ class DomainFronter:
await asyncio.wait_for(
self._h2.request(
method="POST", path=path, host=self.http_host,
headers={"content-type": "application/json"},
headers=self._apps_script_headers(),
body=json.dumps(payload).encode(),
),
timeout=20,
@@ -2595,7 +2612,7 @@ class DomainFronter:
t0 = time.perf_counter()
status, headers, body = await (self._pick_h2() or self._h2).request(
method="POST", path=path, host=self.http_host,
headers={"content-type": "application/json"},
headers=self._apps_script_headers(),
body=json_body,
timeout=self._relay_timeout,
)
@@ -2626,7 +2643,7 @@ class DomainFronter:
status, headers, body = await (self._pick_h2() or self._h2).request(
method="POST", path=path, host=self.http_host,
headers={"content-type": "application/json"},
headers=self._apps_script_headers(),
body=json_body,
timeout=self._relay_timeout,
)
@@ -2664,6 +2681,8 @@ class DomainFronter:
request_lines = [
f"{redirect_method} {rpath} HTTP/1.1",
f"Host: {parsed.netloc}",
"Accept: application/json,text/plain,*/*",
"Accept-Language: en-US,en;q=0.9",
"Accept-Encoding: gzip",
"Connection: keep-alive",
]
@@ -2693,6 +2712,8 @@ class DomainFronter:
f"POST {path} HTTP/1.1\r\n"
f"Host: {self.http_host}\r\n"
f"Content-Type: application/json\r\n"
f"Accept: application/json,text/plain,*/*\r\n"
f"Accept-Language: en-US,en;q=0.9\r\n"
f"Content-Length: {len(json_body)}\r\n"
f"Accept-Encoding: gzip\r\n"
f"Connection: keep-alive\r\n"
@@ -2745,7 +2766,7 @@ class DomainFronter:
status, headers, body = await asyncio.wait_for(
(self._pick_h2() or self._h2).request(
method="POST", path=path, host=self.http_host,
headers={"content-type": "application/json"},
headers=self._apps_script_headers(),
body=json_body,
timeout=batch_timeout,
),