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  }