func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { defer httplog.MakeLogged(req, &w).Log() u, err := url.ParseRequestURI(req.RequestURI) if err != nil { s.error(w, err) return } // TODO: use an http.ServeMux instead of a switch. switch { case u.Path == "/container" || u.Path == "/containers": defer req.Body.Close() data, err := ioutil.ReadAll(req.Body) if err != nil { s.error(w, err) return } if u.Path == "/container" { // This is to provide backward compatibility. It only supports a single manifest var manifest api.ContainerManifest err = yaml.Unmarshal(data, &manifest) if err != nil { s.error(w, err) return } s.UpdateChannel <- manifestUpdate{httpServerSource, []api.ContainerManifest{manifest}} } else if u.Path == "/containers" { var manifests []api.ContainerManifest err = yaml.Unmarshal(data, &manifests) if err != nil { s.error(w, err) return } s.UpdateChannel <- manifestUpdate{httpServerSource, manifests} } case u.Path == "/podInfo": podID := u.Query().Get("podID") if len(podID) == 0 { http.Error(w, "Missing 'podID=' query entry.", http.StatusBadRequest) return } info, err := s.Kubelet.GetPodInfo(podID) if err != nil { s.error(w, err) return } data, err := json.Marshal(info) if err != nil { s.error(w, err) return } w.WriteHeader(http.StatusOK) w.Header().Add("Content-type", "application/json") w.Write(data) case strings.HasPrefix(u.Path, "/stats"): s.serveStats(w, req) default: s.DelegateHandler.ServeHTTP(w, req) } }
// HTTP Handler interface func (server *APIServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { defer func() { if x := recover(); x != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprint(w, "apiserver panic. Look in log for details.") glog.Infof("APIServer panic'd on %v %v: %#v\n%s\n", req.Method, req.RequestURI, x, debug.Stack()) } }() defer httplog.MakeLogged(req, &w).StacktraceWhen( httplog.StatusIsNot( http.StatusOK, http.StatusAccepted, http.StatusConflict, ), ).Log() // Dispatch via our mux. server.mux.ServeHTTP(w, req) }
// RecoverPanics wraps an http Handler to recover and log panics func RecoverPanics(handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { defer func() { if x := recover(); x != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprint(w, "apis panic. Look in log for details.") glog.Infof("APIServer panic'd on %v %v: %#v\n%s\n", req.Method, req.RequestURI, x, debug.Stack()) } }() defer httplog.MakeLogged(req, &w).StacktraceWhen( httplog.StatusIsNot( http.StatusOK, http.StatusAccepted, http.StatusConflict, http.StatusNotFound, ), ).Log() // Dispatch to the internal handler handler.ServeHTTP(w, req) }) }
func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { defer httplog.MakeLogged(req, &w).StacktraceWhen( httplog.StatusIsNot( http.StatusOK, http.StatusNotFound, ), ).Log() u, err := url.ParseRequestURI(req.RequestURI) if err != nil { s.error(w, err) return } // TODO: use an http.ServeMux instead of a switch. switch { case u.Path == "/container" || u.Path == "/containers": defer req.Body.Close() data, err := ioutil.ReadAll(req.Body) if err != nil { s.error(w, err) return } if u.Path == "/container" { // This is to provide backward compatibility. It only supports a single manifest var pod Pod err = yaml.Unmarshal(data, &pod.Manifest) if err != nil { s.error(w, err) return } //TODO: sha1 of manifest? pod.Name = "1" s.updates <- PodUpdate{[]Pod{pod}, SET} } else if u.Path == "/containers" { var manifests []api.ContainerManifest err = yaml.Unmarshal(data, &manifests) if err != nil { s.error(w, err) return } pods := make([]Pod, len(manifests)) for i := range manifests { pods[i].Name = fmt.Sprintf("%d", i+1) pods[i].Manifest = manifests[i] } s.updates <- PodUpdate{pods, SET} } case u.Path == "/podInfo": podID := u.Query().Get("podID") if len(podID) == 0 { w.WriteHeader(http.StatusBadRequest) http.Error(w, "Missing 'podID=' query entry.", http.StatusBadRequest) return } // TODO: backwards compatibility with existing API, needs API change podFullName := GetPodFullName(&Pod{Name: podID, Namespace: "etcd"}) info, err := s.host.GetPodInfo(podFullName) if err == ErrNoContainersInPod { http.Error(w, "Pod does not exist", http.StatusNotFound) return } if err != nil { s.error(w, err) return } data, err := json.Marshal(info) if err != nil { s.error(w, err) return } w.WriteHeader(http.StatusOK) w.Header().Add("Content-type", "application/json") w.Write(data) case strings.HasPrefix(u.Path, "/stats"): s.serveStats(w, req) case strings.HasPrefix(u.Path, "/spec"): info, err := s.host.GetMachineInfo() if err != nil { s.error(w, err) return } data, err := json.Marshal(info) if err != nil { s.error(w, err) return } w.Header().Add("Content-type", "application/json") w.Write(data) case strings.HasPrefix(u.Path, "/logs/"): s.host.ServeLogs(w, req) default: if s.handler != nil { s.handler.ServeHTTP(w, req) } } }