github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/util/http.go (about)

     1  package util
     2  
     3  import (
     4  	"crypto/tls"
     5  	"encoding/json"
     6  	"net/http"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/gorilla/mux"
    11  	"github.com/mongodb/grip"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  // WriteJSON writes a json response with the supplied code on the given writer.
    16  func WriteJSON(w *http.ResponseWriter, data interface{}, status int) {
    17  	// write the response
    18  	(*w).Header().Add("Content-Type", "application/json")
    19  	(*w).Header().Add("Connection", "close")
    20  
    21  	jsonBytes, err := json.Marshal(data)
    22  	if err != nil {
    23  		(*w).WriteHeader(500)
    24  		_, _ = (*w).Write([]byte("{}"))
    25  		return
    26  	}
    27  
    28  	(*w).WriteHeader(status)
    29  	_, err = (*w).Write(jsonBytes)
    30  	grip.Warning(err)
    31  }
    32  
    33  // MakeTlsConfig creates a TLS Config from a certificate and key.
    34  func MakeTlsConfig(cert string, key string) (*tls.Config, error) {
    35  	// Adapted from http.ListenAndServeTLS
    36  	tlsConfig := &tls.Config{}
    37  	tlsConfig.NextProtos = []string{"http/1.1"}
    38  	tlsConfig.Certificates = make([]tls.Certificate, 1)
    39  	var err error
    40  	tlsConfig.Certificates[0], err =
    41  		tls.X509KeyPair([]byte(cert), []byte(key))
    42  	if err != nil {
    43  		return nil, errors.WithStack(err)
    44  	}
    45  	return tlsConfig, nil
    46  }
    47  
    48  // MountHandler routes all requests to the given mux.Router under the prefix to be handled by
    49  // the http.Handler, which the request's path rooted under that prefix.
    50  // So for example, if a router configured with the path /foo is given to
    51  // MountHandler(r, "/bar/baz", newHandler)
    52  // Then a request to the router at /foo/bar/baz/hello will be handled by newHandler,
    53  // appearing with the path "/baz/hello"
    54  func MountHandler(r *mux.Router, prefix string, h http.Handler) http.Handler {
    55  	root := r.PathPrefix(prefix)
    56  	root.Handler(
    57  		http.HandlerFunc(func(w http.ResponseWriter, rq *http.Request) {
    58  			flattened := make([]string, 0)
    59  			for k, v := range mux.Vars(rq) {
    60  				flattened = append(flattened, k)
    61  				flattened = append(flattened, v)
    62  			}
    63  			url, err := root.URL(flattened...)
    64  			if err != nil {
    65  				http.NotFound(w, rq)
    66  				return
    67  			}
    68  			strip := strings.TrimSuffix(url.String(), "/")
    69  			http.StripPrefix(strip, h).ServeHTTP(w, rq)
    70  		}))
    71  	return r
    72  }
    73  
    74  // GetIntValue returns a form value as an integer
    75  func GetIntValue(r *http.Request, valueKey string, defaultValue int) (int, error) {
    76  	val := r.FormValue(valueKey)
    77  	if val == "" {
    78  		return defaultValue, nil
    79  	}
    80  	intVal, err := strconv.Atoi(val)
    81  	if err != nil {
    82  		return 0, errors.Errorf("%v: cannot convert %v to integer: %v", valueKey, val, err.Error())
    83  	}
    84  	return intVal, nil
    85  }
    86  
    87  // GetBoolValue returns a form value as an integer
    88  func GetBoolValue(r *http.Request, valueKey string, defaultValue bool) (bool, error) {
    89  	val := r.FormValue(valueKey)
    90  	if val == "" {
    91  		return defaultValue, nil
    92  	}
    93  	boolVal, err := strconv.ParseBool(val)
    94  	if err != nil {
    95  		return defaultValue, errors.Errorf("%v: cannot convert %v to boolean: %v", valueKey, val, err.Error())
    96  	}
    97  	return boolVal, nil
    98  }
    99  
   100  // GetStringArrayValue returns a form value as a string array
   101  func GetStringArrayValue(r *http.Request, valueKey string, defaultValue []string) []string {
   102  	val := r.FormValue(valueKey)
   103  	if val == "" {
   104  		return defaultValue
   105  	}
   106  	return strings.Split(val, ",")
   107  }