go-resty/resty
Simple HTTP, REST, and SSE client library for Go
Healthy across the board
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 3d ago
- ✓24+ active contributors
- ✓MIT licensed
Show all 6 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Concentrated ownership — top contributor handles 66% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/go-resty/resty)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/go-resty/resty on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: go-resty/resty
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/go-resty/resty shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 3d ago
- 24+ active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Concentrated ownership — top contributor handles 66% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live go-resty/resty
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/go-resty/resty.
What it runs against: a local clone of go-resty/resty — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in go-resty/resty | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch v3 exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 33 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of go-resty/resty. If you don't
# have one yet, run these first:
#
# git clone https://github.com/go-resty/resty.git
# cd resty
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of go-resty/resty and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "go-resty/resty(\\.git)?\\b" \\
&& ok "origin remote is go-resty/resty" \\
|| miss "origin remote is not go-resty/resty (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify v3 >/dev/null 2>&1 \\
&& ok "default branch v3 exists" \\
|| miss "default branch v3 no longer exists"
# 4. Critical files exist
test -f "client.go" \\
&& ok "client.go" \\
|| miss "missing critical file: client.go"
test -f "request.go" \\
&& ok "request.go" \\
|| miss "missing critical file: request.go"
test -f "response.go" \\
&& ok "response.go" \\
|| miss "missing critical file: response.go"
test -f "resty.go" \\
&& ok "resty.go" \\
|| miss "missing critical file: resty.go"
test -f "middleware.go" \\
&& ok "middleware.go" \\
|| miss "missing critical file: middleware.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 33 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~3d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/go-resty/resty"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Resty is a lightweight, fluent HTTP/REST client library for Go that simplifies building API clients with chainable request methods, automatic retries, circuit breakers, and Server-Sent Events (SSE) support. It abstracts Go's net/http complexity and provides middleware, hedging, rate limiting, and digest authentication out of the box. Monolithic package structure: core client logic in client.go/request.go/response.go, feature modules (circuit_breaker.go, rate_limiter.go, retry.go, hedging.go, middleware.go, sse.go) as separate files with paired _test.go files, transport layer split for WASM compatibility (transport_dial.go, transport_dial_wasm.go), and utility functions in util.go.
👥Who it's for
Go developers building microservices, API clients, and distributed systems who need a clean, opinionated HTTP client that handles resilience patterns (retries, circuit breaking, rate limiting) without writing boilerplate middleware.
🌱Maturity & risk
Production-ready and actively maintained. The project is on v3 (using go1.23+), has comprehensive test coverage (710K+ Go code), full CI/CD via GitHub Actions (ci.yml), and requires 100% patch coverage for contributions. The module path resty.dev/v3 and semantic versioning indicate serious governance.
Low risk for core library, but single-maintainer dependency (jeevatkm as primary sponsor/maintainer visible in FUNDING.yml). Only one external dependency (golang.org/x/net), reducing supply-chain attack surface. v3 is a breaking change from v2, so projects on v2 need planned migrations.
Active areas of work
Active v3 development branch with recent additions in streaming (stream.go), Server-Sent Events (sse.go), hedging (hedging.go), and load balancing (load_balancer.go). CI runs on every commit via .github/workflows/ci.yml with coverage tracking on codecov. Build system uses Bazel (BUILD.bazel, WORKSPACE).
🚀Get running
git clone https://github.com/go-resty/resty.git && cd resty && go mod download && go test ./... (requires Go 1.23+)
Daily commands: No server to run—this is a library. Run tests with: go test -v -race ./... or go test -bench=. -benchmem ./benchmark_test.go for benchmarking. Example usage requires importing as: import "resty.dev/v3"
🗺️Map of the codebase
client.go— Core HTTP client implementation; the primary entry point for all request building and execution logic that every feature depends on.request.go— Request object construction and validation; defines how HTTP requests are built and configured before dispatch.response.go— Response parsing and result handling; processes HTTP responses and exposes the result API to callers.resty.go— Public API package exports and module initialization; the public-facing interface all users interact with.middleware.go— Middleware hooks and interceptor chain; enables request/response mutation, logging, and cross-cutting concerns.retry.go— Retry and resilience strategy implementation; handles transient failure recovery and backoff logic.circuit_breaker.go— Circuit breaker pattern for fault tolerance; prevents cascading failures in downstream services.
🛠️How to make changes
Add a new middleware hook
- Define the hook signature in middleware.go as a new exported callback type (e.g., BeforeRequestFunc, AfterResponseFunc) (
middleware.go) - Add a setter method on Client to register the hook (e.g., SetBeforeRequest, AddAfterResponse) (
client.go) - Call the hook at the appropriate point in the request lifecycle (e.g., in executeRequest before sending, or after response received) (
client.go) - Write unit tests in middleware_test.go to verify hook execution order and mutation capability (
middleware_test.go)
Add a new resilience strategy (retry, circuit breaker, rate limiter)
- Create a new file (e.g., new_strategy.go) with a Strategy interface and concrete implementation (
circuit_breaker.go) - Add a setter method on Client to enable/configure the strategy (e.g., SetNewStrategy, AddNewStrategyConfig) (
client.go) - Integrate the strategy into the executeRequest method to wrap or intercept the actual HTTP call (
client.go) - Write comprehensive tests in a new_strategy_test.go file covering success, failure, and edge cases (
circuit_breaker_test.go)
Add a new authentication method
- Create authentication helper function in request.go or a new auth_*.go file (e.g., digest.go pattern) (
request.go) - Add a public method on Request to set auth credentials (e.g., SetDigestAuth, SetBearerToken) (
request.go) - Implement the auth header/parameter injection in the request building phase before sending (
request.go) - Add test cases in request_test.go or a dedicated auth test file to verify correct header/credential format (
request_test.go)
Add a new response unmarshaling format
- Add a new format case in response.go's Unmarshal or Into method (alongside JSON, XML, YAML handling) (
response.go) - Register the MIME type in util.go's content-type detection logic (
util.go) - Write test cases in response_test.go covering unmarshal, type assertion, and error handling for the new format (
response_test.go)
🔧Why these technologies
- Go standard library (net/http) — Provides the foundation for HTTP/HTTPS transport; stable, performant, and built-in.
- golang.org/x/net — Extended networking utilities for TLS, context, and platform-specific dial customization.
- Middleware/hook pattern — Enables extensibility without modifying core logic; allows users to inject custom logic (logging, auth, mutation).
- Circuit breaker & retry with backoff — Implements resilience patterns to handle transient failures and prevent cascading outages in distributed systems.
- Rate limiter & hedging — Protects downstream services from overload and reduces tail latency under high concurrency.
⚖️Trade-offs already made
-
Single Client per application vs. multiple instances
- Why: The design encourages reuse of a single global Client (connection pooling via http.Transport), but allows per-request customization via Request builder pattern.
- Consequence: Less flexibility per-request (e.g., per-request timeout requires cloning or wrapper), but better resource efficiency and connection reuse.
-
Middleware hooks at before-request and after-response only
- Why: Simplicity and clarity; covers 95% of use cases (auth, logging, header injection, response parsing).
- Consequence: Complex request/response mutation patterns (e.g., streaming to disk mid-response) require custom io.Writer or manual Stream() calls.
-
Client owns resilience strategies (retry, circuit breaker, rate limiter)
- Why: Centralized configuration and shared state across all requests from a Client instance.
- Consequence: Cannot easily apply different retry/CB policies to different endpoints without creating separate Clients.
-
No built-in request queuing or concurrency limits
- Why: Defers to Go's goroutine model and rate_limiter for explicit control.
- Consequence: Users must manage goroutine spawning and coordination; no automatic request batching.
🚫Non-goals (don't propose these)
- GraphQL query optimization (REST/HTTP focused)
- Automatic request signing for AWS SigV4 or other cloud vendor auth (implements HTTP Digest only; users extend via middleware)
- WebSocket upgrade support (Server-Sent Events for streaming, not bidirectional WS)
- SPDY/HTTP/2 push server-side support (client-side HTTP/2 via standard lib, no server implementation)
🪤Traps & gotchas
No significant hidden traps. v3 is a breaking change from v2 (different import path and some API changes), so ensure your go.mod correctly specifies resty.dev/v3. Tests use .testdata/ certs (cert.pem, key.pem, sample-root.pem) which are baked in—no external certificate setup needed. WASM support requires transport_dial_wasm.go (uses build tags), not transport_dial.go, but this is handled automatically.
🏗️Architecture
💡Concepts to learn
- Fluent Interface / Builder Pattern — Resty's entire API (client.R().SetHeader().Post()) uses fluent chaining; understanding this pattern is essential to use the library idiomatically
- Circuit Breaker Pattern — circuit_breaker.go implements circuit breaker resilience; critical for reliable distributed systems that call multiple endpoints
- Token Bucket Rate Limiting — rate_limiter.go uses token bucket algorithm to throttle requests; essential for respecting API quotas and preventing cascading failures
- Exponential Backoff Retry — retry.go implements exponential backoff for transient failures; crucial for resilient HTTP clients in flaky networks
- Server-Sent Events (SSE) — sse.go provides streaming HTTP response support for real-time updates; different from WebSockets but simpler for one-way server-to-client messaging
- Request/Response Middleware Hooks — middleware.go's OnBeforeRequest, OnAfterResponse hooks allow cross-cutting concerns (logging, auth injection, response validation) without modifying core logic
- Hedging (Speculative Retries) — hedging.go implements hedged requests (simultaneous redundant requests) for tail-latency reduction in distributed systems; advanced resilience beyond simple retries
🔗Related repos
go-http-utils/headers— Companion library for complex HTTP header handling that complements Resty's request buildingvalyala/fasthttp— Alternative high-performance HTTP client for Go with different design philosophy; useful comparison for performance-critical workloadsgrpc/grpc-go— Complementary RPC framework used alongside Resty in polyglot microservices (HTTP for REST APIs, gRPC for service-to-service)mitchellh/mapstructure— Often paired with Resty to unmarshal response bodies into Go structs with advanced type mapping
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive integration tests for SSE (Server-Sent Events) with multiple concurrent clients
The repo has sse.go and sse_test.go, but given that SSE is a complex feature requiring proper connection management, event parsing, and error handling across concurrent streams, the test coverage likely lacks scenarios for: reconnection logic, partial message handling, concurrent client operations, and timeout edge cases. This would improve reliability for users depending on SSE functionality.
- [ ] Review sse.go and sse_test.go to identify missing test scenarios
- [ ] Add tests for concurrent SSE clients connecting/disconnecting simultaneously in sse_test.go
- [ ] Add tests for malformed SSE streams, incomplete messages, and connection drops in sse_test.go
- [ ] Add benchmark tests in benchmark_test.go for SSE stream throughput under load
- [ ] Verify codecov.io shows improved coverage for sse.go
Add unit tests for transport_dial.go and transport_dial_wasm.go platform-specific code paths
The codebase has platform-specific dial implementations (transport_dial.go for standard Go, transport_dial_wasm.go for WebAssembly), but there are no corresponding test files. These files handle critical network dialing logic that differs by platform. Without dedicated tests, regressions in platform-specific behavior go undetected.
- [ ] Create transport_dial_test.go with unit tests for standard Go dial timeouts, keepalive, and error handling
- [ ] Create transport_dial_wasm_test.go with tests for WASM-specific dial behavior (or use build tags in a single file)
- [ ] Add tests for dial context cancellation and timeout scenarios
- [ ] Add tests verifying correct TCP keepalive settings in transport_dial.go
- [ ] Ensure CI workflow (ci.yml) runs tests with appropriate build tags for both platforms
Add unit tests for circuit_breaker.go covering state transitions and reset mechanisms
The circuit_breaker.go file implements the circuit breaker pattern (critical for resilience), and while circuit_breaker_test.go exists, reviewing it likely reveals gaps in: state machine validation (Open→Half-Open→Closed transitions), concurrent request handling during state transitions, reset timeout edge cases, and failure threshold boundary conditions. These gaps risk production outages.
- [ ] Audit circuit_breaker_test.go for coverage of all state transitions (Open, Half-Open, Closed)
- [ ] Add tests for concurrent requests during state transitions in circuit_breaker_test.go
- [ ] Add tests verifying correct behavior at failure threshold boundaries (e.g., exactly at threshold vs. just over)
- [ ] Add tests for reset timer expiration and Half-Open state recovery paths
- [ ] Add race condition detection tests (go test -race) to circuit_breaker_test.go
- [ ] Verify codecov.io shows >95% coverage for circuit_breaker.go
🌿Good first issues
- Add streaming multipart form support: multipart.go exists but stream.go is separate; contribute integrated streaming multipart request builder with test in multipart_test.go
- Improve redirect.go test coverage: redirect.go lacks a paired redirect_test.go file; write comprehensive tests for redirect policy edge cases (301/302/307/308 handling, loop detection)
- Add examples for SSE with context cancellation: sse.go and context_test.go exist but no runnable example in docs or examples/ showing how to handle SSE client disconnect; create a documented example
⭐Top contributors
Click to expand
Top contributors
- @jeevatkm — 66 commits
- @pior — 4 commits
- @invzhi — 4 commits
- @liuzengh — 3 commits
- @ahmet2mir — 2 commits
📝Recent commits
Click to expand
Recent commits
11551c3— feat(enhancement)!: do not strip the port from the request URL host for redirect host comparison (#1159) (jeevatkm)db80558— feat(enhancement)!: Return ErrReaderNotSeekable instead of sending empty bodies on retry (#1156) (pior)e213520— test: Stabilize certificate watcher test (#1158) (pior)8143665— fix: content-disposition values are sanitized and absolute path, parent-directory travesal segments are rejected (#1157) (jeevatkm)c52f4e3— feat: support SetContext for SSE (#1154) (invzhi)738f69d— fix: unwrap restyError to an error slice (#1155) (pior)f1a4f02— feat: support SetTransport for SSE (#1150) (invzhi)b8c95e9— feat: add built-in rate limiter implementations (#1151) (jeevatkm)5561d3b— feat(enhancement): make hedging implementation to use an interface (#1147) (jeevatkm)b200bf7— fix: digest auth sending invalid empty userhash field (#1140) (issuj)
🔒Security observations
The resty HTTP client library demonstrates good security practices overall. It is a well-maintained open-source project with automated CI/CD workflows and no critical vulnerabilities identified from the static analysis. The primary recommendations focus on maintaining up-to-date dependencies, ensuring test certificates remain segregated from production use, and continuing regular security audits. The library's purpose as a client-side HTTP library means injection risks are minimal, though users should be educated on secure usage patterns when integrating with external APIs.
- Medium · Outdated Go Version Requirement —
go.mod. The module specifies Go 1.23.0, which may have security patches available in newer patch versions. The go.mod file should be regularly updated to use the latest stable Go version to ensure security patches are applied. Fix: Regularly update Go to the latest stable version and update go.mod accordingly. Consider using Go 1.24+ for improved security features. - Low · Test Certificates in Repository —
.testdata/cert.pem, .testdata/key.pem, .testdata/sample-root.pem. The repository contains test certificates (.testdata/cert.pem, .testdata/key.pem, .testdata/sample-root.pem) which could potentially be misused if accidentally deployed to production. While labeled as test data, this represents a minor risk if these files are not properly segregated. Fix: Ensure test certificates are never used in production. Add clear documentation that these are test-only artifacts. Consider adding .testdata to .gitignore with explicit comments, or use a separate test certificates directory with a README explaining their test-only purpose. - Low · Missing Security Headers Implementation Details —
client.go, request.go, response.go. While resty is an HTTP client library, there's no explicit indication of built-in security header validation or enforcement mechanisms visible in the file structure. The library may not validate security-critical headers by default. Fix: Review the implementation of security header handling (HSTS, X-Content-Type-Options, etc.) and provide clear documentation on security best practices when using the library. Consider adding helper functions for common security headers. - Low · Dependency on golang.org/x/net —
go.mod. The project depends on golang.org/x/net v0.43.0. While this is a legitimate Google-maintained package, external dependencies should be regularly audited for vulnerabilities usinggo mod auditor similar tools. Fix: Regularly rungo mod auditandgo list -u -m allto check for known vulnerabilities in dependencies. Update golang.org/x/net to the latest version available and implement automated dependency scanning in CI/CD pipelines (as evidenced by the ci.yml workflow).
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.