github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/api/handlers/utils/handler.go (about) 1 package utils 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "net/http" 8 "net/url" 9 "os" 10 "strings" 11 12 "github.com/gorilla/mux" 13 "github.com/pkg/errors" 14 "github.com/sirupsen/logrus" 15 ) 16 17 // IsLibpodRequest returns true if the request related to a libpod endpoint 18 // (e.g., /v2/libpod/...). 19 func IsLibpodRequest(r *http.Request) bool { 20 split := strings.Split(r.URL.String(), "/") 21 return len(split) >= 3 && split[2] == "libpod" 22 } 23 24 // WriteResponse encodes the given value as JSON or string and renders it for http client 25 func WriteResponse(w http.ResponseWriter, code int, value interface{}) { 26 // RFC2616 explicitly states that the following status codes "MUST NOT 27 // include a message-body": 28 switch code { 29 case http.StatusNoContent, http.StatusNotModified: // 204, 304 30 w.WriteHeader(code) 31 return 32 } 33 34 switch v := value.(type) { 35 case string: 36 w.Header().Set("Content-Type", "text/plain; charset=us-ascii") 37 w.WriteHeader(code) 38 39 if _, err := fmt.Fprintln(w, v); err != nil { 40 logrus.Errorf("unable to send string response: %q", err) 41 } 42 case *os.File: 43 w.Header().Set("Content-Type", "application/octet; charset=us-ascii") 44 w.WriteHeader(code) 45 46 if _, err := io.Copy(w, v); err != nil { 47 logrus.Errorf("unable to copy to response: %q", err) 48 } 49 case io.Reader: 50 w.Header().Set("Content-Type", "application/x-tar") 51 w.WriteHeader(code) 52 53 if _, err := io.Copy(w, v); err != nil { 54 logrus.Errorf("unable to copy to response: %q", err) 55 } 56 default: 57 WriteJSON(w, code, value) 58 } 59 } 60 61 func WriteJSON(w http.ResponseWriter, code int, value interface{}) { 62 // FIXME: we don't need to write the header in all/some circumstances. 63 w.Header().Set("Content-Type", "application/json") 64 w.WriteHeader(code) 65 66 coder := json.NewEncoder(w) 67 coder.SetEscapeHTML(true) 68 if err := coder.Encode(value); err != nil { 69 logrus.Errorf("unable to write json: %q", err) 70 } 71 } 72 73 func FilterMapToString(filters map[string][]string) (string, error) { 74 f, err := json.Marshal(filters) 75 if err != nil { 76 return "", err 77 } 78 return string(f), nil 79 } 80 81 func getVar(r *http.Request, k string) string { 82 val := mux.Vars(r)[k] 83 safeVal, err := url.PathUnescape(val) 84 if err != nil { 85 logrus.Error(errors.Wrapf(err, "failed to unescape mux key %s, value %s", k, val)) 86 return val 87 } 88 return safeVal 89 } 90 91 // GetName extracts the name from the mux 92 func GetName(r *http.Request) string { 93 return getVar(r, "name") 94 }