mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-09-21 07:32:00 +00:00
fix(quickproxy): ensure request body is preserved on fallback
Tests / Unit Tests (push) Failing after 26s
Tests / Integration Tests (push) Failing after 41s
Build , Vet Test, and Lint / Build (push) Successful in 4m26s
Build , Vet Test, and Lint / Lint Code (push) Successful in 4m58s
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in 5m1s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in 5m3s
Tests / Unit Tests (push) Failing after 26s
Tests / Integration Tests (push) Failing after 41s
Build , Vet Test, and Lint / Build (push) Successful in 4m26s
Build , Vet Test, and Lint / Lint Code (push) Successful in 4m58s
Build , Vet Test, and Lint / Run Vet Tests (1.24.x) (push) Successful in 5m1s
Build , Vet Test, and Lint / Run Vet Tests (1.23.x) (push) Successful in 5m3s
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -130,6 +131,75 @@ func TestHandler_UnreachableUpstreamFallsBack(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandler_UnreachableUpstreamFallsBackWithBody(t *testing.T) {
|
||||
// A closed listener address: nothing is listening, so dialing fails and
|
||||
// ReverseProxy invokes ErrorHandler. The fallback handler must still see
|
||||
// the original request body, even though ReverseProxy consumed and
|
||||
// closed it while attempting (and failing) the upstream request.
|
||||
unreachable := "http://127.0.0.1:1"
|
||||
|
||||
svc, err := NewService([]Rule{{URLPrefix: "/", Target: unreachable}}, WithTimeout(500*time.Millisecond))
|
||||
if err != nil {
|
||||
t.Fatalf("NewService: %v", err)
|
||||
}
|
||||
|
||||
echoBody := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("fallback reading body: %v", err)
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write(body)
|
||||
})
|
||||
|
||||
handler := svc.Handler(echoBody)
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, "/submit", strings.NewReader("payload=1"))
|
||||
rr := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200", rr.Code)
|
||||
}
|
||||
if got := rr.Body.String(); got != "payload=1" {
|
||||
t.Fatalf("body = %q, want payload=1", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandler_404FallsBackWithBody(t *testing.T) {
|
||||
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}))
|
||||
defer upstream.Close()
|
||||
|
||||
svc, err := NewService([]Rule{{URLPrefix: "/", Target: upstream.URL}})
|
||||
if err != nil {
|
||||
t.Fatalf("NewService: %v", err)
|
||||
}
|
||||
|
||||
echoBody := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
body, err := io.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("fallback reading body: %v", err)
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write(body)
|
||||
})
|
||||
|
||||
handler := svc.Handler(echoBody)
|
||||
|
||||
req := httptest.NewRequest(http.MethodPut, "/missing", strings.NewReader("payload=2"))
|
||||
rr := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200", rr.Code)
|
||||
}
|
||||
if got := rr.Body.String(); got != "payload=2" {
|
||||
t.Fatalf("body = %q, want payload=2", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandler_NonNotFoundErrorsPassThrough(t *testing.T) {
|
||||
codes := []int{http.StatusOK, http.StatusForbidden, http.StatusBadRequest, http.StatusInternalServerError}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user