diff --git a/pkg/queue/health/probe.go b/pkg/queue/health/probe.go index 2aa0d6e27e4d..23c893b4388b 100644 --- a/pkg/queue/health/probe.go +++ b/pkg/queue/health/probe.go @@ -162,18 +162,21 @@ func http2UpgradeProbe(config HTTPProbeConfigOptions) (int, error) { func HTTPProbe(config HTTPProbeConfigOptions) error { if config.MaxProtoMajor == 0 { // If we don't know if the connection supports HTTP2, we will try it. - // Once we get a non-error response, we won't try again. // If maxProto is 0, container is not ready, so we don't know whether http2 is supported. // If maxProto is 1, we know we're ready, but we also can't upgrade, so just return. // If maxProto is 2, we know we can upgrade to http2 + // If we get an error response, we will assume that the connection is HTTP1, as we can not guarantee if the service can handle the OPTIONS request maxProto, err := http2UpgradeProbe(config) - if err != nil { - return fmt.Errorf("failed to run HTTP2 upgrade probe with error: %w", err) - } config.MaxProtoMajor = maxProto if config.MaxProtoMajor == 1 { return nil } + + if err != nil { + // we default to HTTP1 because the options request did not work + // however, we do not know if the container is ready yet, so we still need to probe + config.MaxProtoMajor = 1 + } } httpClient := &http.Client{ Transport: autoDowngradingTransport(config), diff --git a/pkg/queue/health/probe_test.go b/pkg/queue/health/probe_test.go index 3afbbc73eb04..bec2e6eac11a 100644 --- a/pkg/queue/health/probe_test.go +++ b/pkg/queue/health/probe_test.go @@ -201,6 +201,48 @@ func TestHTTPProbeAutoHTTP2(t *testing.T) { } } +func TestHTTPProbeAutoHTTP2FailedUpgrade(t *testing.T) { + h2cHeaders := map[string]string{ + "Connection": "Upgrade, HTTP2-Settings", + "Upgrade": "h2c", + } + expectedPath := "/health" + var callCount atomic.Int32 + + server := newH2cTestServer(t, func(w http.ResponseWriter, r *http.Request) { + count := callCount.Inc() + if r.Method == http.MethodOptions { + // make sure that the correct headers are present on the options request + for key, value := range h2cHeaders { + if r.Header.Get(key) != value { + t.Errorf("Key %v = %v was supposed to be present in the request", key, value) + } + } + w.WriteHeader(http.StatusInternalServerError) + } else { + w.WriteHeader(http.StatusOK) + } + if count > 2 { + t.Error("Expected probe to make two requests only") + } + }) + + action := newHTTPGetAction(t, server.URL) + action.Path = expectedPath + + config := HTTPProbeConfigOptions{ + Timeout: time.Second, + HTTPGetAction: action, + MaxProtoMajor: 0, + } + if err := HTTPProbe(config); err != nil { + t.Error("Expected probe to succeed but it failed with", err) + } + if count := callCount.Load(); count != 2 { + t.Errorf("Unexpected call count %d", count) + } +} + func TestHTTPSchemeProbeSuccess(t *testing.T) { server := newTestServer(t, func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK)