MCPcopy
hub / github.com/caddyserver/caddy / TestResponseRetryHeader

Function TestResponseRetryHeader

modules/caddyhttp/reverseproxy/retries_test.go:335–382  ·  view source on GitHub ↗

TestResponseRetryHeader verifies that response header matching triggers retries via a CEL expression checking {rp.header.*}

(t *testing.T)

Source from the content-addressed store, hash-verified

333// TestResponseRetryHeader verifies that response header matching triggers
334// retries via a CEL expression checking {rp.header.*}
335func TestResponseRetryHeader(t *testing.T) {
336 // Bad upstream: returns 200 but with X-Upstream-Retry header
337 badServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
338 w.Header().Set("X-Upstream-Retry", "true")
339 w.WriteHeader(http.StatusOK)
340 w.Write([]byte("bad"))
341 }))
342 t.Cleanup(badServer.Close)
343
344 // Good upstream: returns 200 without retry header
345 goodServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
346 w.WriteHeader(http.StatusOK)
347 w.Write([]byte("good"))
348 }))
349 t.Cleanup(goodServer.Close)
350
351 retryMatch := caddyhttp.MatcherSets{
352 caddyhttp.MatcherSet{
353 newExpressionMatcher(t, `{http.reverse_proxy.header.X-Upstream-Retry} == "true"`),
354 },
355 }
356
357 // RoundRobin picks index 1 first, then 0
358 upstreams := []*Upstream{
359 {Host: new(Host), Dial: goodServer.Listener.Addr().String()},
360 {Host: new(Host), Dial: badServer.Listener.Addr().String()},
361 }
362
363 h := minimalHandlerWithRetryMatch(1, retryMatch, upstreams...)
364
365 req := httptest.NewRequest(http.MethodGet, "http://example.com/", nil)
366 req = prepareTestRequest(req)
367 rec := httptest.NewRecorder()
368
369 err := h.ServeHTTP(rec, req, caddyhttp.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
370 return nil
371 }))
372 if err != nil {
373 t.Fatalf("unexpected error: %v", err)
374 }
375
376 if rec.Code != http.StatusOK {
377 t.Errorf("status: got %d, want %d", rec.Code, http.StatusOK)
378 }
379 if rec.Body.String() != "good" {
380 t.Errorf("body: got %q, want %q (retried to wrong upstream)", rec.Body.String(), "good")
381 }
382}
383
384// TestResponseRetryNoMatchNoRetry verifies that when no retry_match entries
385// match the response, the original response is returned without retrying

Callers

nothing calls this directly

Calls 12

HandlerFuncFuncType · 0.92
newExpressionMatcherFunction · 0.85
prepareTestRequestFunction · 0.85
AddrMethod · 0.80
CleanupMethod · 0.65
ServeHTTPMethod · 0.65
SetMethod · 0.45
HeaderMethod · 0.45
WriteHeaderMethod · 0.45
WriteMethod · 0.45
StringMethod · 0.45

Tested by

no test coverage detected