import subprocess
import shlex
from typing import Dict, Any
from shutil import which
class CurlError(Exception):
"""Custom exception for curl-related errors"""
pass
def run_curl(target: str, opts: str) -> Dict[str, Any]:
"""
Run a curl command against the given target with the provided options.
This tool is useful for making HTTP requests, testing endpoints, checking headers,
and debugging web services without requiring a full browser.
:param target: URL or hostname (e.g. "https://example.com")
:param opts: space-separated curl options (e.g. "-I -L")
:return: A dictionary containing status, stdout, and stderr
Common curl options:
-I, --head Fetch headers only (HEAD request)
-L, --location Follow redirects
-X, --request METHOD Specify HTTP method (GET, POST, PUT, DELETE, etc.)
-d, --data DATA Send POST data
-H, --header HEADER Add custom header
-A, --user-agent AGENT Set User-Agent
-b, --cookie COOKIE Send cookies
-u, --user USER:PASS HTTP authentication
-v, --verbose Verbose output
-s, --silent Silent mode
-o, --output FILE Write output to file
-O, --remote-name Write to remote filename
--proxy PROXY Use proxy
--insecure Allow insecure SSL
-m, --max-time SECONDS Timeout in seconds
"""
try:
if which("curl") is None:
raise CurlError(
"curl not found in PATH. Please install curl or ensure it's in your system PATH."
)
cmd = ["curl"]
if opts:
cmd.extend(shlex.split(opts))
cmd.append(target)
completed = subprocess.run(
cmd,
text=True,
capture_output=True,
timeout=60
)
return {
"status": "success" if completed.returncode == 0 else "error",
"return_code": completed.returncode,
"stdout": completed.stdout,
"stderr": completed.stderr,
"command": " ".join(cmd)
}
except subprocess.TimeoutExpired:
raise CurlError(f"curl command timed out after 60 seconds for target: {target}")
except FileNotFoundError as e:
raise CurlError(f"curl executable not found: {e}")
except Exception as e:
raise CurlError(f"Error running curl against {target}: {str(e)}")