diff --git a/pkg/api/errors/errors.go b/pkg/api/errors/errors.go index 88df9357c6c..ea1e2fac2a1 100644 --- a/pkg/api/errors/errors.go +++ b/pkg/api/errors/errors.go @@ -25,6 +25,12 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/util/errors" ) +// HTTP Status codes not in the golang http package. +const ( + StatusUnprocessableEntity = 422 + StatusTooManyRequests = 429 +) + // StatusError is an error intended for consumption by a REST API server; it can also be // reconstructed by clients from a REST response. Public to allow easy type switches. type StatusError struct { @@ -134,7 +140,7 @@ func NewInvalid(kind, name string, errs ValidationErrorList) error { } return &StatusError{api.Status{ Status: api.StatusFailure, - Code: 422, // RFC 4918: StatusUnprocessableEntity + Code: StatusUnprocessableEntity, // RFC 4918: StatusUnprocessableEntity Reason: api.StatusReasonInvalid, Details: &api.StatusDetails{ Kind: kind, diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index a5d4f5895bf..8c9cb05b649 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -50,10 +50,6 @@ type defaultAPIServer struct { group *APIGroupVersion } -const ( - StatusUnprocessableEntity = 422 -) - // Handle returns a Handler function that exposes the provided storage interfaces // as RESTful resources at prefix, serialized by codec, and also includes the support // http resources. diff --git a/pkg/apiserver/handlers.go b/pkg/apiserver/handlers.go index 34163acc923..23da82a6d3c 100644 --- a/pkg/apiserver/handlers.go +++ b/pkg/apiserver/handlers.go @@ -24,6 +24,7 @@ import ( "strings" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/auth/authorizer" authhandlers "github.com/GoogleCloudPlatform/kubernetes/pkg/auth/handlers" "github.com/GoogleCloudPlatform/kubernetes/pkg/httplog" @@ -71,9 +72,10 @@ func RateLimit(rl util.RateLimiter, handler http.Handler) http.Handler { handler.ServeHTTP(w, req) return } - w.WriteHeader(http.StatusServiceUnavailable) + // Return a 429 status indicating "Too Many Requests" + w.WriteHeader(errors.StatusTooManyRequests) w.Header().Set("Retry-After", "1") - fmt.Fprintf(w, "Rate limit exceeded.") + fmt.Fprintf(w, "Rate limit is 1 QPS or a burst of 20") }) } @@ -96,7 +98,7 @@ func RecoverPanics(handler http.Handler) http.Handler { http.StatusTemporaryRedirect, http.StatusConflict, http.StatusNotFound, - StatusUnprocessableEntity, + errors.StatusUnprocessableEntity, ), ).Log() diff --git a/pkg/client/request.go b/pkg/client/request.go index 6c6c60add69..78b9270d256 100644 --- a/pkg/client/request.go +++ b/pkg/client/request.go @@ -483,7 +483,8 @@ func (r *Request) Do() Result { continue } - if resp.StatusCode == http.StatusServiceUnavailable { + // Check to see if we got a 429 Too Many Requests response code. + if resp.StatusCode == errors.StatusTooManyRequests { if retries < 10 { retries++ if waitFor := resp.Header.Get("Retry-After"); waitFor != "" {