A Python HTTP/HTTPS API testing tool for GitHub Actions and CLI usage
Project description
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 releasevX.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: Configurable exponential backoff with jitter
- 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@main
with:
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.12
uses: lfreleng-actions/http-api-tool-docker@main
with:
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@main
with:
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 CA
uses: lfreleng-actions/http-api-tool-docker@main
with:
deploy: 'docker'
url: 'https://internal-api.company.com/health'
ca_bundle_path: '/path/to/ca-certificates.pem'
expected_http_code: '200'
Deployment Method Comparison:
| Feature | uvx (default) | docker |
|---|---|---|
| Speed | ⚡ Fast (~10s) | 🐌 Slower (~60s for build) |
| Isolation | Process-level | Container-level |
| Caching | PyPI cache | Docker layer cache |
| Use Case | Most scenarios | Special 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
| Input | Description | Required | Default |
|---|---|---|---|
deploy |
Deployment method: uvx (fast, default) or docker (containerized) |
No | uvx |
python_version |
Python version to use when deploy=uvx | No | 3.11 |
url |
URL of API server/interface to check | Yes | - |
auth_string |
Authentication string, colon separated username/password | No | - |
service_name |
Name of HTTP/HTTPS API service tested | No | API Service |
initial_sleep_time |
Time in seconds between API service connection attempts | No | 1 |
max_delay |
Max delay in seconds between retries | No | 30 |
retries |
Number of retries before declaring service unavailable | No | 3 |
expected_http_code |
HTTP response code to accept from the API service | No | 200 |
regex |
Verify server response with regular expression | No | - |
show_header_json |
Display response header as JSON in action output | No | false |
curl_timeout |
Max time in seconds for cURL to wait for a response | No | 5 |
http_method |
HTTP method to use (GET, POST, PUT, etc.) | No | GET |
request_body |
Data to send with POST/PUT/PATCH requests | No | - |
content_type |
Content type for the request body | No | application/json |
request_headers |
Custom HTTP headers sent in JSON format | No | - |
verify_ssl |
Verify SSL certificates | No | true |
ca_bundle_path |
Path to CA bundle file for SSL verification | No | - |
include_response_body |
Include response body in outputs (base64) | No | false |
follow_redirects |
Follow HTTP redirects | No | true |
max_response_time |
Max acceptable response time in seconds | No | 0 |
connection_reuse |
Reuse connections between requests | No | true |
debug |
Enables debugging output | No | false |
fail_on_timeout |
Fail if response time exceeds max_response_time | No | false |
Outputs
| Output | Description |
|---|---|
time_delay |
Number of seconds waiting for service availability/failure |
response_http_code |
HTTP response code received from the server |
response_header_json |
HTTP response header as JSON |
response_header_size |
HTTP response header size in bytes |
response_body_size |
HTTP response body size in bytes |
regex_match |
Whether the regular expression matched the server reply |
response_body_base64 |
Response body base64 encoded (when enabled) |
total_time |
Total time for the request in seconds |
connect_time |
Time to establish connection in seconds |
response_time_exceeded |
Whether 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 Check
uses: lfreleng-actions/http-api-tool-docker@main
with:
url: 'https://api.example.com/health'
expected_http_code: '200'
POST with JSON Data
- name: Create User
uses: lfreleng-actions/http-api-tool-docker@main
with:
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 Resource
uses: lfreleng-actions/http-api-tool-docker@main
with:
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 Response
uses: lfreleng-actions/http-api-tool-docker@main
with:
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.tomlaffecting dependencies (runuv lockto 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 service
uses: lfreleng-actions/go-httpbin-action@fd9c3701056fc2e667542ac66b4a63c44faea6c5 # v0.1.0
id: httpbin
with:
debug: 'true'
port: '8080'
- name: Test API with go-httpbin
uses: lfreleng-actions/http-api-tool-docker@main
with:
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.pemin 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:
- Input Compatibility: Most inputs remain the same with updated naming
- Output Compatibility: Outputs are similar with enhanced information
- 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
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality (use
uv run pytest) - Run pre-commit hooks
- Submit a pull request
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file http_api_tool-1.0.5.tar.gz.
File metadata
- Download URL: http_api_tool-1.0.5.tar.gz
- Upload date:
- Size: 112.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d3d2c2c05c41a54bcf8c76740e12b6bac5ca4ee69756fce1548403aa4396291d
|
|
| MD5 |
354872b48784f095a064fe78af4ab3cf
|
|
| BLAKE2b-256 |
2fa4d1c517523343daf6a75db9924bd21bca0fc97e0dc31eb66482929a3b93ea
|
Provenance
The following attestation bundles were made for http_api_tool-1.0.5.tar.gz:
Publisher:
build-test-release.yaml on lfreleng-actions/http-api-tool-docker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
http_api_tool-1.0.5.tar.gz -
Subject digest:
d3d2c2c05c41a54bcf8c76740e12b6bac5ca4ee69756fce1548403aa4396291d - Sigstore transparency entry: 1271291038
- Sigstore integration time:
-
Permalink:
lfreleng-actions/http-api-tool-docker@d65d674b2761b55f3213e88344c277bdc08004d6 -
Branch / Tag:
refs/tags/v1.0.5 - Owner: https://github.com/lfreleng-actions
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-test-release.yaml@d65d674b2761b55f3213e88344c277bdc08004d6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file http_api_tool-1.0.5-py3-none-any.whl.
File metadata
- Download URL: http_api_tool-1.0.5-py3-none-any.whl
- Upload date:
- Size: 25.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33317e5cf3fd860665dfb799778cb2de840c95ad542eca2dc6e64deeebfbd84e
|
|
| MD5 |
9b64883e0ab43eb3e5258515a78111db
|
|
| BLAKE2b-256 |
50cd51483c5ec0d333bd0fe97617835d297b4d886f42207aa4f8eaa6fb24821e
|
Provenance
The following attestation bundles were made for http_api_tool-1.0.5-py3-none-any.whl:
Publisher:
build-test-release.yaml on lfreleng-actions/http-api-tool-docker
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
http_api_tool-1.0.5-py3-none-any.whl -
Subject digest:
33317e5cf3fd860665dfb799778cb2de840c95ad542eca2dc6e64deeebfbd84e - Sigstore transparency entry: 1271291051
- Sigstore integration time:
-
Permalink:
lfreleng-actions/http-api-tool-docker@d65d674b2761b55f3213e88344c277bdc08004d6 -
Branch / Tag:
refs/tags/v1.0.5 - Owner: https://github.com/lfreleng-actions
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-test-release.yaml@d65d674b2761b55f3213e88344c277bdc08004d6 -
Trigger Event:
push
-
Statement type: