github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/pkg/api/server/handler_api.go (about) 1 package server 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 "runtime" 8 9 "github.com/containers/podman/v2/pkg/api/handlers/utils" 10 "github.com/containers/podman/v2/pkg/auth" 11 "github.com/google/uuid" 12 "github.com/sirupsen/logrus" 13 ) 14 15 // APIHandler is a wrapper to enhance HandlerFunc's and remove redundant code 16 func (s *APIServer) APIHandler(h http.HandlerFunc) http.HandlerFunc { 17 return func(w http.ResponseWriter, r *http.Request) { 18 // http.Server hides panics, we want to see them and fix the cause. 19 defer func() { 20 err := recover() 21 if err != nil { 22 buf := make([]byte, 1<<20) 23 n := runtime.Stack(buf, true) 24 logrus.Warnf("Recovering from API handler panic: %v, %s", err, buf[:n]) 25 // Try to inform client things went south... won't work if handler already started writing response body 26 utils.InternalServerError(w, fmt.Errorf("%v", err)) 27 } 28 }() 29 30 // Wrapper to hide some boiler plate 31 fn := func(w http.ResponseWriter, r *http.Request) { 32 rid := uuid.New().String() 33 logrus.Infof("APIHandler(%s) -- %s %s BEGIN", rid, r.Method, r.URL.String()) 34 if logrus.IsLevelEnabled(logrus.DebugLevel) { 35 for k, v := range r.Header { 36 switch auth.HeaderAuthName(k) { 37 case auth.XRegistryConfigHeader, auth.XRegistryAuthHeader: 38 logrus.Debugf("APIHandler(%s) -- Header: %s=<hidden>", rid, k) 39 default: 40 logrus.Debugf("APIHandler(%s) -- Header: %s=%v", rid, k, v) 41 } 42 } 43 } 44 // Set in case handler wishes to correlate logging events 45 r.Header.Set("X-Reference-Id", rid) 46 47 if err := r.ParseForm(); err != nil { 48 logrus.Infof("Failed Request: unable to parse form: %q (%s)", err, rid) 49 } 50 51 // TODO: Use r.ConnContext when ported to go 1.13 52 c := context.WithValue(r.Context(), "decoder", s.Decoder) // nolint 53 c = context.WithValue(c, "runtime", s.Runtime) // nolint 54 c = context.WithValue(c, "shutdownFunc", s.Shutdown) // nolint 55 c = context.WithValue(c, "idletracker", s.idleTracker) // nolint 56 r = r.WithContext(c) 57 58 cv := utils.APIVersion[utils.CompatTree][utils.CurrentAPIVersion] 59 w.Header().Set("API-Version", fmt.Sprintf("%d.%d", cv.Major, cv.Minor)) 60 61 lv := utils.APIVersion[utils.LibpodTree][utils.CurrentAPIVersion].String() 62 w.Header().Set("Libpod-API-Version", lv) 63 w.Header().Set("Server", "Libpod/"+lv+" ("+runtime.GOOS+")") 64 65 h(w, r) 66 logrus.Debugf("APIHandler(%s) -- %s %s END", rid, r.Method, r.URL.String()) 67 } 68 fn(w, r) 69 } 70 } 71 72 // VersionedPath prepends the version parsing code 73 // any handler may override this default when registering URL(s) 74 func VersionedPath(p string) string { 75 return "/v{version:[0-9][0-9.]*}" + p 76 }