Add Flask REST API test server for External System Gateway and Inbound API testing
This commit is contained in:
152
infra/tools/restapi_tool.py
Normal file
152
infra/tools/restapi_tool.py
Normal file
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env python3
|
||||
"""REST API client tool for ScadaLink test infrastructure."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
DEFAULT_URL = "http://localhost:5200"
|
||||
DEFAULT_API_KEY = "scadalink-test-key-1"
|
||||
|
||||
|
||||
def cmd_check(args):
|
||||
"""Test API server connectivity and report status."""
|
||||
headers = {"X-API-Key": args.api_key}
|
||||
|
||||
# Test health endpoint (no auth required)
|
||||
try:
|
||||
resp = requests.get(f"{args.url}/api/Ping", timeout=5)
|
||||
ping_ok = resp.status_code == 200
|
||||
except Exception as e:
|
||||
ping_ok = False
|
||||
ping_err = str(e)
|
||||
|
||||
print(f"Ping ({args.url}/api/Ping): {'OK' if ping_ok else 'FAILED - ' + ping_err}")
|
||||
|
||||
if not ping_ok:
|
||||
sys.exit(1)
|
||||
|
||||
# Test authenticated endpoint
|
||||
try:
|
||||
resp = requests.post(f"{args.url}/api/GetStatus", json={}, headers=headers, timeout=5)
|
||||
if resp.status_code == 200:
|
||||
data = resp.json()
|
||||
print(f"Status: {data.get('status', 'unknown')}")
|
||||
print(f"Uptime: {data.get('uptime', 0)}s")
|
||||
auth_ok = True
|
||||
elif resp.status_code == 401:
|
||||
print("Auth: FAILED - invalid API key")
|
||||
auth_ok = False
|
||||
else:
|
||||
print(f"Status check: HTTP {resp.status_code}")
|
||||
auth_ok = False
|
||||
except Exception as e:
|
||||
print(f"Status check: FAILED - {e}")
|
||||
auth_ok = False
|
||||
|
||||
# List available methods
|
||||
try:
|
||||
resp = requests.get(f"{args.url}/api/methods", headers=headers, timeout=5)
|
||||
if resp.status_code == 200:
|
||||
methods = resp.json().get("methods", [])
|
||||
print(f"Available methods: {len(methods)}")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if ping_ok and auth_ok:
|
||||
print("\nREST API server is healthy.")
|
||||
else:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def cmd_call(args):
|
||||
"""Call an API method."""
|
||||
headers = {"X-API-Key": args.api_key, "Content-Type": "application/json"}
|
||||
url = f"{args.url}/api/{args.method}"
|
||||
|
||||
params = {}
|
||||
if args.params:
|
||||
try:
|
||||
params = json.loads(args.params)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error: invalid JSON params: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
if args.method == "Ping":
|
||||
resp = requests.get(url, headers=headers, timeout=args.timeout)
|
||||
else:
|
||||
resp = requests.post(url, json=params, headers=headers, timeout=args.timeout)
|
||||
except requests.exceptions.Timeout:
|
||||
print(f"Error: request timed out after {args.timeout}s", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
print(f"HTTP {resp.status_code}")
|
||||
try:
|
||||
print(json.dumps(resp.json(), indent=2))
|
||||
except Exception:
|
||||
print(resp.text)
|
||||
|
||||
if resp.status_code >= 400:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def cmd_methods(args):
|
||||
"""List all available API methods."""
|
||||
headers = {"X-API-Key": args.api_key}
|
||||
|
||||
try:
|
||||
resp = requests.get(f"{args.url}/api/methods", headers=headers, timeout=5)
|
||||
if resp.status_code != 200:
|
||||
print(f"Error: HTTP {resp.status_code}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
methods = resp.json().get("methods", [])
|
||||
print(f"{'Method':<25} {'HTTP':<6} {'Path':<30} {'Description'}")
|
||||
print("-" * 95)
|
||||
|
||||
for m in methods:
|
||||
print(f"{m['method']:<25} {m['httpMethod']:<6} {m['path']:<30} {m.get('description', '')}")
|
||||
if m.get("params"):
|
||||
params_str = ", ".join(f"{k}: {v}" for k, v in m["params"].items())
|
||||
print(f" {'Params:':<23} {params_str}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="REST API client tool for ScadaLink test infrastructure")
|
||||
parser.add_argument("--url", default=DEFAULT_URL, help=f"API base URL (default: {DEFAULT_URL})")
|
||||
parser.add_argument("--api-key", default=DEFAULT_API_KEY, help=f"API key (default: {DEFAULT_API_KEY})")
|
||||
|
||||
sub = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
sub.add_parser("check", help="Test API connectivity and report status")
|
||||
|
||||
call_p = sub.add_parser("call", help="Call an API method")
|
||||
call_p.add_argument("--method", required=True, help="Method name (e.g. Add, GetProductionReport)")
|
||||
call_p.add_argument("--params", help="JSON params (e.g. '{\"a\": 2, \"b\": 3}')")
|
||||
call_p.add_argument("--timeout", type=float, default=30, help="Request timeout in seconds (default: 30)")
|
||||
|
||||
sub.add_parser("methods", help="List all available API methods")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
commands = {
|
||||
"check": cmd_check,
|
||||
"call": cmd_call,
|
||||
"methods": cmd_methods,
|
||||
}
|
||||
|
||||
commands[args.command](args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user