Documentation
¶
Overview ¶
Package http wraps an http.RoundTripper so outbound client calls are subject to chaos. Construct an engine, attach rules, then pass http.DefaultTransport (or any RoundTripper) and the engine to WrapTransport. The returned RoundTripper is safe to share across goroutines.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MutateResponse ¶ added in v1.27.0
MutateResponse returns a fault that runs fn on the *http.Response after a successful round-trip, replacing the response the caller observes with fn's return value. fn runs only on the success path; on a transport error the native error passes through untouched. fn must not eagerly drain resp.Body; wrap it lazily if a body transform is needed.
func WrapTransport ¶
func WrapTransport(rt http.RoundTripper, eng *engine.Engine) http.RoundTripper
WrapTransport returns a RoundTripper that consults eng on every request. If eng is nil or has no rules, the wrapper is a near-zero-cost passthrough.
Example ¶
package main
import (
"errors"
"fmt"
"net/http"
"net/http/httptest"
chaoshttp "github.com/RomanAgaltsev/chaotic/adapter/http"
"github.com/RomanAgaltsev/chaotic/engine"
"github.com/RomanAgaltsev/chaotic/fault"
)
func main() {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = fmt.Fprintln(w, "ok")
}))
defer srv.Close()
// Fail only the first request with a transient error.
eng := engine.New().AddRule(engine.NewRule(
engine.MatchKind(engine.OpHTTPClient),
engine.Times(1),
engine.WithFault(fault.Error(errors.New("transient"))),
).Named("flap"))
client := &http.Client{Transport: chaoshttp.WrapTransport(http.DefaultTransport, eng)}
resp1, err := client.Get(srv.URL)
if resp1 != nil {
resp1.Body.Close()
}
fmt.Println("attempt 1 failed:", err != nil)
resp, err := client.Get(srv.URL)
if err != nil {
fmt.Println("attempt 2 error:", err)
return
}
defer resp.Body.Close()
fmt.Println("attempt 2 status:", resp.StatusCode)
}
Output: attempt 1 failed: true attempt 2 status: 200
Example (HttpStatus) ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
chaoshttp "github.com/RomanAgaltsev/chaotic/adapter/http"
"github.com/RomanAgaltsev/chaotic/engine"
"github.com/RomanAgaltsev/chaotic/fault"
)
func main() {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
}))
defer srv.Close()
eng := engine.New().AddRule(engine.NewRule(
engine.MatchKind(engine.OpHTTPClient),
engine.WithFault(fault.HTTPStatus(503)),
).Named("degrade"))
client := &http.Client{Transport: chaoshttp.WrapTransport(http.DefaultTransport, eng)}
// The client sees a real 503 response (not a transport error) to test
// retry/handling code.
resp, err := client.Get(srv.URL + "/")
fmt.Println("err:", err)
fmt.Println("status:", resp.StatusCode)
_ = resp.Body.Close()
}
Output: err: <nil> status: 503
Types ¶
This section is empty.