#!/usr/bin/env python3 """ API Test Script This script helps test your API endpoints before running the full image downloader. It will check if the list endpoint returns valid data and if the download endpoint is accessible. Usage: python test_api.py --api-url --list-endpoint --download-endpoint """ import argparse import asyncio import aiohttp import json from urllib.parse import urljoin from typing import Dict, Any class APITester: def __init__(self, api_url: str, list_endpoint: str, download_endpoint: str, timeout: int = 30, api_key: str = None): self.api_url = api_url.rstrip('/') self.list_endpoint = list_endpoint.lstrip('/') self.download_endpoint = download_endpoint.lstrip('/') self.timeout = timeout self.api_key = api_key async def test_list_endpoint(self, session: aiohttp.ClientSession) -> Dict[str, Any]: """Test the list endpoint and return information about the response.""" url = urljoin(self.api_url, self.list_endpoint) print(f"Testing list endpoint: {url}") try: headers = {} if self.api_key: headers['x-api-key'] = self.api_key async with session.get(url, headers=headers, timeout=self.timeout) as response: print(f"Status Code: {response.status}") print(f"Content-Type: {response.headers.get('content-type', 'Not specified')}") if response.status == 200: data = await response.json() print(f"Response type: {type(data)}") # Analyze the response structure if isinstance(data, list): print(f"Found {len(data)} assets in array") if data: print(f"First asset keys: {list(data[0].keys())}") elif isinstance(data, dict): print(f"Response keys: {list(data.keys())}") # Check common patterns for key in ['data', 'results', 'items', 'assets', 'images']: if key in data and isinstance(data[key], list): print(f"Found {len(data[key])} assets in '{key}' field") if data[key]: print(f"First asset keys: {list(data[key][0].keys())}") break else: print("No recognized array field found in response") else: print(f"Unexpected response format: {type(data)}") return { 'success': True, 'data': data, 'url': url } else: print(f"Error: HTTP {response.status_code}") return { 'success': False, 'error': f"HTTP {response.status_code}", 'url': url } except Exception as e: print(f"Error testing list endpoint: {e}") return { 'success': False, 'error': str(e), 'url': url } async def test_download_endpoint(self, session: aiohttp.ClientSession, asset_id: str) -> Dict[str, Any]: """Test the download endpoint with a sample asset ID.""" url = urljoin(self.api_url, f"{self.download_endpoint}/{asset_id}") print(f"\nTesting download endpoint: {url}") try: headers = {} if self.api_key: headers['x-api-key'] = self.api_key async with session.get(url, headers=headers, timeout=self.timeout) as response: print(f"Status Code: {response.status}") print(f"Content-Type: {response.headers.get('content-type', 'Not specified')}") print(f"Content-Length: {response.headers.get('content-length', 'Not specified')}") if response.status == 200: content_type = response.headers.get('content-type', '') if content_type.startswith('image/'): print("✓ Download endpoint returns image content") return { 'success': True, 'url': url, 'content_type': content_type } else: print(f"⚠ Warning: Content type is not an image: {content_type}") return { 'success': True, 'url': url, 'content_type': content_type, 'warning': 'Not an image' } else: print(f"Error: HTTP {response.status}") return { 'success': False, 'error': f"HTTP {response.status}", 'url': url } except Exception as e: print(f"Error testing download endpoint: {e}") return { 'success': False, 'error': str(e), 'url': url } async def run_tests(self): """Run all API tests.""" print("=" * 60) print("API Endpoint Test") print("=" * 60) timeout = aiohttp.ClientTimeout(total=self.timeout) async with aiohttp.ClientSession(timeout=timeout) as session: # Test list endpoint list_result = await self.test_list_endpoint(session) if list_result['success']: # Try to test download endpoint with first asset data = list_result['data'] asset_id = None # Find an asset ID to test with if isinstance(data, list) and data: asset = data[0] for key in ['id', 'asset_id', 'image_id', 'file_id', 'uuid', 'key']: if key in asset: asset_id = asset[key] break elif isinstance(data, dict): for key in ['data', 'results', 'items', 'assets', 'images']: if key in data and isinstance(data[key], list) and data[key]: asset = data[key][0] for id_key in ['id', 'asset_id', 'image_id', 'file_id', 'uuid', 'key']: if id_key in asset: asset_id = asset[id_key] break if asset_id: break if asset_id: print(f"\nUsing asset ID '{asset_id}' for download test") download_result = await self.test_download_endpoint(session, asset_id) else: print("\n⚠ Could not find an asset ID to test download endpoint") print("You may need to manually test the download endpoint") # Print summary print("\n" + "=" * 60) print("TEST SUMMARY") print("=" * 60) if list_result['success']: print("✓ List endpoint: Working") else: print("✗ List endpoint: Failed") print(f" Error: {list_result['error']}") if 'download_result' in locals(): if download_result['success']: print("✓ Download endpoint: Working") if 'warning' in download_result: print(f" Warning: {download_result['warning']}") else: print("✗ Download endpoint: Failed") print(f" Error: {download_result['error']}") print("\nRecommendations:") if list_result['success']: print("- List endpoint is working correctly") print("- You can proceed with the image downloader") else: print("- Check your API URL and list endpoint") print("- Verify the API is accessible") print("- Check if authentication is required") if 'download_result' in locals() and not download_result['success']: print("- Check your download endpoint format") print("- Verify asset IDs are being passed correctly") def main(): parser = argparse.ArgumentParser( description="Test API endpoints for image downloader", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: python test_api.py --api-url "https://api.example.com" \\ --list-endpoint "/assets" \\ --download-endpoint "/download" """ ) parser.add_argument( '--api-url', required=True, help='Base URL of the API (e.g., https://api.example.com)' ) parser.add_argument( '--list-endpoint', required=True, help='Endpoint to get the list of assets (e.g., /assets or /images)' ) parser.add_argument( '--download-endpoint', required=True, help='Endpoint to download individual assets (e.g., /download or /assets)' ) parser.add_argument( '--timeout', type=int, default=30, help='Request timeout in seconds (default: 30)' ) parser.add_argument( '--api-key', help='API key for authentication (x-api-key header)' ) args = parser.parse_args() tester = APITester( api_url=args.api_url, list_endpoint=args.list_endpoint, download_endpoint=args.download_endpoint, timeout=args.timeout, api_key=args.api_key ) try: asyncio.run(tester.run_tests()) except KeyboardInterrupt: print("\nTest interrupted by user") except Exception as e: print(f"Error: {e}") return 1 return 0 if __name__ == "__main__": exit(main())