Skip to content

Repository files navigation

HTTP API Test Tool

An HTTP API testing tool for GitHub Actions and command-line usage.

This action performs HTTP requests with configurable verification of response status, content, headers, and timing. Implemented in Python to modern PEP standards, using Typer and pycurl. Avoids JSON escaping issues associated with shell code implementations in GitHub actions.

http-api-tool-docker

A containerized version of the HTTP API test tool with secure, multi-architecture support.

Published Docker Images

Pre-built, multi-architecture Docker images are automatically published to GitHub Container Registry on every release:

# Pull the latest version
docker pull ghcr.io/lfreleng-actions/http-api-tool-docker:latest
# Pull a specific version
docker pull ghcr.io/lfreleng-actions/http-api-tool-docker:v0.2.0
# Use directly in commands
docker run --rm ghcr.io/lfreleng-actions/http-api-tool-docker:latest test \
--url https://api.example.com/health \
--expected-http-code 200

Available Tags:

  • latest - Most recent release
  • vX.Y.Z - Specific version (e.g., v0.2.0)
  • X.Y - Minor version (e.g., 0.2)
  • X - Major version (e.g., 0)

Supported Platforms:

  • linux/amd64 (Intel/AMD x86_64)
  • linux/arm64 (Apple Silicon/ARM64)

Docker Security Features

The Containerfile implements these security best practices:

  • Version Pinning: uv binary version is explicitly pinned (0.8.4)
  • Checksum Validation: Downloads verify against SHA256 checksums to prevent MITM attacks
  • Multi-Architecture Support: Automatically detects and downloads the correct binary for:
    • linux/amd64 (Intel/AMD x86_64)
    • linux/arm64 (Apple Silicon/ARM64)

Building the Container (Optional)

You can build the container locally if needed, though pre-built images are available:

# Build for current platform
docker build -f docker/Containerfile -t http-api-tool .# Build for specific platform
docker build -f docker/Containerfile --platform linux/amd64 -t http-api-tool .
docker build -f docker/Containerfile --platform linux/arm64 -t http-api-tool .# Override uv version
docker build -f docker/Containerfile --build-arg UV_VERSION=0.8.5 \
-t http-api-tool .

Container Usage

# Using published image
docker run --rm ghcr.io/lfreleng-actions/http-api-tool-docker:latest --help
# Test an API endpoint
docker run --rm ghcr.io/lfreleng-actions/http-api-tool-docker:latest test \
--url https://api.example.com/health \
--expected-http-code 200
# Using locally built image
docker run --rm http-api-tool --help
# Check uv version in container
docker run --rm --entrypoint=/usr/local/bin/uv \
ghcr.io/lfreleng-actions/http-api-tool-docker:latest --version

Features

  • Supported HTTP Methods: Supports GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
  • Authentication: Basic Auth via auth_string and custom headers support
  • Response Validation: Status code, regex pattern matching, response time limits
  • Retry Logic: Exponential backoff, doubling up to a configurable cap
  • Dual Usage: Works as both a CLI tool and GitHub Action
  • Robust Error Handling: Detailed error messages and proper exit codes
  • JSON Safety: Uses pycurl instead of shell commands to avoid escaping issues
  • SSL/TLS Support: Full SSL verification with custom CA bundle support
  • Response Metrics: Comprehensive timing and size measurements

Usage

As a GitHub Action

The action supports two deployment methods:

1. uvx Deployment (Default - Fast & Recommended)

Uses uvx to run the tool directly from PyPI without building a container. This is faster and is the recommended method.

- name: Test API Endpoint (uvx - default)uses: lfreleng-actions/http-api-tool-docker@mainwith:
url: 'https://api.example.com/health'http_method: 'GET'expected_http_code: '200'curl_timeout: '30'max_response_time: '10'retries: '3'initial_sleep_time: '2'# Explicitly specify uvx with custom Python version
- name: Test API with uvx and Python 3.12uses: lfreleng-actions/http-api-tool-docker@mainwith:
deploy: 'uvx'python_version: '3.12'url: 'https://api.example.com/health'expected_http_code: '200'

2. Docker Deployment (Containerized)

Uses Docker to run the tool in a container. This is useful when you need isolation or specific container features.

- name: Test API Endpoint (Docker)uses: lfreleng-actions/http-api-tool-docker@mainwith:
deploy: 'docker'url: 'https://api.example.com/health'http_method: 'GET'expected_http_code: '200'curl_timeout: '30'max_response_time: '10'retries: '3'initial_sleep_time: '2'# Example with custom CA certificate
- name: Test API with Custom CAuses: lfreleng-actions/http-api-tool-docker@mainwith:
deploy: 'docker'url: 'https://internal-api.company.com/health'ca_bundle_path: '/path/to/ca-certificates.pem'expected_http_code: '200'

Deployment Method Comparison:

Featureuvx (default)docker
Speed⚡ Fast (~10s)🐌 Slower (~60s for build)
IsolationProcess-levelContainer-level
CachingPyPI cacheDocker layer cache
Use CaseMost scenariosSpecial isolation needs

As a CLI Tool

# Install UV (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install dependencies using UV with hash verification
uv sync --frozen --no-dev
# Basic usage
uv run python -m http_api_tool test --url https://api.example.com/health
# Advanced usage
uv run python -m http_api_tool test \
--url https://api.example.com/users \
--http-method POST \
--request-body '{"name": "John", "email": "john@example.com"}' \
--request-headers '{"Content-Type": "application/json"}' \
--auth-string username:password \
--expected-http-code 201 \
--regex '"id":\s*\d+' \
--curl-timeout 30 \
--max-response-time 10 \
--retries 3

Inputs

InputDescriptionRequiredDefault
deployDeployment method: uvx (fast, default) or docker (containerized)Nouvx
python_versionPython version to use when deploy=uvxNo3.11
urlURL of API server/interface to checkYes-
auth_stringAuthentication string, colon separated username/passwordNo-
service_nameName of HTTP/HTTPS API service testedNoAPI Service
initial_sleep_timeDelay in seconds before the first retry, doubling thereafterNo1
max_delayMax delay in seconds between retriesNo30
retriesNumber of retries before declaring service unavailableNo3
expected_http_codeHTTP response code to accept from the API serviceNo200
regexVerify server response with regular expressionNo-
show_header_jsonDisplay response header as JSON in action outputNofalse
curl_timeoutMax time in seconds for cURL to wait for a responseNo5
http_methodHTTP method to use (GET, POST, PUT, etc.)NoGET
request_bodyData to send with POST/PUT/PATCH requestsNo-
content_typeContent type for the request bodyNoapplication/json
request_headersCustom HTTP headers sent in JSON formatNo-
verify_sslVerify SSL certificatesNotrue
ca_bundle_pathPath to CA bundle file for SSL verificationNo-
include_response_bodyInclude response body in outputs (base64)Nofalse
follow_redirectsFollow HTTP redirectsNotrue
max_response_timeMax acceptable response time in secondsNo0
connection_reuseReuse connections between requestsNotrue
debugEnables debugging outputNofalse
fail_on_timeoutFail if response time exceeds max_response_timeNofalse

Outputs

OutputDescription
time_delayNumber of seconds waiting for service availability/failure
response_http_codeHTTP response code received from the server
response_header_jsonHTTP response header as JSON
response_header_sizeHTTP response header size in bytes
response_body_sizeHTTP response body size in bytes
regex_matchWhether the regular expression matched the server reply
response_body_base64Response body base64 encoded (when enabled)
total_timeTotal time for the request in seconds
connect_timeTime to establish connection in seconds
response_time_exceededWhether response time exceeded max time

Authentication

Authentication String

with:
auth_string: 'username:password'

Custom Headers

with:
request_headers: | { "Authorization": "Bearer your-jwt-token", "X-API-Key": "your-api-key", "X-Custom-Header": "value" }

Examples

Simple Health Check

- name: Health Checkuses: lfreleng-actions/http-api-tool-docker@mainwith:
url: 'https://api.example.com/health'expected_http_code: '200'

POST with JSON Data

- name: Create Useruses: lfreleng-actions/http-api-tool-docker@mainwith:
url: 'https://api.example.com/users'http_method: 'POST'request_headers: '{"Content-Type": "application/json"}'request_body: '{"name": "John Doe", "email": "john@example.com"}'expected_http_code: '201'regex: '"id":\s*\d+'

Authenticated Request with Retry

- name: Get Protected Resourceuses: lfreleng-actions/http-api-tool-docker@mainwith:
url: 'https://api.example.com/protected'request_headers: '{"Authorization": "Bearer ${{ secrets.API_TOKEN }}"}'retries: '5'initial_sleep_time: '2'curl_timeout: '30'

Response Validation

- name: Test API Responseuses: lfreleng-actions/http-api-tool-docker@mainwith:
url: 'https://api.example.com/status'regex: '"status":\s*"ok"'max_response_time: '5'

Error Handling

The action provides detailed error messages for common scenarios:

  • Connection Errors: Network connectivity issues
  • Timeout Errors: Request or connection timeouts
  • Authentication Errors: Invalid credentials
  • Validation Errors: Unexpected status codes or response patterns
  • SSL Errors: Certificate verification failures

Development

Running Tests

# Install UV (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install development dependencies with hash verification
uv sync --frozen
# Run tests
uv run pytest tests/ -v
# Run with coverage
uv run pytest tests/ --cov=http_api_tool --cov-report=html

Integration Testing

The project includes a comprehensive integration test suite:

# Run all tests including integration tests
uv run pytest tests/ -v
# Run with coverage
uv run pytest tests/ --cov=http_api_tool --cov-report=html

The test suite validates:

  • Version display and help output
  • All HTTP methods (GET, POST, PUT, DELETE)
  • JSON request/response handling
  • Custom headers support
  • Regex pattern matching
  • Response time validation
  • Retry logic with backoff
  • HTTPS with SSL/TLS certificate validation

CI/CD Integration: The integration test suite runs automatically in GitHub Actions after every PyPI release using the go-httpbin-action for reliable, self-hosted testing. This ensures the published package version matches the git tag and all features work as expected.

Pre-commit Hooks

# Install pre-commit (included in dev dependencies)
uv sync --frozen
# Install hooks
uv run pre-commit install
# Run hooks manually
uv run pre-commit run --all-files

Docker Requirements Management

The Docker image uses a dynamic requirements generation approach where the Docker build process generates the requirements-docker.txt file to ensure correct platform compatibility.

If you need to manually regenerate for local development:

# Regenerate requirements-docker.txt with all dependencies and hashes# Note: This project now uses UV for dependency management# The Containerfile uses UV directly, so requirements-docker.txt is no longer needed# UV lock file (uv.lock) is automatically generated and used during builds# Test the Docker build
docker build -f docker/Containerfile . --platform linux/arm64 -t http-api-tool-test

The requirements-docker.txt file contains:

  • UV handles dependency resolution and locking automatically
  • SHA256 hashes in uv.lock file
  • Security protection against supply chain attacks
  • Ensures reproducible Docker builds

When to regenerate:

  • Updating dependencies in the project
  • Docker build failures with hash verification errors
  • Setting up the project for the first time
  • After changes to pyproject.toml affecting dependencies (run uv lock to regenerate lock file)

Local Development

# Test CLI functionality
uv run python -m http_api_tool test --help
# Test against local server
python -m http.server 8000 &
uv run python -m http_api_tool test --url http://localhost:8000

Testing with go-httpbin Service

For testing HTTP API functionality, you can either use the go-httpbin GitHub Action for workflows or set up a local go-httpbin service for development.

Using the go-httpbin GitHub Action

For GitHub Actions workflows, use the standalone go-httpbin action to set up an HTTPS testing service:

steps:
- name: Setup go-httpbin HTTPS serviceuses: lfreleng-actions/go-httpbin-action@fd9c3701056fc2e667542ac66b4a63c44faea6c5 # v0.1.0id: httpbinwith:
debug: 'true'port: '8080'
- name: Test API with go-httpbinuses: lfreleng-actions/http-api-tool-docker@mainwith:
url: 'https://localhost:8080/get'ca_bundle_path: 'mkcert-ca.pem'expected_http_code: '200'

Using Local go-httpbin Service for Development

For local development and testing:

# Build Docker image
docker build -f docker/Containerfile -t http-api-tool .# Run container
docker run --rm http-api-tool test \
--url https://example.com/api \
--expected-http-code 200

The local go-httpbin service provides all the same endpoints as httpbin.org but runs locally for faster, more reliable testing.

The setup-go-httpbin target automatically:

  • Installs mkcert if not present
  • Creates a local Certificate Authority (CA)
  • Generates SSL certificates for localhost
  • Saves the CA certificate as mkcert-ca.pem in the project root
  • Starts the go-httpbin service with proper HTTPS support

This ensures that SSL certificate validation remains enabled for all tests, providing a more realistic testing environment.

Migration from Shell Version

If you're migrating from the original shell-based implementation:

  1. Input Compatibility: Most inputs remain the same with updated naming
  2. Output Compatibility: Outputs are similar with enhanced information
  3. Behavior Changes:
    • Better JSON handling (no more escaping issues)
    • More robust error reporting
    • Improved retry logic with exponential backoff
    • Better SSL/TLS handling
    • Enhanced debugging output
    • More comprehensive response metrics

Package Management with UV

This project uses UV (fast Python package installer and resolver) for dependency management:

For Development

Install dependencies with:

# Install UV (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install development dependencies
uv sync --frozen

Run unit tests with:

uv run pytest tests/ -v

Requirements

  • Python 3.10+
  • UV (Fast Python package installer and resolver)
  • pycurl
  • typer (for CLI usage)

UV manages dependencies, with hash-verified lock files for reproducible builds.

License

Apache-2.0 License. See LICENSE for details.

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality (use uv run pytest)
  5. Run pre-commit hooks
  6. Submit a pull request

About

Tests an HTTP/HTTPS API service/endpoint

Resources

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages