Check request

#!/bin/bash perform_check_request() { local access_id="$1" local access_code="$2" shift 2 local -a ip_list=("$@") local timeout=30 # === Input Validation === if [[ -z "$access_id" ]]; then echo "Error: access_id must be a non-empty string" >&2 return 1 fi if [[ -z "$access_code" ]]; then echo "Error: access_code must be a non-empty string" >&2 return 1 fi if [[ ${#ip_list[@]} -eq 0 ]]; then echo "Error: ip_list must be a non-empty list of strings" >&2 return 1 fi local url="https://www.serversnug.com/api/public/v1/check/" # === Build JSON payload safely using jq === local payload payload=$(jq -n \ --arg access_id "$access_id" \ --arg access_code "$access_code" \ --argjson ip "$(printf '%s\n' "${ip_list[@]}" | jq -R . | jq -s .)" \ '{access_id: $access_id, access_code: $access_code, ip: $ip}') || { echo "Error: Failed to construct JSON payload" >&2 return 1 } # === Make the request === local tmpfile tmpfile=$(mktemp) || { echo "Error: Failed to create temporary file" >&2 return 1 } local http_code http_code=$(curl -sS --max-time "$timeout" \ -w "%{http_code}" \ -o "$tmpfile" \ -X POST \ -H "Content-Type: application/json" \ -d "$payload" \ "$url") local curl_exit=$? local response_body response_body=$(<"$tmpfile") rm -f "$tmpfile" # Handle curl-level failures if [[ $curl_exit -ne 0 ]]; then if [[ $curl_exit -eq 28 ]]; then echo "Error: Request timed out while contacting ServerSnug API" >&2 else echo "Error: Failed to connect to ServerSnug API (network issue)" >&2 fi return 1 fi # === Validate JSON response === if ! echo "$response_body" | jq empty > /dev/null 2>&1; then echo "Error: Invalid JSON response from server. Status code: $http_code" >&2 return 1 fi # === Handle HTTP status codes === case "$http_code" in 403) echo "Error: 403 Forbidden - Credentials not recognized" >&2 return 1 ;; 500) echo "Error: 500 Internal Server Error - ServerSnug service issue" >&2 return 1 ;; 502) echo "Error: 502 Bad Gateway - ServerSnug service issue" >&2 return 1 ;; 503) echo "Error: 503 Service Unavailable - ServerSnug under maintenance" >&2 return 1 ;; 422) local err err=$(echo "$response_body" | jq -r '.error // "Unknown error"') echo "Error: 422 Processing Error: $err" >&2 return 1 ;; esac if [[ "$http_code" != "200" ]]; then echo "Error: Unexpected HTTP status: $http_code" >&2 return 1 fi # === Check for API-level errors (even on 200) === local api_error api_error=$(echo "$response_body" | jq -r '.error // empty') if [[ -n "$api_error" ]]; then case "$api_error" in "Allowance exceeded") echo "Error: Allowance exceeded - fewer (or no) results returned" >&2 ;; "Malformed request") echo "Error: Malformed request - check JSON format" >&2 ;; *) echo "Error: API error: $api_error" >&2 ;; esac return 1 fi # === Validate response structure === if ! echo "$response_body" | jq -e 'has("count") and has("response")' > /dev/null; then echo "Error: Response missing required fields ('count' or 'response')" >&2 return 1 fi # Success → output JSON echo "$response_body" return 0 }
import requests import json from typing import List, Dict, Any def perform_check_request( access_id: str, access_code: str, ip_list: List[str], timeout: int = 30 ) -> Dict[str, Any]: """ Performs a ServerSnug 'check' request with full error handling. Returns the parsed JSON response on success. Raises detailed exceptions for any failure. """ # Input validation if not access_id or not isinstance(access_id, str): raise ValueError("access_id must be a non-empty string") if not access_code or not isinstance(access_code, str): raise ValueError("access_code must be a non-empty string") if not isinstance(ip_list, list) or not ip_list: raise ValueError("ip_list must be a non-empty list of strings") if not all(isinstance(ip, str) for ip in ip_list): raise ValueError("All elements in ip_list must be strings (IP addresses)") url = "https://www.serversnug.com/api/public/v1/check/" payload = { "access_id": access_id, "access_code": access_code, "ip": ip_list } try: response = requests.post( url, json=payload, # ensures proper JSON Content-Type timeout=timeout, allow_redirects=False ) except requests.exceptions.Timeout: raise ConnectionError("Request timed out while contacting ServerSnug API") except requests.exceptions.ConnectionError: raise ConnectionError("Failed to connect to ServerSnug API (network issue)") except requests.exceptions.RequestException as e: raise ConnectionError(f"Request failed: {e}") # Always attempt to parse JSON even on error status codes try: data: Dict[str, Any] = response.json() except json.JSONDecodeError: raise ValueError(f"Invalid JSON response from server. Status code: {response.status_code}") except Exception as e: raise ValueError(f"Failed to parse response: {e}") # Handle HTTP-level errors first if response.status_code == 403: raise PermissionError("403 Forbidden - Credentials not recognized") if response.status_code == 500: raise RuntimeError("500 Internal Server Error - ServerSnug service issue") if response.status_code == 502: raise RuntimeError("502 Internal Server Error - ServerSnug service issue") if response.status_code == 503: raise RuntimeError("503 Service Unavailable - ServerSnug under maintenance") if response.status_code == 422: error_msg = data.get("error") # Error is Missing ip raise RuntimeError("422 Processing Error: {error_msg}") if response.status_code != 200: raise RuntimeError(f"Unexpected HTTP status: {response.status_code}") # Check for API-level error message (returned with 200) error_msg = data.get("error") if error_msg: if error_msg == "Allowance exceeded": raise RuntimeError("Allowance exceeded - fewer (or no) results returned") if error_msg == "Malformed request": raise ValueError("Malformed request - check JSON format") raise RuntimeError(f"API error: {error_msg}") # Validate expected success structure if "count" not in data or "response" not in data: raise ValueError("Response missing required fields ('count' or 'response')") return data
<?php /** * Performs a ServerSnug 'check' request with full error handling. * Returns the parsed JSON response on success. * Throws detailed exceptions for any failure. */ function perform_check_request( string $access_id, string $access_code, array $ip_list, int $timeout = 30 ): array { // ===================== // Input validation // ===================== if (empty($access_id)) { throw new InvalidArgumentException("access_id must be a non-empty string"); } if (empty($access_code)) { throw new InvalidArgumentException("access_code must be a non-empty string"); } if (!is_array($ip_list) || empty($ip_list)) { throw new InvalidArgumentException("ip_list must be a non-empty list of strings"); } foreach ($ip_list as $ip) { if (!is_string($ip)) { throw new InvalidArgumentException("All elements in ip_list must be strings (IP addresses)"); } } $url = "https://www.serversnug.com/api/public/v1/check/"; $payload = [ "access_id" => $access_id, "access_code" => $access_code, "ip" => $ip_list ]; // ===================== // cURL request // ===================== $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Accept: application/json', ], CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => $timeout, CURLOPT_FOLLOWLOCATION => false, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2, ]); $responseBody = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); $curlErrno = curl_errno($ch); curl_close($ch); // ===================== // Network / cURL errors // ===================== if ($curlErrno !== 0) { if ($curlErrno === CURLE_OPERATION_TIMEDOUT) { throw new RuntimeException("Request timed out while contacting ServerSnug API"); } throw new RuntimeException("Failed to connect to ServerSnug API (network issue): " . $curlError); } // ===================== // Parse JSON response // ===================== $data = json_decode($responseBody, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new RuntimeException( "Invalid JSON response from server. Status code: {$httpCode} - " . json_last_error_msg() ); } // ===================== // HTTP status code handling // ===================== if ($httpCode === 403) { throw new RuntimeException("403 Forbidden - Credentials not recognized"); } if ($httpCode === 500) { throw new RuntimeException("500 Internal Server Error - ServerSnug service issue"); } if ($httpCode === 502) { throw new RuntimeException("502 Bad Gateway - ServerSnug service issue"); } if ($httpCode === 503) { throw new RuntimeException("503 Service Unavailable - ServerSnug under maintenance"); } if ($httpCode === 422) { $errorMsg = $data['error'] ?? 'Unknown processing error'; throw new RuntimeException("422 Processing Error: " . $errorMsg); } if ($httpCode !== 200) { throw new RuntimeException("Unexpected HTTP status: {$httpCode}"); } // ===================== // API-level error messages (can come with 200) // ===================== if (!empty($data['error'])) { $errorMsg = $data['error']; if ($errorMsg === "Allowance exceeded") { throw new RuntimeException("Allowance exceeded - fewer (or no) results returned"); } if ($errorMsg === "Malformed request") { throw new InvalidArgumentException("Malformed request - check JSON format"); } throw new RuntimeException("API error: " . $errorMsg); } // ===================== // Validate expected response structure // ===================== if (!isset($data['count']) || !isset($data['response'])) { throw new RuntimeException("Response missing required fields ('count' or 'response')"); } return $data; } ?>
/** * Performs a ServerSnug 'check' request with full error handling. * Returns the parsed JSON response on success. * Throws detailed Error objects for any failure. */ async function performCheckRequest(accessId, accessCode, ipList, timeout = 30) { // ===================== // Input validation // ===================== if (!accessId || typeof accessId !== 'string') { throw new Error("access_id must be a non-empty string"); } if (!accessCode || typeof accessCode !== 'string') { throw new Error("access_code must be a non-empty string"); } if (!Array.isArray(ipList) || ipList.length === 0) { throw new Error("ip_list must be a non-empty list of strings"); } if (!ipList.every(ip => typeof ip === 'string')) { throw new Error("All elements in ip_list must be strings (IP addresses)"); } const url = "https://www.serversnug.com/api/public/v1/check/"; const payload = { access_id: accessId, access_code: accessCode, ip: ipList }; // ===================== // Timeout handling with AbortController // ===================== const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout * 1000); let response; try { response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(payload), signal: controller.signal, }); } catch (err) { if (err.name === 'AbortError') { throw new Error("Request timed out while contacting ServerSnug API"); } throw new Error("Failed to connect to ServerSnug API (network issue): " + err.message); } finally { clearTimeout(timeoutId); } // ===================== // Parse JSON (even on error status codes) // ===================== let data; try { data = await response.json(); } catch (err) { throw new Error(`Invalid JSON response from server. Status code: ${response.status}`); } // ===================== // HTTP status code handling // ===================== if (response.status === 403) { throw new Error("403 Forbidden - Credentials not recognized"); } if (response.status === 500) { throw new Error("500 Internal Server Error - ServerSnug service issue"); } if (response.status === 502) { throw new Error("502 Bad Gateway - ServerSnug service issue"); } if (response.status === 503) { throw new Error("503 Service Unavailable - ServerSnug under maintenance"); } if (response.status === 422) { const errorMsg = data?.error || 'Unknown processing error'; throw new Error(`422 Processing Error: ${errorMsg}`); } if (response.status !== 200) { throw new Error(`Unexpected HTTP status: ${response.status}`); } // ===================== // API-level error messages (can appear even with status 200) // ===================== if (data?.error) { const errorMsg = data.error; if (errorMsg === "Allowance exceeded") { throw new Error("Allowance exceeded - fewer (or no) results returned"); } if (errorMsg === "Malformed request") { throw new Error("Malformed request - check JSON format"); } throw new Error(`API error: ${errorMsg}`); } // ===================== // Validate expected response structure // ===================== if (!('count' in data) || !('response' in data)) { throw new Error("Response missing required fields ('count' or 'response')"); } return data; } export default performCheckRequest;