HTTPCan
A modern, high‑performance superset of httpbin.org for testing HTTP clients, proxies, and AI agents — with mock OpenAI/Anthropic LLM APIs and a full OAuth 2.0 server. Built with Rust and Actix Web.
Hosted at https://httpcan.org — every endpoint is live there, zero install.
Quick Links: Quick Start · Installation · Configuration · Examples · OpenAPI & Homepage · API Reference · Production · Library · Development · License
✨ Features
- 84-endpoint superset of httpbin.org: every httpbin.org endpoint covered and drop‑in compatible, plus 33 endpoints httpbin.org doesn't have and 18 it has but httpcan fixes or extends — see the homepage for the full badge‑tagged list
- AI API mock: OpenAI- and Anthropic-compatible
/llmendpoints — point any SDKbase_urlat it (streaming included) and test AI clients without a paid provider - OAuth 2.0 mock: a full authorization server at
/oauth2— four RFC 6749 grants (authorization code + PKCE, implicit, password, rotating refresh, client credentials), Bearer-protected userinfo, and RFC 8414 discovery - AI‑friendly streaming: native
/sseand/ndjsonendpoints with OpenAI/Ollama‑compatible chunk formats - Measured performance: in our benchmarks against comparable HTTP testing servers, HTTPCan led on both throughput and tail latency
- Anti‑phishing redirects: browser clients hitting
/redirect-tosee a confirmation page instead of a silent 302, closing an open‑redirect abuse vector - Correct header handling: duplicate and non‑ASCII request headers are preserved instead of being dropped or crashing the server
- Safer by default: built‑in filtering strips ~100 reverse‑proxy/CDN headers from echoed responses, with
--exclude-headersfor more - Cloud‑native observability:
/healthzliveness probe,/tagsinstance identification, andServer-Timing/X-Httpcan-Versionheaders on every response - Self‑documenting homepage:
/lists every endpoint by category with compatibility badges and one‑click "Copy curl" buttons — fully static HTML, crawlable by search engines and AI agents - Tiny & fast: <10MB Docker image, minimal memory footprint, high throughput via Actix Web + Tokio
Quick Start
No install needed — the full API is hosted at https://httpcan.org:
Or run your own:
# Docker (recommended)
# Cargo
Installation
🐳 Docker
# Latest image
# Custom port
# Header filtering
📦 Cargo
# Install globally
# Run
🛠️ From Source
# Default (8080)
# Custom port
# Release build
🧰 Configuration
CLI flags:
| Option | Description | Default | Example |
|---|---|---|---|
-p, --port <PORT> |
Port number to listen on. Also settable via HTTPCAN_PORT |
8080 |
--port 3000 |
--openapi-servers <MODE> |
How /openapi.json builds its servers array: current-first (default) prepends the instance the visitor is talking to; spec-only serves the spec's own servers verbatim. Also settable via HTTPCAN_OPENAPI_SERVERS |
current-first |
--openapi-servers spec-only |
--exclude-headers <HEADERS> |
Exclude headers in responses; comma‑separated; supports wildcard suffix (e.g., x-bar-*). Also settable via HTTPCAN_EXCLUDE_HEADERS |
"" |
--exclude-headers "x-forwarded-*,cf-*,server" |
--max-bytes <BYTES> |
Max bytes for /bytes, /stream-bytes, /range, and /drip; over‑limit returns 404 instead of truncating (httpbin #594). Also settable via HTTPCAN_MAX_BYTES |
102400 |
--max-bytes 1048576 |
--canonical-scheme <auto|http|https> |
Scheme for SEO‑facing URLs only (canonical link, sitemap.xml, robots.txt); doesn't affect copy‑curl examples or the OpenAPI current server, which always mirror the actual request. Also settable via HTTPCAN_CANONICAL_SCHEME |
auto |
--canonical-scheme https |
--static-dir <DIR> |
Static assets directory: user overrides for openapi.json, favicon.png, index.html, robots.txt, sitemap.xml, plus extra files served at /static/<name> or /<name>. Also settable via HTTPCAN_STATIC_DIR |
binary-relative static, else ./static |
--static-dir /etc/httpcan/static |
--oauth2-clients <ID:SECRET,…> |
OAuth 2.0 client registry for /oauth2: when set, client secrets are validated (invalid_client on mismatch); when empty, any non‑empty secret passes (mock mode). Also settable via HTTPCAN_OAUTH2_CLIENTS |
(empty) | --oauth2-clients "webapp:s3cr3t,cli:an0ther" |
-h, --help |
Print help information | --help |
|
-V, --version |
Print version | --version |
Notes:
- Built‑in filtering includes reverse proxy/CDN providers (Nginx, Cloudflare, AWS, GCP, Azure).
- When using Docker, ensure
-p host:containermapping matches your--portif you override it.
Any flag backed by an environment variable (e.g. HTTPCAN_CANONICAL_SCHEME) can also be set via a .env file in the working directory — handy for a bare‑binary deployment on a server, where there's no Docker --env-file/env_file: or systemd EnvironmentFile= to inject real environment variables for you:
# .env
HTTPCAN_CANONICAL_SCHEME=https
.env values are loaded before CLI flags are parsed, so an explicit --canonical-scheme flag still takes precedence over HTTPCAN_CANONICAL_SCHEME in .env.
Usage Examples
# Basic GET
# POST with JSON
Auth
# Basic auth
# Username only (empty password) — enhanced
Status & Redirects
# Specific status
# Random from list
# Inject response headers (rate-limit / Retry-After testing)
# Redirect to a URL (supports form/json)
🔒 Open‑redirect protection on
/redirect‑toUnlike a naive 302,
/redirect-todetects browser clients (viaAccept: text/html) and returns an interstitial warning page instead of silently redirecting. This prevents phishing abuse where attackers exploit your trusted domain (e.g.…/redirect-to?url=https://evil.com).
- Programmatic clients (curl, httpx, …) still receive the standard
302— no API breakage.- Browser clients get a
200HTML page showing the destination URL and requiring an explicit click.- Non‑
http(s)URL schemes (javascript:,data:, …) render as a disabled link.- Destination URLs are HTML‑escaped in the interstitial to prevent XSS.
- The page carries
X-Robots-Tag: noindexto avoid search‑engine indexing.
Compression & Formats
Streaming (SSE/NDJSON)
# SSE
&format=simple
&delay=2000
# NDJSON
&format=simple
&model=llama3&delay=1500
AI API Mock
# OpenAI-compatible chat completions (streaming supported)
# Anthropic-compatible messages
# OpenAI-compatible Responses API
# OpenAI-compatible legacy completions (text-in/text-out)
Point an SDK at it — no API key needed (any value is accepted), and responses are deterministic:
=
=
# Custom reply text
The Anthropic SDK works with base_url="https://httpcan.org/llm" (it appends /v1/messages itself). GET /llm returns a self-describing index, and GET /llm/v1/models returns the model list in whichever family's shape the request looks like (an anthropic-version header switches it).
OAuth 2.0 Mock
# 1) Send the resource owner to the authorization endpoint (consent page)
# 2) Exchange the one-time code (Basic or form-body client auth; PKCE supported)
# 3) Call the Bearer-protected resource
All four RFC 6749 grants work: authorization_code (with PKCE S256/plain), password, refresh_token (rotating — a presented refresh token is single-use), and client_credentials. response_type=token (implicit flow, legacy) hands out the access token in the redirect fragment. Codes are one-time, tokens are HMAC-signed per process, and the consent email is the only identity. GET /oauth2 is a self-describing index; GET /.well-known/oauth-authorization-server serves RFC 8414 metadata for discovery-based clients.
Cookies & Inspection
OpenAPI & Homepage
- OpenAPI spec:
GET /openapi.json - API catalog (RFC 9727, automated discovery):
GET /.well-known/api-catalog— a Linkset pointing agents at the spec, docs, and health probe; URLs mirror the request origin - Homepage: visit
/for a static, crawlable page listing every endpoint by category, each with a compatibility badge (Enhanced/New) relative to httpbin.org and a one‑click "Copy curl" button (pre‑filled with sample parameters and resolved against the instance you're viewing). It always renders as HTML, regardless of theAcceptheader — no JavaScript required to read the content.
API Reference
Endpoints are grouped into the same categories shown on the homepage (/) — visit a running instance for the full interactive list with compatibility badges and copy‑ready curl examples:
| Category | Endpoints |
|---|---|
| HTTP Methods | /get /post /put /patch /delete /method /head /options /trace /query /echo |
| Anything | /anything /anything/{path} |
| Auth | /basic-auth /hidden-basic-auth /bearer /jwt-bearer /digest-auth |
| Status codes | /status/{codes} |
| Request inspection | /headers /ip /user-agent |
| Response inspection | /cache /etag /response-headers |
| Response formats | /json /xml /html /robots.txt /deny /encoding/utf8 /encoding/iso-8859-1 /gzip /deflate /brotli /zstd |
| Dynamic data | /uuid /base64 /bytes /stream-bytes /stream /range /links /drip /delay |
| Cookies | /cookies /cookies/set /cookies/delete |
| Images | /image /image/png /image/jpeg /image/webp /image/svg |
| Redirects | /redirect /relative-redirect /absolute-redirect /redirect-to |
| Streaming | /sse /ndjson |
| AI API Mock | /llm/v1/chat/completions /llm/v1/messages /llm/v1/responses /llm/v1/completions /llm/v1/models |
| OAuth 2.0 Mock | /oauth2/authorize /oauth2/token /oauth2/userinfo |
| Observability | /healthz /tags |
Every endpoint carries a compatibility badge relative to httpbin.org:
- (no badge) — drop‑in compatible with httpbin.org
- Enhanced — httpbin.org has this endpoint, but httpcan fixes a bug or extends it
- New — not available in httpbin.org
For full parameter details and schemas, consult the OpenAPI spec.
HTTPCan Enhancements
- Echo endpoint:
/echoreflects request body and headers (multi‑method) - Methods+:
QUERYHTTP method (RFC 9430 — a safe, idempotent GET with a body) accepted on/anything,/anything/{anything}, and/echo, with a dedicated/queryendpoint echoing URL args plus the parsed body - Auth+: Basic auth with username only; JWT Bearer decode/inspect at
/jwt-bearer - Status+: Content‑type priority:
Accept> requestContent-Type> default; supports custom bodies via query/body - Redirects+:
POST /redirect-tosupportsapplication/x-www-form-urlencoded,multipart/form-data,application/json; browser clients get an open-redirect interstitial (see above) - Streaming+: SSE/NDJSON endpoints with
count,delay, and AI formats (OpenAI/Ollama) - File uploads+: Multiple files with the same field return as array across multipart endpoints
- Observability+:
/healthzliveness probe;/tagsexposesHTTPCAN_*env vars; every response carriesServer-TimingandX-Httpcan-Versionheaders - Method echo+:
/methodechoes any method name;/head/options/trace/queryare dedicated echo endpoints; GET endpoints also answerHEAD - Status headers+:
?header=Name:Valueinjects response headers on/status/{codes}(repeatable; e.g.Retry-Afterfor rate‑limit testing) - Body encoding+: POST to
/gzip,/deflate,/brotli,/zstd, or/base64returns the request body in the matching encoding
🚀 Production Considerations
Before deploying HTTPCan on the public internet, review these hardening options:
- Open‑redirect protection on
/redirect‑to: Browser clients (detected viaAccept: text/html) receive an interstitial warning page showing the destination URL instead of a silent302. This blocks phishing abuse via…/redirect-to?url=https://evil.comon your trusted domain. Programmatic clients (curl, httpx, …) still get the standard302for API compatibility. Non‑http(s)URL schemes render as a disabled link. - No reflected XSS on
/base64: Decoded content is always returned astext/plain; charset=utf-8, nevertext/html. Browsers display the raw text without rendering embedded<script>tags. - Response header filtering:
- Built‑in (always on): ~100 reverse‑proxy/CDN headers are stripped from all echoed responses by default — Nginx (
x-real-ip,x-forwarded-*), Cloudflare (cf-*), AWS CloudFront/ALB (cloudfront-*,x-amzn-*), GCP (x-appengine-*,x-cloud-trace-context), Azure (x-azure-*,x-ms-*). Prevents infrastructure information leakage without any configuration. - Custom (
--exclude-headers): Add your own patterns to strip additional sensitive headers, with wildcard suffix support:--exclude-headers "x-internal-*,server,x-secret-token".
- Built‑in (always on): ~100 reverse‑proxy/CDN headers are stripped from all echoed responses by default — Nginx (
- Resource limits:
--max-bytescaps/bytesand/stream-bytesresponses (default 100KB); over‑limit requests return404instead of silently truncating (httpbin #594). - Non‑root Docker: The official image runs as a dedicated unprivileged user (
uid 10001).
🎨 Self-Hosting & Customization
The binary is fully self-contained: the OpenAPI spec and favicon are embedded at compile time, and /, /robots.txt, and /sitemap.xml are generated per request. To customize your instance, drop files into a static assets directory (--static-dir, or the default static/ next to the binary / ./static; in Docker, mount a volume at /httpcan/static — files must be world-readable for uid 10001):
| File in static dir | Replaces | Notes |
|---|---|---|
openapi.json |
embedded spec at /openapi.json |
The current server is still injected into servers (verbatim with --openapi-servers spec-only) |
favicon.png |
embedded favicon at /favicon.png |
|
index.html |
generated homepage at / |
Forfeits origin-resolved curl examples, markdown negotiation, and Link headers |
robots.txt |
generated policy at /robots.txt |
E.g. Disallow: * for private instances |
sitemap.xml |
generated index at /sitemap.xml |
Absolute URLs in a static file don't follow the request origin or --canonical-scheme |
Behavior notes:
- Files are checked per request — adding or replacing a file takes effect immediately, no restart. The directory itself must exist at startup.
- Every other file in the directory is served at
/static/<name>(and at/<name>when the name doesn't collide with an API route). - Reserved: files named after API routes (
json,get,image, …) never shadow those routes; dot‑prefixed files are rejected with 400.
🦀 Library Usage
Add dependency:
[]
= "0.6"
Embed server:
use HttpCanServer;
async
More examples and advanced config: see LIBRARY_USAGE.md.
Development
# Run checks
# Run locally
Contributions are welcome! Please open issues/PRs for discussion.
License
MIT — see LICENSE.