util.go raw

   1  package rest
   2  
   3  import (
   4  	"log"
   5  	"net/http"
   6  	"strings"
   7  )
   8  
   9  // DoerFunc satisfies Interface. DoerFuncs are useful for adding
  10  // logging/instrumentation to the http.Client that is used
  11  // within the rest.APIClient.
  12  type DoerFunc func(*http.Request) (*http.Response, error)
  13  
  14  // Do is implementation of rest.Doer interface. Calls itself on the
  15  // given http.Request.
  16  func (f DoerFunc) Do(r *http.Request) (*http.Response, error) {
  17  	return f(r)
  18  }
  19  
  20  // A Decorator wraps a Doer with extra behavior, and doesnt
  21  // affect the behavior of other instances of the same type.
  22  type Decorator func(Doer) Doer
  23  
  24  // Decorate decorates a Doer c with all the given Decorators, in order.
  25  // Core object(Doer instance) that we want to apply layers(Decorator slice) to.
  26  func Decorate(d Doer, ds ...Decorator) Doer {
  27  	decorated := d
  28  	for _, decorate := range ds {
  29  		decorated = decorate(decorated)
  30  	}
  31  	return decorated
  32  }
  33  
  34  // Logging returns a Decorator that logs a Doer's requests.
  35  // Dependency injection for the logger instance(inside the closures environment).
  36  func Logging(l *log.Logger) Decorator {
  37  	return func(d Doer) Doer {
  38  		return DoerFunc(func(r *http.Request) (*http.Response, error) {
  39  			userAgent := r.UserAgent()
  40  			escapedUserAgent := strings.Replace(userAgent, "\n", "", -1)
  41  			escapedUserAgent = strings.Replace(escapedUserAgent, "\r", "", -1)
  42  			userURL := r.URL.String()
  43  			escapedURL := strings.Replace(userURL, "\n", "", -1)
  44  			escapedURL = strings.Replace(escapedURL, "\r", "", -1)
  45  			l.Printf("%s: %s %s", escapedUserAgent, r.Method, escapedURL)
  46  			return d.Do(r)
  47  		})
  48  	}
  49  }
  50