Repository: knative/serving
Pull request #11915 (2021-09-03 13:32:11)

[main] Upgrade to latest dependencies
Cron -knative-prow-robot

/cc knative/serving-writers
/assign knative/serving-writers

Produced by: knative-sandbox/knobots/actions/update-deps

Details:
```
bumping knative.dev/caching 77b5d6a...553240b:
  > 553240b upgrade to latest dependencies (# 522)
bumping knative.dev/networking ee93e22...5f2e230:
  > 5f2e230 upgrade to latest dependencies (# 495)
bumping knative.dev/pkg 7a61343...dec98b4:
  > dec98b4 fix a small lint warning (# 2270)
  > fbe9e7e Widen the error checker interface to allow response error checking (# 2253)
```

knative-prow-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/knative/serving/pull/11915#" title="Author self-approved">knative-automation</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **julz** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @julz` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=knative%2Fserving).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/knative/serving/blob/main/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["julz"]} -->
codecov[bot]: # [Codecov](https://codecov.io/gh/knative/serving/pull/11915?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) Report
> Merging [#11915](https://codecov.io/gh/knative/serving/pull/11915?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) (edb70d6) into [main](https://codecov.io/gh/knative/serving/commit/ae44ea6a2a9da1b64e1204f7d9279e0c0b0377a0?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) (ae44ea6) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/knative/serving/pull/11915/graphs/tree.svg?width=650&height=150&src=pr&token=MPpDfAj4Ui&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative)](https://codecov.io/gh/knative/serving/pull/11915?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative)

```diff
@@           Coverage Diff           @@
##             main   #11915   +/-   ##
=======================================
  Coverage   87.69%   87.69%           
=======================================
  Files         197      197           
  Lines        9467     9467           
=======================================
  Hits         8302     8302           
  Misses        901      901           
  Partials      264      264           
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/knative/serving/pull/11915?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/knative/serving/pull/11915?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative). Last update [ae44ea6...edb70d6](https://codecov.io/gh/knative/serving/pull/11915?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative).

knative-prow-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/knative/serving/pull/11915#" title="Author self-approved">knative-automation</a>*, *<a href="https://github.com/knative/serving/pull/11915#pullrequestreview-746130218" title="Approved">markusthoemmes</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=knative%2Fserving).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/knative/serving/blob/main/OWNERS)~~ [markusthoemmes]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->

Patch:
diff --git a/go.mod b/go.mod
index a8e7afb89..3826ef8b8 100644
--- a/go.mod
+++ b/go.mod
@@ -45,9 +45,9 @@ require (
 	k8s.io/code-generator v0.21.4
 	k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7
 	k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 // indirect
-	knative.dev/caching v0.0.0-20210831064556-77b5d6ab7525
+	knative.dev/caching v0.0.0-20210903022457-553240b1b365
 	knative.dev/hack v0.0.0-20210806075220-815cd312d65c
-	knative.dev/networking v0.0.0-20210902120205-ee93e22aa557
-	knative.dev/pkg v0.0.0-20210902202457-7a61343b36ca
+	knative.dev/networking v0.0.0-20210903055657-5f2e230c665f
+	knative.dev/pkg v0.0.0-20210903055557-dec98b426132
 	sigs.k8s.io/yaml v1.2.0
 )
diff --git a/go.sum b/go.sum
index 97a38091a..faf5dcb8a 100644
--- a/go.sum
+++ b/go.sum
@@ -1526,15 +1526,15 @@ k8s.io/legacy-cloud-providers v0.21.0/go.mod h1:bNxo7gDg+PGkBmT/MFZswLTWdSWK9kAl
 k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 h1:0T5IaWHO3sJTEmCP6mUlBvMukxPKUQWqiI/YuiBNMiQ=
 k8s.io/utils v0.0.0-20210111153108-fddb29f9d009/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-knative.dev/caching v0.0.0-20210831064556-77b5d6ab7525 h1:dy2VJqa2gCVGhU9rNXu59W3pmiAexCKoh03Un+K3L/g=
-knative.dev/caching v0.0.0-20210831064556-77b5d6ab7525/go.mod h1:m+qT5SoXDbEm0DqBw9LTheZIi/UlQ5YqSsvjgFSom1k=
+knative.dev/caching v0.0.0-20210903022457-553240b1b365 h1:p8jEwTrExGkeEL3ytXCOKG4CHAyJM/lWitVzqxt00ZI=
+knative.dev/caching v0.0.0-20210903022457-553240b1b365/go.mod h1:J2o0f0nayAT6ZaXy9yo4GyEcoPyJndMrh+4X5kQTQ5w=
 knative.dev/hack v0.0.0-20210806075220-815cd312d65c h1:nOXoDWAAItwr4o0dp3nHr6skgpVD4IvME/UX84YNl5k=
 knative.dev/hack v0.0.0-20210806075220-815cd312d65c/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI=
-knative.dev/networking v0.0.0-20210902120205-ee93e22aa557 h1:Wuss+xFFkH4xitrk6n2YV75Q7HzkVcF+HiDt+ptXfHg=
-knative.dev/networking v0.0.0-20210902120205-ee93e22aa557/go.mod h1:dJaJfTZQlZqqtvKA59ihb5Ndl7KtCn6PW7VVr+fls5Q=
-knative.dev/pkg v0.0.0-20210830224055-82f3a9f1c5bc/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8=
-knative.dev/pkg v0.0.0-20210902202457-7a61343b36ca h1:1tsBZgj1FheRcDQrIReteUiU/afjTZG8j5hTM3iBkJQ=
+knative.dev/networking v0.0.0-20210903055657-5f2e230c665f h1:83X6Ck5L53bXVu2MMsS4cFZInBcjoIzI0hEd6mWOIsU=
+knative.dev/networking v0.0.0-20210903055657-5f2e230c665f/go.mod h1:RU3UlJNSFKwyCWUV0tOGtlcca+WA83M3QxBl1wi/vhw=
 knative.dev/pkg v0.0.0-20210902202457-7a61343b36ca/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8=
+knative.dev/pkg v0.0.0-20210903055557-dec98b426132 h1:+iDyXF8cRdFclCu8eUTRBjxQ9ApE3KkleBScMl/3wHU=
+knative.dev/pkg v0.0.0-20210903055557-dec98b426132/go.mod h1:jMSqkNMsrzuy+XR4Yr/BMy7SDVbUOl3KKB6+5MR+ZU8=
 pgregory.net/rapid v0.3.3 h1:jCjBsY4ln4Atz78QoBWxUEvAHaFyNDQg9+WU62aCn1U=
 pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
diff --git a/pkg/reconciler/route/resources/ingress.go b/pkg/reconciler/route/resources/ingress.go
index 1b2f7e09e..e081b3f69 100644
--- a/pkg/reconciler/route/resources/ingress.go
+++ b/pkg/reconciler/route/resources/ingress.go
@@ -19,7 +19,9 @@ package resources
 import (
 	"context"
 	"encoding/json"
+	"fmt"
 	"sort"
+	"strings"
 
 	"github.com/davecgh/go-spew/spew"
 	"go.uber.org/zap"
@@ -193,16 +195,9 @@ func makeIngressSpec(
 		}
 	}
 
-	var httpOption netv1alpha1.HTTPOption
-
-	switch config.FromContext(ctx).Network.HTTPProtocol {
-	case network.HTTPEnabled:
-		httpOption = netv1alpha1.HTTPOptionEnabled
-	case network.HTTPRedirected:
-		httpOption = netv1alpha1.HTTPOptionRedirected
-	// This will be deprecated soon
-	case network.HTTPDisabled:
-		httpOption = ""
+	httpOption, err := getHTTPOption(ctx, r.Annotations)
+	if err != nil {
+		return netv1alpha1.IngressSpec{}, err
 	}
 
 	return netv1alpha1.IngressSpec{
@@ -212,6 +207,32 @@ func makeIngressSpec(
 	}, nil
 }
 
+func getHTTPOption(ctx context.Context, annotations map[string]string) (netv1alpha1.HTTPOption, error) {
+	if len(annotations) != 0 && annotations[networking.HTTPOptionAnnotationKey] != "" {
+		annotation := annotations[networking.HTTPOptionAnnotationKey]
+		switch strings.ToLower(annotation) {
+		case "enabled":
+			return netv1alpha1.HTTPOptionEnabled, nil
+		case "redirected":
+			return netv1alpha1.HTTPOptionRedirected, nil
+		default:
+			return "", fmt.Errorf("incorrect HTTPOption annotation:" + annotation)
+		}
+	}
+
+	switch config.FromContext(ctx).Network.HTTPProtocol {
+	case network.HTTPEnabled:
+		return netv1alpha1.HTTPOptionEnabled, nil
+	case network.HTTPRedirected:
+		return netv1alpha1.HTTPOptionRedirected, nil
+	// This will be deprecated soon
+	case network.HTTPDisabled:
+		return "", nil
+	default:
+		return "", nil
+	}
+}
+
 func getChallengeHosts(challenges []netv1alpha1.HTTP01Challenge) map[string]netv1alpha1.HTTP01Challenge {
 	c := make(map[string]netv1alpha1.HTTP01Challenge, len(challenges))
 
diff --git a/vendor/knative.dev/pkg/webhook/json/decode.go b/vendor/knative.dev/pkg/webhook/json/decode.go
index 9e206a10b..b62caec61 100644
--- a/vendor/knative.dev/pkg/webhook/json/decode.go
+++ b/vendor/knative.dev/pkg/webhook/json/decode.go
@@ -81,11 +81,7 @@ func Decode(bites []byte, target interface{}, disallowUnknownFields bool) error
 		bytes.NewReader(metaSuffix),
 	))
 
-	if err := dec.Decode(target); err != nil {
-		return err
-	}
-
-	return nil
+	return dec.Decode(target)
 }
 
 func findMetadataOffsets(bites []byte) (start, end int64, err error) {
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 73877e941..2f445c192 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1017,7 +1017,7 @@ k8s.io/utils/buffer
 k8s.io/utils/integer
 k8s.io/utils/pointer
 k8s.io/utils/trace
-# knative.dev/caching v0.0.0-20210831064556-77b5d6ab7525
+# knative.dev/caching v0.0.0-20210903022457-553240b1b365
 ## explicit
 knative.dev/caching/config
 knative.dev/caching/pkg/apis/caching
@@ -1042,7 +1042,7 @@ knative.dev/caching/pkg/client/listers/caching/v1alpha1
 ## explicit
 knative.dev/hack
 knative.dev/hack/shell
-# knative.dev/networking v0.0.0-20210902120205-ee93e22aa557
+# knative.dev/networking v0.0.0-20210903055657-5f2e230c665f
 ## explicit
 knative.dev/networking/config
 knative.dev/networking/pkg
@@ -1072,7 +1072,7 @@ knative.dev/networking/pkg/client/injection/reconciler/networking/v1alpha1/serve
 knative.dev/networking/pkg/client/listers/networking/v1alpha1
 knative.dev/networking/pkg/ingress
 knative.dev/networking/pkg/prober
-# knative.dev/pkg v0.0.0-20210902202457-7a61343b36ca
+# knative.dev/pkg v0.0.0-20210903055557-dec98b426132
 ## explicit
 knative.dev/pkg/apiextensions/storageversion
 knative.dev/pkg/apiextensions/storageversion/cmd/migrate


Test patch:
diff --git a/pkg/reconciler/route/resources/ingress_test.go b/pkg/reconciler/route/resources/ingress_test.go
index 2a302fca1..f955e0b08 100644
--- a/pkg/reconciler/route/resources/ingress_test.go
+++ b/pkg/reconciler/route/resources/ingress_test.go
@@ -1045,6 +1045,50 @@ func TestMakeIngressWithTLS(t *testing.T) {
 	}
 }
 
+func TestMakeIngressWithHTTPOption(t *testing.T) {
+	targets := map[string]traffic.RevisionTargets{}
+	ingressClass := "foo-ingress"
+	tls := []netv1alpha1.IngressTLS{{
+		Hosts:      []string{"*.default.domain.com"},
+		SecretName: "secret",
+	}}
+	tests := []struct {
+		name                 string
+		httpOptionAnnotation string
+		wantOption           netv1alpha1.HTTPOption
+		wantError            bool
+	}{{
+		name:                 "Route annotation HTTPOption enabled",
+		httpOptionAnnotation: "Enabled",
+		wantOption:           netv1alpha1.HTTPOptionEnabled,
+	}, {
+		name:       "No HTTPOption annotation",
+		wantOption: netv1alpha1.HTTPOptionRedirected,
+	}, {
+		name:                 "Incorrect HTTPOption annotation",
+		httpOptionAnnotation: "INCORRECT",
+		wantError:            true,
+	}}
+	for _, tc := range tests {
+		t.Run(tc.name, func(t *testing.T) {
+			annotations := map[string]string{
+				networking.HTTPOptionAnnotationKey: tc.httpOptionAnnotation,
+			}
+			r := Route(ns, "test-route", WithURL, WithRouteAnnotation(annotations))
+			got, err := MakeIngress(testContextWithHTTPOption(), r, &traffic.Config{Targets: targets}, tls, ingressClass)
+			if (err != nil) != tc.wantError {
+				t.Fatalf("MakeIngress() error = %v, WantErr %v", err, tc.wantError)
+			}
+			if tc.wantError {
+				return
+			}
+			if diff := cmp.Diff(tc.wantOption, got.Spec.HTTPOption); diff != "" {
+				t.Error("Unexpected Ingress (-want, +got):", diff)
+			}
+		})
+	}
+}
+
 func TestMakeIngressTLS(t *testing.T) {
 	cert := &netv1alpha1.Certificate{
 		ObjectMeta: metav1.ObjectMeta{
@@ -1250,3 +1294,9 @@ func testContext() context.Context {
 		Defaults: configDefaults,
 	}), cfg)
 }
+
+func testContextWithHTTPOption() context.Context {
+	cfg := testConfig()
+	cfg.Network.HTTPProtocol = network.HTTPRedirected
+	return config.ToContext(context.Background(), cfg)
+}
diff --git a/test/e2e-tests.sh b/test/e2e-tests.sh
index cdf763ddb..289f885e2 100755
--- a/test/e2e-tests.sh
+++ b/test/e2e-tests.sh
@@ -71,9 +71,9 @@ fi
 
 toggle_feature autocreateClusterDomainClaims true config-network || fail_test
 go_test_e2e -timeout=30m \
- ./test/conformance/api/... \
- ./test/conformance/runtime/... \
- ./test/e2e \
+  ./test/conformance/api/... \
+  ./test/conformance/runtime/... \
+  ./test/e2e \
   ${parallelism} \
   ${TEST_OPTIONS} || failed=1
 toggle_feature autocreateClusterDomainClaims false config-network || fail_test
diff --git a/third_party/kourier-latest/kourier.yaml b/third_party/kourier-latest/kourier.yaml
index af34ae97f..37dc0dede 100644
--- a/third_party/kourier-latest/kourier.yaml
+++ b/third_party/kourier-latest/kourier.yaml
@@ -18,7 +18,7 @@ metadata:
   name: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210901-8b94798b"
+    serving.knative.dev/release: "v20210903-289da393"
 
 ---
 # Copyright 2020 The Knative Authors
@@ -42,7 +42,7 @@ metadata:
   namespace: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210901-8b94798b"
+    serving.knative.dev/release: "v20210903-289da393"
 data:
   envoy-bootstrap.yaml: |
     dynamic_resources:
@@ -145,7 +145,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210901-8b94798b"
+    serving.knative.dev/release: "v20210903-289da393"
 data:
   _example: |
     ################################
@@ -190,7 +190,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210901-8b94798b"
+    serving.knative.dev/release: "v20210903-289da393"
 ---
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRole
@@ -199,7 +199,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210901-8b94798b"
+    serving.knative.dev/release: "v20210903-289da393"
 rules:
   - apiGroups: [""]
     resources: ["events"]
@@ -226,7 +226,7 @@ metadata:
   name: net-kourier
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210901-8b94798b"
+    serving.knative.dev/release: "v20210903-289da393"
 roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: ClusterRole
@@ -258,7 +258,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210901-8b94798b"
+    serving.knative.dev/release: "v20210903-289da393"
 spec:
   replicas: 1
   selector:
@@ -270,7 +270,7 @@ spec:
         app: net-kourier-controller
     spec:
       containers:
-        - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:32e25873aabb392f6194141453f771b82e0c4a43851bf70180be3ca92abd14fc
+        - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:8385260dba1b319a250422bf96b903349a3582e3c95232f4fc0f3f04379e63b9
           name: controller
           env:
             - name: CERTS_SECRET_NAMESPACE
@@ -309,7 +309,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210901-8b94798b"
+    serving.knative.dev/release: "v20210903-289da393"
 spec:
   ports:
     - name: grpc-xds
@@ -342,7 +342,7 @@ metadata:
   namespace: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210901-8b94798b"
+    serving.knative.dev/release: "v20210903-289da393"
 spec:
   strategy:
     type: RollingUpdate
@@ -417,7 +417,7 @@ metadata:
   namespace: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210901-8b94798b"
+    serving.knative.dev/release: "v20210903-289da393"
 spec:
   ports:
     - name: http2
@@ -439,7 +439,7 @@ metadata:
   namespace: kourier-system
   labels:
     networking.knative.dev/ingress-provider: kourier
-    serving.knative.dev/release: "v20210901-8b94798b"
+    serving.knative.dev/release: "v20210903-289da393"
 spec:
   ports:
     - name: http2
diff --git a/vendor/knative.dev/pkg/test/spoof/spoof.go b/vendor/knative.dev/pkg/test/spoof/spoof.go
index aa3a90f1a..442fd3940 100644
--- a/vendor/knative.dev/pkg/test/spoof/spoof.go
+++ b/vendor/knative.dev/pkg/test/spoof/spoof.go
@@ -68,6 +68,14 @@ type ResponseChecker func(resp *Response) (done bool, err error)
 // If an error should be retried, it should return true and the wrapped error to explain why to retry.
 type ErrorRetryChecker func(e error) (retry bool, err error)
 
+// ResponseRetryChecker is used to determine if a response should be retried or not.
+// If a response should be retried, it should return true and an error to explain why to retry.
+//
+// This is distinct from ResponseChecker in that it shall be used to retry responses,
+// where the HTTP request was technically successful (it returned something) but indicates
+// an error (e.g. the overload page of a loadbalancer).
+type ResponseRetryChecker func(resp *Response) (retry bool, err error)
+
 // SpoofingClient is a minimal HTTP client wrapper that spoofs the domain of requests
 // for non-resolvable domains.
 type SpoofingClient struct {
@@ -147,16 +155,16 @@ func ResolveEndpoint(ctx context.Context, kubeClientset kubernetes.Interface, do
 // Do dispatches to the underlying http.Client.Do, spoofing domains as needed
 // and transforming the http.Response into a spoof.Response.
 // Each response is augmented with "ZipkinTraceID" header that identifies the zipkin trace corresponding to the request.
-func (sc *SpoofingClient) Do(req *http.Request, errorRetryCheckers ...ErrorRetryChecker) (*Response, error) {
+func (sc *SpoofingClient) Do(req *http.Request, errorRetryCheckers ...interface{}) (*Response, error) {
 	return sc.Poll(req, func(*Response) (bool, error) { return true, nil }, errorRetryCheckers...)
 }
 
 // Poll executes an http request until it satisfies the inState condition or, if there's an error,
 // none of the error retry checkers permit a retry.
 // If no retry checkers are specified `DefaultErrorRetryChecker` will be used.
-func (sc *SpoofingClient) Poll(req *http.Request, inState ResponseChecker, errorRetryCheckers ...ErrorRetryChecker) (*Response, error) {
-	if len(errorRetryCheckers) == 0 {
-		errorRetryCheckers = []ErrorRetryChecker{DefaultErrorRetryChecker}
+func (sc *SpoofingClient) Poll(req *http.Request, inState ResponseChecker, checkers ...interface{}) (*Response, error) {
+	if len(checkers) == 0 {
+		checkers = []interface{}{DefaultErrorRetryChecker}
 	}
 
 	var resp *Response
@@ -166,11 +174,13 @@ func (sc *SpoofingClient) Poll(req *http.Request, inState ResponseChecker, error
 		defer span.End()
 		rawResp, err := sc.Client.Do(req.WithContext(traceContext))
 		if err != nil {
-			for _, checker := range errorRetryCheckers {
-				retry, newErr := checker(err)
-				if retry {
-					sc.Logf("Retrying %s: %v", req.URL.String(), newErr)
-					return false, nil
+			for _, checker := range checkers {
+				if ec, ok := checker.(ErrorRetryChecker); ok {
+					retry, newErr := ec(err)
+					if retry {
+						sc.Logf("Retrying %s: %v", req.URL.String(), newErr)
+						return false, nil
+					}
 				}
 			}
 			sc.Logf("NOT Retrying %s: %v", req.URL.String(), err)
@@ -190,6 +200,20 @@ func (sc *SpoofingClient) Poll(req *http.Request, inState ResponseChecker, error
 			Header:     rawResp.Header,
 			Body:       body,
 		}
+
+		// This is distinct from inState in that it allows us to uniformly check for
+		// error responses to retry HTTP requests that have technically been successful,
+		// but haven't reached their destination (e.g. got a loadbalancer overload page).
+		for _, checker := range checkers {
+			if rc, ok := checker.(ResponseRetryChecker); ok {
+				retry, newErr := rc(resp)
+				if retry {
+					sc.Logf("Retrying %s: %v", req.URL.String(), newErr)
+					return false, nil
+				}
+			}
+		}
+
 		return inState(resp)
 	})
 
@@ -295,8 +319,8 @@ func (sc *SpoofingClient) endpointState(
 	return f(req, inState)
 }
 
-func (sc *SpoofingClient) Check(req *http.Request, inState ResponseChecker, errorRetryCheckers ...ErrorRetryChecker) (*Response, error) {
-	resp, err := sc.Do(req, errorRetryCheckers...)
+func (sc *SpoofingClient) Check(req *http.Request, inState ResponseChecker, checkers ...interface{}) (*Response, error) {
+	resp, err := sc.Do(req, checkers...)
 	if err != nil {
 		return nil, err
 	}