Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
api_call.py220 linesDownload Raw Back to bin
1"""2World-Level API Resilience Toolkit3====================================4Handles: IP blocks, timeouts, rate limits, SSL errors, connection drops5 6Usage:7  python api_call.py GET https://api.example.com/endpoint8  python api_call.py POST https://api.example.com/data '{"key":"value"}'9  python api_call.py GET https://api.example.com --proxy http://127.0.0.1:808010 11Features:12  - Auto Retry with Exponential Backoff13  - Random User-Agent Rotation14  - Connection Timeout Handling15  - Rate Limit Detection (429) with Auto-Wait16  - SSL Error Bypass Option17  - Proxy Support (for mitmproxy or any proxy)18  - Detailed Error Diagnosis19"""20 21import sys22import time23import random24import json25import urllib.request26import urllib.error27import urllib.parse28import ssl29import os30 31# ─────────────────────────────────────────────32# CONFIGURATION - Edit these as needed33# ─────────────────────────────────────────────34MAX_RETRIES = 535INITIAL_WAIT = 2       # seconds before first retry36TIMEOUT = 30           # request timeout in seconds37BYPASS_SSL = False     # Set True if getting SSL errors (self-signed certs)38PROXY = None           # e.g. "http://127.0.0.1:8080" for mitmproxy39# ─────────────────────────────────────────────40 41USER_AGENTS = [42    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0 Safari/537.36",43    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0",44    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Safari/605.1.15",45    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Chrome/122.0 Safari/537.36",46    "python-httpx/0.27.0",47    "axios/1.7.2",48    "curl/8.7.1",49]50 51DIAGNOSABLE_ERRORS = {52    400: "BAD REQUEST - Check your payload/params format",53    401: "UNAUTHORIZED - Check your API key/token",54    403: "FORBIDDEN - IP may be blocked or permissions missing",55    404: "NOT FOUND - Check the URL/endpoint",56    408: "REQUEST TIMEOUT - Server too slow, try increasing TIMEOUT",57    429: "RATE LIMITED - Waiting before retry...",58    500: "SERVER ERROR - Their problem, will retry",59    502: "BAD GATEWAY - Proxy/CDN issue, retrying",60    503: "SERVICE UNAVAILABLE - Server overloaded, retrying",61    504: "GATEWAY TIMEOUT - Network issue, retrying",62}63 64 65def make_request(method, url, data=None, headers=None, proxy=None, bypass_ssl=False, timeout=30):66    """Core request function with all resilience features."""67    if headers is None:68        headers = {}69 70    headers["User-Agent"] = random.choice(USER_AGENTS)71    headers["Accept"] = "application/json, text/plain, */*"72    headers["Accept-Language"] = "en-US,en;q=0.9"73    headers["Connection"] = "keep-alive"74 75    # SSL context76    ctx = ssl.create_default_context()77    if bypass_ssl:78        ctx.check_hostname = False79        ctx.verify_mode = ssl.CERT_NONE80 81    # Proxy handler82    handlers = []83    if proxy:84        proxy_handler = urllib.request.ProxyHandler({"http": proxy, "https": proxy})85        handlers.append(proxy_handler)86 87    https_handler = urllib.request.HTTPSHandler(context=ctx)88    handlers.append(https_handler)89    opener = urllib.request.build_opener(*handlers)90 91    # Build request92    body = None93    if data:94        if isinstance(data, dict):95            body = json.dumps(data).encode("utf-8")96            headers["Content-Type"] = "application/json"97        else:98            body = data.encode("utf-8") if isinstance(data, str) else data99 100    req = urllib.request.Request(url, data=body, headers=headers, method=method.upper())101 102    response = opener.open(req, timeout=timeout)103    raw = response.read()104    status = response.status105 106    try:107        result = json.loads(raw)108    except Exception:109        result = raw.decode("utf-8", errors="replace")110 111    return status, result112 113 114def api_call(method, url, data=None, headers=None):115    """Resilient API call with retry, backoff, and diagnosis."""116    wait = INITIAL_WAIT117    last_error = None118 119    for attempt in range(1, MAX_RETRIES + 1):120        try:121            print(f"\n[Attempt {attempt}/{MAX_RETRIES}] {method.upper()} {url}")122            status, result = make_request(123                method, url, data=data, headers=headers,124                proxy=PROXY, bypass_ssl=BYPASS_SSL, timeout=TIMEOUT125            )126 127            if status == 429:128                retry_after = wait * 3129                print(f"  ⚠ {DIAGNOSABLE_ERRORS[429]}")130                print(f"  Waiting {retry_after}s before next attempt...")131                time.sleep(retry_after)132                wait = min(wait * 2, 120)133                continue134 135            if 200 <= status < 300:136                print(f"  ✓ SUCCESS ({status})")137                return status, result138 139            msg = DIAGNOSABLE_ERRORS.get(status, f"HTTP {status} - Unexpected error")140            print(f"  ✗ {msg}")141 142            if status in (400, 401, 403, 404):143                print("  → Non-retryable error. Stopping.")144                return status, result145 146        except urllib.error.URLError as e:147            reason = str(e.reason)148            print(f"  ✗ CONNECTION ERROR: {reason}")149 150            if "SSL" in reason or "certificate" in reason.lower():151                print("  DIAGNOSIS: SSL/Certificate issue.")152                print("  FIX: Set BYPASS_SSL = True in this script")153            elif "timed out" in reason.lower():154                print("  DIAGNOSIS: Connection timed out.")155                print("  FIX: Increase TIMEOUT or check network")156            elif "Name or service not known" in reason or "getaddrinfo" in reason:157                print("  DIAGNOSIS: DNS resolution failed.")158                print("  FIX: Check internet / try a different DNS (1.1.1.1)")159            else:160                print("  DIAGNOSIS: Network/connectivity issue.")161                print("  FIX: Try mitmproxy or a proxy for routing")162 163            last_error = e164 165        except TimeoutError:166            print(f"  ✗ TIMEOUT after {TIMEOUT}s")167            last_error = "Timeout"168 169        except Exception as e:170            print(f"  ✗ UNEXPECTED: {e}")171            last_error = e172 173        if attempt < MAX_RETRIES:174            print(f"  ↻ Retrying in {wait}s... (backoff)")175            time.sleep(wait)176            wait = min(wait * 2, 60)177 178    print(f"\n✗ All {MAX_RETRIES} attempts failed. Last error: {last_error}")179    return None, None180 181 182def main():183    if len(sys.argv) < 3:184        print("Usage: python api_call.py <METHOD> <URL> [JSON_BODY] [--proxy PROXY_URL]")185        print("Examples:")186        print("  python api_call.py GET https://httpbin.org/get")187        print("  python api_call.py POST https://httpbin.org/post '{\"key\":\"value\"}'")188        print("  python api_call.py GET https://api.github.com/repos/cli/cli --proxy http://127.0.0.1:8080")189        sys.exit(1)190 191    method = sys.argv[1]192    url = sys.argv[2]193    data = None194    global PROXY195 196    args = sys.argv[3:]197    for i, arg in enumerate(args):198        if arg == "--proxy" and i + 1 < len(args):199            PROXY = args[i + 1]200        elif arg.startswith("{") or arg.startswith("["):201            try:202                data = json.loads(arg)203            except Exception:204                data = arg205 206    status, result = api_call(method, url, data=data)207 208    if result is not None:209        print("\n─── RESPONSE ─────────────────────────────")210        if isinstance(result, (dict, list)):211            print(json.dumps(result, indent=2, ensure_ascii=False))212        else:213            print(result)214        print("─────────────────────────────────────────")215 216 217if __name__ == "__main__":218    main()219
220 
codekingpro/portable-devtools · Team Ai