HTTP load and smoke testing for APIs. Two-layer design: quick CLI for ad-hoc tests, scenario YAML for complex multi-step flows.
# Quick mode — one URL, no config file
htload https://api.example.com/health -c 10 -n 1000
# Scenario mode — multi-step, multi-phase, auth-aware
htload -f scenarios/smoke.yaml- Quick mode —
htload <url> [flags]. Zero ceremony. Supports GET/POST/PUT/DELETE/PATCH with headers and body. - Scenario mode — YAML-defined multi-step virtual-user flows with setup, multiple phases, and teardown.
- CRUD support — Every HTTP method. Inline bodies or
-D @file.json(curl convention). - Auth — Static bearer tokens, API keys, basic auth, OAuth client credentials. Or login-via-setup with variable capture.
- Assertions — Status code, jsonpath, response time thresholds.
- Captures — Extract values from responses and reuse in subsequent steps.
- Template interpolation —
{{.UUID}},{{.RandomString 8}},{{.Env.VAR}},{{.Vars.captured}}. - Multi-phase execution — Warmup → stress → cooldown, each with its own rate and duration.
- Thresholds —
--fail-if-p99 500ms --fail-if-rate 0.99. CI-friendly exit codes. - Reports — Console live output, JSON file output, Prometheus pushgateway (planned).
brew tap madstone-tech/tap
brew install ogougo install github.com/madstone-tech/ogou/cmd/htload@latestDownload the latest release for your platform from GitHub Releases.
tar -xzf ogou_Linux_x86_64.tar.gz
sudo mv htload /usr/local/bin/docker run --rm ghcr.io/madstone-tech/ogou:latest https://api.example.com/health -c 10htload https://httpbin.org/get -c 10 -n 100htload https://api.example.com/health \
-c 50 -d 5m \
--fail-if-p99 500ms \
--fail-if-rate 0.99htload https://api.example.com/users \
-X POST \
-D '{"email":"test@example.com"}' \
-H "Content-Type: application/json" \
-c 20 -d 60shtload https://api.example.com/users \
-X POST \
-D @payload.json \
-H "Content-Type: application/json" \
-c 20 -d 60sWrite a YAML file for complex, multi-step, authenticated flows:
name: api-smoke
base_url: https://api.example.com
auth:
strategy: bearer
token_from_env: API_TOKEN
phases:
- name: warmup
duration: 10s
rate:
constant: 1
steps:
- name: health
method: GET
path: /health
assertions:
- status: 200
- name: load
duration: 30s
rate:
ramp:
from: 5
to: 20
steps:
- name: list-orgs
method: GET
path: /api/v1/orgs
assertions:
- status: 200
- name: create-org
method: POST
path: /api/v1/orgs
body:
template: |
{"name":"Org-{{.RandomString 6}}","slug":"org-{{.RandomString 6}}"}
assertions:
- status: 201
captures:
- name: orgID
source: jsonpath
from: "$.id"
- name: get-org
method: GET
path: /api/v1/orgs/{{.Vars.orgID}}
assertions:
- status: 200Run it:
htload -f scenarios/api-smoke.yaml| Code | Meaning |
|---|---|
0 |
All successful, thresholds met. |
1 |
Failure or threshold breached. |
2 |
Invalid args or scenario. |
Import the engine and drive programmatically:
import (
"github.com/madstone-tech/ogou/pkg/engine"
"github.com/madstone-tech/ogou/pkg/http"
"github.com/madstone-tech/ogou/pkg/reporter"
)
scenario := engine.Scenario{
Name: "signup-flow",
BaseURL: "https://api.example.com",
Phases: []engine.Phase{{
Name: "load",
Duration: 30 * time.Second,
Rate: engine.RateProfile{Constant: intPtr(10)},
Steps: []engine.Step{{
Name: "create-org",
Method: "POST",
Path: "/api/v1/orgs",
Body: &engine.BodySource{Inline: `{"name":"test"}`},
}},
}},
}
driver := http.NewDriver(30 * time.Second)
rep := reporter.NewConsoleReporter()
runner := engine.NewRunner(driver, rep)
results, err := runner.Run(context.Background(), scenario)# Clone
git clone https://github.com/madstone-tech/ogou.git
cd ogou
# Install tools
task tools
# Run CI locally
task ci
# Run tests
task test
# Build binary
task build
# Run
./htload https://httpbin.org/get -c 10 -n 100See AGENTS.md for contributor guidance.
- HTTP driver
- Quick CLI mode
- Scenario YAML parser
- Multi-phase virtual users
- JSON response assertions (jsonpath)
- Response capture (jsonpath, header, regex)
- Template interpolation (UUID, RandomString, Env, Vars)
- Auth provisioners (bearer, apikey, basic, oauth-cc)
- JSON reporter
- Prometheus pushgateway reporter
- Docker multi-arch images
- Lambda runtime handler
Apache-2.0