github.com/jghiloni/cli@v6.28.1-0.20170628223758-0ce05fe032a2+incompatible/api/uaa/uaa_connection.go (about) 1 package uaa 2 3 import ( 4 "bytes" 5 "crypto/tls" 6 "crypto/x509" 7 "encoding/json" 8 "io/ioutil" 9 "net" 10 "net/http" 11 "net/url" 12 "time" 13 ) 14 15 // UAAConnection represents the connection to UAA 16 type UAAConnection struct { 17 HTTPClient *http.Client 18 } 19 20 // NewConnection returns a pointer to a new UAA Connection 21 func NewConnection(skipSSLValidation bool, dialTimeout time.Duration) *UAAConnection { 22 tr := &http.Transport{ 23 TLSClientConfig: &tls.Config{ 24 InsecureSkipVerify: skipSSLValidation, 25 }, 26 Proxy: http.ProxyFromEnvironment, 27 DialContext: (&net.Dialer{ 28 KeepAlive: 30 * time.Second, 29 Timeout: dialTimeout, 30 }).DialContext, 31 } 32 33 return &UAAConnection{ 34 HTTPClient: &http.Client{Transport: tr}, 35 } 36 } 37 38 // Make takes a passedRequest, converts it into an HTTP request and then 39 // executes it. The response is then injected into passedResponse. 40 func (connection *UAAConnection) Make(request *http.Request, passedResponse *Response) error { 41 // In case this function is called from a retry, passedResponse may already 42 // be populated with a previous response. We reset in case there's an HTTP 43 // error and we don't repopulate it in populateResponse. 44 passedResponse.reset() 45 46 response, err := connection.HTTPClient.Do(request) 47 if err != nil { 48 return connection.processRequestErrors(request, err) 49 } 50 51 return connection.populateResponse(response, passedResponse) 52 } 53 54 func (connection *UAAConnection) processRequestErrors(request *http.Request, err error) error { 55 switch e := err.(type) { 56 case *url.Error: 57 if _, ok := e.Err.(x509.UnknownAuthorityError); ok { 58 return UnverifiedServerError{ 59 URL: request.URL.String(), 60 } 61 } 62 return RequestError{Err: e} 63 default: 64 return err 65 } 66 } 67 68 func (connection *UAAConnection) populateResponse(response *http.Response, passedResponse *Response) error { 69 passedResponse.HTTPResponse = response 70 71 rawBytes, err := ioutil.ReadAll(response.Body) 72 defer response.Body.Close() 73 if err != nil { 74 return err 75 } 76 passedResponse.RawResponse = rawBytes 77 78 err = connection.handleStatusCodes(response, passedResponse) 79 if err != nil { 80 return err 81 } 82 83 if passedResponse.Result != nil { 84 decoder := json.NewDecoder(bytes.NewBuffer(passedResponse.RawResponse)) 85 decoder.UseNumber() 86 err = decoder.Decode(passedResponse.Result) 87 if err != nil { 88 return err 89 } 90 } 91 92 return nil 93 } 94 95 func (*UAAConnection) handleStatusCodes(response *http.Response, passedResponse *Response) error { 96 if response.StatusCode >= 400 { 97 return RawHTTPStatusError{ 98 StatusCode: response.StatusCode, 99 RawResponse: passedResponse.RawResponse, 100 } 101 } 102 103 return nil 104 }