#!/usr/bin/env python3 """ Ultra-thin checker: consume a JSON mapping of {domain: [expected_status_codes]} and verify HTTP HEAD responses. All mapping logic is done in the filter `web_health_expectations`. """ import argparse import json import sys from typing import Dict, List import requests def parse_args(argv=None): p = argparse.ArgumentParser(description="Web health checker (expects precomputed domain→codes mapping).") p.add_argument("--web-protocol", default="https", choices=["http", "https"], help="Protocol to use") p.add_argument("--expectations", required=True, help="JSON STRING: {\"domain\": [codes], ...}") return p.parse_args(argv) def _parse_json_mapping(name: str, value: str) -> Dict[str, List[int]]: try: obj = json.loads(value) except json.JSONDecodeError as e: raise SystemExit(f"--{name} must be a valid JSON string: {e}") if not isinstance(obj, dict): raise SystemExit(f"--{name} must be a JSON object (mapping)") # sanitize list-of-ints shape clean = {} for k, v in obj.items(): if isinstance(v, list): try: clean[k] = [int(x) for x in v] except Exception: clean[k] = [] else: clean[k] = [] return clean def main(argv=None) -> int: args = parse_args(argv) expectations = _parse_json_mapping("expectations", args.expectations) errors = 0 for domain in sorted(expectations.keys()): expected = expectations[domain] or [] url = f"{args.web_protocol}://{domain}" try: r = requests.head(url, allow_redirects=False, timeout=10) if expected and r.status_code in expected: print(f"{domain}: OK") elif not expected: # If somehow empty list slipped through, treat as failure to be explicit print(f"{domain}: ERROR: No expectations provided. Got {r.status_code}.") errors += 1 else: print(f"{domain}: ERROR: Expected {expected}. Got {r.status_code}.") errors += 1 except requests.RequestException as e: print(f"{domain}: error due to {e}") errors += 1 if errors: print(f"Warning: {errors} domains responded with an unexpected https status code.") return errors if __name__ == "__main__": sys.exit(main())