import json as json_lib from typing import Optional import click import rich import requests from ...http_client import HTTPClient @click.group() def http(): """Make HTTP requests to the LiteLLM proxy server""" pass @http.command() @click.argument("method") @click.argument("uri") @click.option( "--data", "-d", type=str, help="Data to send in the request body (as JSON string)", ) @click.option( "--json", "-j", type=str, help="JSON data to send in the request body (as JSON string)", ) @click.option( "--header", "-H", multiple=True, help="HTTP headers in 'key:value' format. Can be specified multiple times.", ) @click.pass_context def request( ctx: click.Context, method: str, uri: str, data: Optional[str] = None, json: Optional[str] = None, header: tuple[str, ...] = (), ): """Make an HTTP request to the LiteLLM proxy server METHOD: HTTP method (GET, POST, PUT, DELETE, etc.) URI: URI path (will be appended to base_url) Examples: litellm http request GET /models litellm http request POST /chat/completions -j '{"model": "gpt-4", "messages": [{"role": "user", "content": "Hello"}]}' litellm http request GET /health/test_connection -H "X-Custom-Header:value" """ # Parse headers from key:value format headers = {} for h in header: try: key, value = h.split(":", 1) headers[key.strip()] = value.strip() except ValueError: raise click.BadParameter(f"Invalid header format: {h}. Expected format: 'key:value'") # Parse JSON data if provided json_data = None if json: try: json_data = json_lib.loads(json) except ValueError as e: raise click.BadParameter(f"Invalid JSON format: {e}") # Parse data if provided request_data = None if data: try: request_data = json_lib.loads(data) except ValueError: # If not JSON, use as raw data request_data = data client = HTTPClient(ctx.obj["base_url"], ctx.obj["api_key"]) try: response = client.request( method=method, uri=uri, data=request_data, json=json_data, headers=headers, ) rich.print_json(data=response) except requests.exceptions.HTTPError as e: click.echo(f"Error: HTTP {e.response.status_code}", err=True) try: error_body = e.response.json() rich.print_json(data=error_body) except json_lib.JSONDecodeError: click.echo(e.response.text, err=True) raise click.Abort()