diff --git a/pkg/apiserver/handlers.go b/pkg/apiserver/handlers.go index ea4eff9ff2d..b5e65375948 100644 --- a/pkg/apiserver/handlers.go +++ b/pkg/apiserver/handlers.go @@ -19,15 +19,11 @@ package apiserver import ( "fmt" "net/http" - "runtime/debug" "strings" "github.com/golang/glog" "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/auth/authorizer" - "k8s.io/kubernetes/pkg/httplog" - "k8s.io/kubernetes/pkg/util/runtime" "k8s.io/kubernetes/pkg/util/sets" ) @@ -70,41 +66,6 @@ func ReadOnly(handler http.Handler) http.Handler { }) } -// RecoverPanics wraps an http Handler to recover and log panics. -func RecoverPanics(handler http.Handler, resolver *RequestInfoResolver) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - defer runtime.HandleCrash(func(err interface{}) { - http.Error(w, "This request caused apisever to panic. Look in log for details.", http.StatusInternalServerError) - glog.Errorf("APIServer panic'd on %v %v: %v\n%s\n", req.Method, req.RequestURI, err, debug.Stack()) - }) - - logger := httplog.NewLogged(req, &w) - requestInfo, err := resolver.GetRequestInfo(req) - if err != nil || requestInfo.Verb != "proxy" { - logger.StacktraceWhen( - httplog.StatusIsNot( - http.StatusOK, - http.StatusCreated, - http.StatusAccepted, - http.StatusBadRequest, - http.StatusMovedPermanently, - http.StatusTemporaryRedirect, - http.StatusConflict, - http.StatusNotFound, - http.StatusUnauthorized, - http.StatusForbidden, - http.StatusNotModified, - errors.StatusUnprocessableEntity, - http.StatusSwitchingProtocols, - ), - ) - } - defer logger.Log() - // Dispatch to the internal handler - handler.ServeHTTP(w, req) - }) -} - // RequestAttributeGetter is a function that extracts authorizer.Attributes from an http.Request type RequestAttributeGetter interface { GetAttribs(req *http.Request) (attribs authorizer.Attributes) diff --git a/pkg/genericapiserver/config.go b/pkg/genericapiserver/config.go index 3c4113f20b0..8d367cac584 100644 --- a/pkg/genericapiserver/config.go +++ b/pkg/genericapiserver/config.go @@ -364,7 +364,7 @@ func (s *GenericAPIServer) buildHandlerChains(c *Config, handler http.Handler) ( // insecure filters insecure = handler insecure = api.WithRequestContext(insecure, c.RequestContextMapper) - insecure = apiserver.RecoverPanics(insecure, s.NewRequestInfoResolver()) + insecure = genericfilters.WithPanicRecovery(insecure, s.NewRequestInfoResolver()) insecure = genericfilters.WithTimeoutForNonLongRunningRequests(insecure, longRunningFunc) // secure filters @@ -375,7 +375,7 @@ func (s *GenericAPIServer) buildHandlerChains(c *Config, handler http.Handler) ( secure = audit.WithAudit(secure, attributeGetter, s.auditWriter) // before impersonation to read original user secure = authhandlers.WithAuthentication(secure, c.RequestContextMapper, c.Authenticator, authhandlers.Unauthorized(c.SupportsBasicAuth)) secure = api.WithRequestContext(secure, c.RequestContextMapper) - secure = apiserver.RecoverPanics(secure, s.NewRequestInfoResolver()) + secure = genericfilters.WithPanicRecovery(secure, s.NewRequestInfoResolver()) secure = genericfilters.WithTimeoutForNonLongRunningRequests(secure, longRunningFunc) secure = genericfilters.WithMaxInFlightLimit(secure, c.MaxRequestsInFlight, longRunningFunc) diff --git a/pkg/genericapiserver/filters/panics.go b/pkg/genericapiserver/filters/panics.go new file mode 100644 index 00000000000..91470b6bf7f --- /dev/null +++ b/pkg/genericapiserver/filters/panics.go @@ -0,0 +1,64 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package filters + +import ( + "net/http" + "runtime/debug" + + "github.com/golang/glog" + + "k8s.io/kubernetes/pkg/api/errors" + "k8s.io/kubernetes/pkg/apiserver" + "k8s.io/kubernetes/pkg/httplog" + "k8s.io/kubernetes/pkg/util/runtime" +) + +// WithPanicRecovery wraps an http Handler to recover and log panics. +func WithPanicRecovery(handler http.Handler, resolver *apiserver.RequestInfoResolver) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + defer runtime.HandleCrash(func(err interface{}) { + http.Error(w, "This request caused apisever to panic. Look in log for details.", http.StatusInternalServerError) + glog.Errorf("APIServer panic'd on %v %v: %v\n%s\n", req.Method, req.RequestURI, err, debug.Stack()) + }) + + logger := httplog.NewLogged(req, &w) + requestInfo, err := resolver.GetRequestInfo(req) + if err != nil || requestInfo.Verb != "proxy" { + logger.StacktraceWhen( + httplog.StatusIsNot( + http.StatusOK, + http.StatusCreated, + http.StatusAccepted, + http.StatusBadRequest, + http.StatusMovedPermanently, + http.StatusTemporaryRedirect, + http.StatusConflict, + http.StatusNotFound, + http.StatusUnauthorized, + http.StatusForbidden, + http.StatusNotModified, + errors.StatusUnprocessableEntity, + http.StatusSwitchingProtocols, + ), + ) + } + defer logger.Log() + // Dispatch to the internal handler + handler.ServeHTTP(w, req) + }) +}