From fca3ae254a07896f7d3df5c34e150d8cbe02e39b Mon Sep 17 00:00:00 2001 From: Kirill Kodanev Date: Sat, 13 Sep 2025 16:06:46 +0300 Subject: [PATCH] Enhance query API code ADD DOMAIN: cloud.hetzner.com --- domains.txt | 3 +- scripts/generate-configs.sh | 63 ++++++++++++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/domains.txt b/domains.txt index 959f414..c9100ee 100644 --- a/domains.txt +++ b/domains.txt @@ -114,4 +114,5 @@ yt3.ggpht.com yt4.ggpht.com yt.be zona.media -googlevideo.com \ No newline at end of file +googlevideo.com +cloud.hetzner.com \ No newline at end of file diff --git a/scripts/generate-configs.sh b/scripts/generate-configs.sh index 494455a..a1546d1 100644 --- a/scripts/generate-configs.sh +++ b/scripts/generate-configs.sh @@ -87,18 +87,65 @@ while IFS= read -r line || [ -n "$line" ]; do normalized_ok=$((normalized_ok+1)) dbg " -> NORMALIZED: $dom_norm" - dbg " -> Querying API: ${API_URL}${dom_norm}" - resp="$(curl -s --max-time 15 "${API_URL}${dom_norm}" || true)" - preview="$(printf '%s' "$resp" | tr '\n' ' ' | cut -c1-400)" - dbg " -> API response preview: ${preview}" + dbg " -> Querying API: ${API_URL}${dom_norm}" - if ! jq -e . >/dev/null 2>&1 <<<"$resp"; then - api_error=$((api_error+1)) - ERRORS["$dom_norm"]="non-json-response" - dbg " -> non-JSON, skipping" + # параметры retry + max_attempts=3 + attempt=0 + resp="" + http_code=0 + content_type="" + + while :; do + attempt=$((attempt+1)) + # делаем запрос, записываем тело и код отдельно + # --compressed: поддержка gzip + # -sS: показывать ошибки curl в debug (если DEBUG enabled, они попадут в DEBUG_LOG) + # -m: общий timeout + # --connect-timeout: timeout на установление соединения + raw="$(curl -sS --compressed -m 20 --connect-timeout 8 -H 'Accept: application/json' -w '\n%{http_code}\n%{content_type}' "${API_URL}${dom_norm}" 2>>"$DEBUG_LOG" )" || true + + # последний \n%{http_code}\n%{content_type} — отделяем + http_code="$(printf '%s' "$raw" | tail -n1)" + content_type="$(printf '%s' "$raw" | tail -n2 | head -n1)" + resp="$(printf '%s' "$raw" | sed '$d' | sed '$d')" # всё кроме двух последних строк + + preview="$(printf '%s' "$resp" | tr '\n' ' ' | cut -c1-400)" + dbg " -> Attempt #${attempt}: HTTP=${http_code}, Content-Type=${content_type}, preview=${preview}" + + # если получили 200 и content-type похож на json — выходим + if [ "$http_code" = "200" ] && printf '%s' "$content_type" | grep -qEi 'application/(json|javascript)|^text/json'; then + break + fi + + # если тело выглядит как json (на всякий случай), тоже принимаем + if jq -e . >/dev/null 2>&1 <<<"$resp"; then + dbg " -> Body is valid JSON despite HTTP=${http_code}, accepting." + break + fi + + # если исчерпали попытки — помечаем как ошибка + if [ "$attempt" -ge "$max_attempts" ]; then + api_error=$((api_error+1)) + ERRORS["$dom_norm"]="http_${http_code}_or_nonjson" + dbg " -> Failed after ${attempt} attempts: HTTP=${http_code}, preview=${preview}" + resp="" # явный маркер + break + fi + + # backoff: 0.5s, 1s, 2s ... + sleep_time=$(awk "BEGIN {printf \"%.0f\", 0.5 * (2 ^ ($attempt - 1))}") + dbg " -> Retry after ${sleep_time}s..." + sleep "$sleep_time" + done + + # если нет валидного JSON — пропускаем, с логом + if [ -z "$resp" ] || ! jq -e . >/dev/null 2>&1 <<<"$resp"; then + dbg " -> non-JSON or empty response, skipping domain: $dom_norm" continue fi + # error handling if jq -e 'has("error")' <<<"$resp" >/dev/null; then err_msg="$(jq -r '.error' <<<"$resp")"