一键导入
api-client-tester-waruna834
Complete API testing tool for REST, GraphQL, and WebSocket with collections support - lightweight Postman alternative
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Complete API testing tool for REST, GraphQL, and WebSocket with collections support - lightweight Postman alternative
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | api-client-tester-waruna834 |
| description | Complete API testing tool for REST, GraphQL, and WebSocket with collections support - lightweight Postman alternative |
| triggers | ["test REST API endpoints","send GraphQL queries","test WebSocket connections","manage API request collections","authenticate API requests","export API test collections","inspect HTTP responses","build API testing suite"] |
Skill by ara.so — Devtools Skills collection.
API Client & Tester is a complete API testing tool for REST, GraphQL, and WebSocket protocols. It provides a lightweight alternative to Postman with support for multiple HTTP methods, authentication strategies, request collections, and import/export functionality.
git clone https://github.com/waruna834/API_Client___Tester.git
cd API_Client___Tester
pip install -r requirements.txt
python main.py
requirements.txtThe tool supports standard HTTP methods with authentication:
import requests
import json
class APIClient:
def __init__(self, base_url=""):
self.base_url = base_url
self.headers = {}
self.auth = None
def set_auth(self, auth_type, credentials):
"""Set authentication for requests"""
if auth_type == "basic":
from requests.auth import HTTPBasicAuth
self.auth = HTTPBasicAuth(credentials['username'], credentials['password'])
elif auth_type == "bearer":
self.headers['Authorization'] = f"Bearer {credentials['token']}"
elif auth_type == "api_key":
self.headers[credentials['key_name']] = credentials['key_value']
def request(self, method, endpoint, **kwargs):
"""Send HTTP request"""
url = f"{self.base_url}{endpoint}"
kwargs.setdefault('headers', {}).update(self.headers)
if self.auth:
kwargs['auth'] = self.auth
response = requests.request(method, url, **kwargs)
return {
'status_code': response.status_code,
'headers': dict(response.headers),
'body': response.text,
'json': response.json() if response.headers.get('content-type', '').startswith('application/json') else None
}
# Usage
client = APIClient(base_url="https://api.example.com")
client.set_auth("bearer", {"token": os.getenv("API_TOKEN")})
response = client.request("GET", "/users", params={"page": 1})
print(f"Status: {response['status_code']}")
print(f"Data: {response['json']}")
class GraphQLClient:
def __init__(self, endpoint, headers=None):
self.endpoint = endpoint
self.headers = headers or {}
def query(self, query, variables=None):
"""Execute GraphQL query"""
payload = {
'query': query,
'variables': variables or {}
}
response = requests.post(
self.endpoint,
json=payload,
headers=self.headers
)
result = response.json()
if 'errors' in result:
raise Exception(f"GraphQL errors: {result['errors']}")
return result['data']
def mutation(self, mutation, variables=None):
"""Execute GraphQL mutation"""
return self.query(mutation, variables)
# Usage
gql_client = GraphQLClient(
endpoint="https://api.example.com/graphql",
headers={"Authorization": f"Bearer {os.getenv('GRAPHQL_TOKEN')}"}
)
query = """
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
}
}
"""
result = gql_client.query(query, variables={"id": "123"})
print(result['user'])
import websocket
import json
import threading
class WebSocketClient:
def __init__(self, url):
self.url = url
self.ws = None
self.messages = []
def on_message(self, ws, message):
"""Handle incoming message"""
self.messages.append({
'timestamp': datetime.now().isoformat(),
'data': message
})
print(f"Received: {message}")
def on_error(self, ws, error):
"""Handle error"""
print(f"Error: {error}")
def on_close(self, ws, close_status_code, close_msg):
"""Handle connection close"""
print(f"Connection closed: {close_status_code} - {close_msg}")
def on_open(self, ws):
"""Handle connection open"""
print("WebSocket connection opened")
def connect(self):
"""Establish WebSocket connection"""
self.ws = websocket.WebSocketApp(
self.url,
on_open=self.on_open,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close
)
ws_thread = threading.Thread(target=self.ws.run_forever)
ws_thread.daemon = True
ws_thread.start()
def send(self, data):
"""Send message"""
if self.ws:
self.ws.send(json.dumps(data) if isinstance(data, dict) else data)
def close(self):
"""Close connection"""
if self.ws:
self.ws.close()
# Usage
ws_client = WebSocketClient("wss://echo.websocket.org")
ws_client.connect()
# Send message
ws_client.send({"type": "ping", "timestamp": time.time()})
# Wait for responses
time.sleep(2)
# Close connection
ws_client.close()
import json
import os
class CollectionManager:
def __init__(self, collections_dir="./collections"):
self.collections_dir = collections_dir
os.makedirs(collections_dir, exist_ok=True)
def create_collection(self, name, requests=None):
"""Create a new collection"""
collection = {
'name': name,
'created_at': datetime.now().isoformat(),
'requests': requests or []
}
return collection
def add_request(self, collection, request_data):
"""Add request to collection"""
request = {
'id': str(uuid.uuid4()),
'name': request_data.get('name', 'Untitled'),
'method': request_data['method'],
'url': request_data['url'],
'headers': request_data.get('headers', {}),
'body': request_data.get('body', ''),
'auth': request_data.get('auth', None),
'params': request_data.get('params', {})
}
collection['requests'].append(request)
return collection
def save_collection(self, collection):
"""Save collection to file"""
filename = f"{collection['name'].replace(' ', '_')}.json"
filepath = os.path.join(self.collections_dir, filename)
with open(filepath, 'w') as f:
json.dump(collection, f, indent=2)
return filepath
def load_collection(self, name):
"""Load collection from file"""
filename = f"{name.replace(' ', '_')}.json"
filepath = os.path.join(self.collections_dir, filename)
with open(filepath, 'r') as f:
return json.load(f)
def export_collection(self, collection, output_path):
"""Export collection to JSON"""
with open(output_path, 'w') as f:
json.dump(collection, f, indent=2)
def import_collection(self, input_path):
"""Import collection from JSON"""
with open(input_path, 'r') as f:
collection = json.load(f)
self.save_collection(collection)
return collection
# Usage
manager = CollectionManager()
# Create collection
collection = manager.create_collection("User API Tests")
# Add requests
collection = manager.add_request(collection, {
'name': 'Get All Users',
'method': 'GET',
'url': 'https://api.example.com/users',
'auth': {'type': 'bearer', 'token': '${API_TOKEN}'}
})
collection = manager.add_request(collection, {
'name': 'Create User',
'method': 'POST',
'url': 'https://api.example.com/users',
'headers': {'Content-Type': 'application/json'},
'body': json.dumps({'name': 'John Doe', 'email': 'john@example.com'}),
'auth': {'type': 'bearer', 'token': '${API_TOKEN}'}
})
# Save collection
manager.save_collection(collection)
# Export for sharing
manager.export_collection(collection, "./exports/user_api_tests.json")
client = APIClient(base_url="https://api.example.com")
client.set_auth("basic", {
'username': os.getenv('API_USERNAME'),
'password': os.getenv('API_PASSWORD')
})
response = client.request("GET", "/protected")
client = APIClient(base_url="https://api.example.com")
client.set_auth("bearer", {
'token': os.getenv('BEARER_TOKEN')
})
response = client.request("GET", "/me")
client = APIClient(base_url="https://api.example.com")
client.set_auth("api_key", {
'key_name': 'X-API-Key',
'key_value': os.getenv('API_KEY')
})
response = client.request("GET", "/data")
import requests
from urllib.parse import urlencode
class OAuth2Client:
def __init__(self, client_id, client_secret, auth_url, token_url):
self.client_id = client_id
self.client_secret = client_secret
self.auth_url = auth_url
self.token_url = token_url
self.access_token = None
def get_authorization_url(self, redirect_uri, scope=None):
"""Generate authorization URL"""
params = {
'client_id': self.client_id,
'redirect_uri': redirect_uri,
'response_type': 'code'
}
if scope:
params['scope'] = scope
return f"{self.auth_url}?{urlencode(params)}"
def exchange_code_for_token(self, code, redirect_uri):
"""Exchange authorization code for access token"""
data = {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': redirect_uri,
'client_id': self.client_id,
'client_secret': self.client_secret
}
response = requests.post(self.token_url, data=data)
token_data = response.json()
self.access_token = token_data['access_token']
return token_data
# Usage
oauth = OAuth2Client(
client_id=os.getenv('OAUTH_CLIENT_ID'),
client_secret=os.getenv('OAUTH_CLIENT_SECRET'),
auth_url="https://oauth.example.com/authorize",
token_url="https://oauth.example.com/token"
)
auth_url = oauth.get_authorization_url(
redirect_uri="http://localhost:8080/callback",
scope="read write"
)
print(f"Visit: {auth_url}")
class BatchExecutor:
def __init__(self, client):
self.client = client
def execute_collection(self, collection, environment=None):
"""Execute all requests in a collection"""
results = []
env_vars = environment or {}
for request in collection['requests']:
# Replace environment variables
url = self._replace_vars(request['url'], env_vars)
headers = {k: self._replace_vars(v, env_vars)
for k, v in request.get('headers', {}).items()}
try:
response = self.client.request(
request['method'],
url,
headers=headers,
json=json.loads(request.get('body', '{}')) if request.get('body') else None
)
results.append({
'request': request['name'],
'status': 'success',
'response': response
})
except Exception as e:
results.append({
'request': request['name'],
'status': 'error',
'error': str(e)
})
return results
def _replace_vars(self, text, env_vars):
"""Replace ${VAR} with environment values"""
for key, value in env_vars.items():
text = text.replace(f"${{{key}}}", str(value))
return text
# Usage
executor = BatchExecutor(client)
environment = {
'BASE_URL': 'https://api.example.com',
'API_TOKEN': os.getenv('API_TOKEN'),
'USER_ID': '12345'
}
results = executor.execute_collection(collection, environment)
for result in results:
print(f"{result['request']}: {result['status']}")
if result['status'] == 'success':
print(f" Status Code: {result['response']['status_code']}")
class ResponseValidator:
@staticmethod
def validate_status(response, expected_status):
"""Validate status code"""
return response['status_code'] == expected_status
@staticmethod
def validate_json_schema(response, schema):
"""Validate JSON response against schema"""
from jsonschema import validate, ValidationError
try:
validate(instance=response['json'], schema=schema)
return True
except ValidationError as e:
return False, str(e)
@staticmethod
def validate_response_time(response, max_time_ms):
"""Validate response time"""
return response.get('elapsed_ms', 0) <= max_time_ms
# Usage
validator = ResponseValidator()
response = client.request("GET", "/users/123")
# Validate status
assert validator.validate_status(response, 200), "Expected 200 status"
# Validate schema
schema = {
"type": "object",
"properties": {
"id": {"type": "string"},
"name": {"type": "string"},
"email": {"type": "string", "format": "email"}
},
"required": ["id", "name", "email"]
}
is_valid = validator.validate_json_schema(response, schema)
assert is_valid, "Response doesn't match schema"
# .env file
API_BASE_URL=https://api.example.com
API_TOKEN=your_token_here
API_USERNAME=your_username
API_PASSWORD=your_password
OAUTH_CLIENT_ID=your_client_id
OAUTH_CLIENT_SECRET=your_client_secret
GRAPHQL_ENDPOINT=https://api.example.com/graphql
WEBSOCKET_URL=wss://api.example.com/ws
import json
class Config:
def __init__(self, config_path="config.json"):
self.config_path = config_path
self.config = self.load()
def load(self):
"""Load configuration"""
try:
with open(self.config_path, 'r') as f:
return json.load(f)
except FileNotFoundError:
return self.get_defaults()
def get_defaults(self):
"""Default configuration"""
return {
'timeout': 30,
'retry_count': 3,
'verify_ssl': True,
'follow_redirects': True,
'default_headers': {
'User-Agent': 'API-Client-Tester/1.0'
}
}
def save(self):
"""Save configuration"""
with open(self.config_path, 'w') as f:
json.dump(self.config, f, indent=2)
# Usage
config = Config()
print(f"Timeout: {config.config['timeout']}")
# Disable SSL verification (not recommended for production)
response = requests.get(url, verify=False)
# Or provide custom CA bundle
response = requests.get(url, verify='/path/to/ca-bundle.crt')
client = APIClient(base_url="https://api.example.com")
try:
response = client.request(
"GET",
"/slow-endpoint",
timeout=10 # 10 seconds timeout
)
except requests.exceptions.Timeout:
print("Request timed out")
import time
from functools import wraps
def rate_limit(calls=10, period=60):
"""Rate limiting decorator"""
timestamps = []
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
now = time.time()
timestamps[:] = [t for t in timestamps if now - t < period]
if len(timestamps) >= calls:
sleep_time = period - (now - timestamps[0])
time.sleep(sleep_time)
timestamps.append(time.time())
return func(*args, **kwargs)
return wrapper
return decorator
@rate_limit(calls=10, period=60)
def make_api_call(endpoint):
return client.request("GET", endpoint)
class ResilientWebSocketClient(WebSocketClient):
def __init__(self, url, max_retries=5):
super().__init__(url)
self.max_retries = max_retries
self.retry_count = 0
def on_error(self, ws, error):
"""Handle error with reconnection"""
print(f"Error: {error}")
if self.retry_count < self.max_retries:
self.retry_count += 1
time.sleep(2 ** self.retry_count) # Exponential backoff
self.connect()
else:
print("Max retries reached")
def on_open(self, ws):
"""Reset retry count on successful connection"""
self.retry_count = 0
print("WebSocket connection established")
Orchestrate psychology clinic workflows with AI-powered scheduling, WhatsApp automation, AFIP billing, and video consultations for Argentine practitioners
SaaS platform for psychology clinics with intelligent scheduling, WhatsApp automation, AFIP billing, videollamadas, and Claude AI integration
Build and customize the Sesión mental health practice management platform with appointment scheduling, WhatsApp automation, AFIP billing, and Claude AI integration
Orchestrate psychology clinic operations with AI-powered scheduling, WhatsApp automation, AFIP billing, and secure video consultations for Argentine mental health practitioners
Connect AI agents to a running Tabbit browser instance via Chrome DevTools Protocol (CDP) and control it through agent-browser
AI-powered mental health practice management platform for Argentina with WhatsApp automation, AFIP-compliant invoicing, and video consultations