Implements the top-level httpx.Client that composes the full chain: Logging → User Middlewares → Retry → Circuit Breaker → Balancer → Transport - Response wrapper with JSON/XML/Bytes decoding and body caching - NewJSONRequest helper with Content-Type and GetBody support - Functional options: WithBaseURL, WithTimeout, WithRetry, WithEndpoints, etc. - Integration tests covering retry, balancing, error mapping, and JSON round-trips
79 lines
1.8 KiB
Go
79 lines
1.8 KiB
Go
package httpx_test
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"testing"
|
|
|
|
"git.codelab.vc/pkg/httpx"
|
|
)
|
|
|
|
func TestNewJSONRequest(t *testing.T) {
|
|
t.Run("body is JSON encoded", func(t *testing.T) {
|
|
payload := map[string]string{"key": "value"}
|
|
req, err := httpx.NewJSONRequest(context.Background(), http.MethodPost, "http://example.com", payload)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
body, err := io.ReadAll(req.Body)
|
|
if err != nil {
|
|
t.Fatalf("reading body: %v", err)
|
|
}
|
|
|
|
var decoded map[string]string
|
|
if err := json.Unmarshal(body, &decoded); err != nil {
|
|
t.Fatalf("unmarshal: %v", err)
|
|
}
|
|
if decoded["key"] != "value" {
|
|
t.Errorf("decoded[key] = %q, want %q", decoded["key"], "value")
|
|
}
|
|
})
|
|
|
|
t.Run("content type is set", func(t *testing.T) {
|
|
req, err := httpx.NewJSONRequest(context.Background(), http.MethodPost, "http://example.com", "test")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
ct := req.Header.Get("Content-Type")
|
|
if ct != "application/json" {
|
|
t.Errorf("Content-Type = %q, want %q", ct, "application/json")
|
|
}
|
|
})
|
|
|
|
t.Run("GetBody works", func(t *testing.T) {
|
|
payload := map[string]int{"num": 123}
|
|
req, err := httpx.NewJSONRequest(context.Background(), http.MethodPost, "http://example.com", payload)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if req.GetBody == nil {
|
|
t.Fatal("GetBody is nil")
|
|
}
|
|
|
|
// Read body first time
|
|
b1, err := io.ReadAll(req.Body)
|
|
if err != nil {
|
|
t.Fatalf("reading body: %v", err)
|
|
}
|
|
|
|
// Get a fresh body
|
|
body2, err := req.GetBody()
|
|
if err != nil {
|
|
t.Fatalf("GetBody(): %v", err)
|
|
}
|
|
b2, err := io.ReadAll(body2)
|
|
if err != nil {
|
|
t.Fatalf("reading body2: %v", err)
|
|
}
|
|
|
|
if string(b1) != string(b2) {
|
|
t.Errorf("GetBody returned different data: %q vs %q", b1, b2)
|
|
}
|
|
})
|
|
}
|