github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+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{ 35 Transport: tr, 36 CheckRedirect: func(_ *http.Request, _ []*http.Request) error { 37 // This prevents redirects. When making a request to /oauth/authorize, 38 // the client should not follow redirects in order to obtain the ssh 39 // passcode. 40 return http.ErrUseLastResponse 41 }, 42 }, 43 } 44 } 45 46 // Make takes a passedRequest, converts it into an HTTP request and then 47 // executes it. The response is then injected into passedResponse. 48 func (connection *UAAConnection) Make(request *http.Request, passedResponse *Response) error { 49 // In case this function is called from a retry, passedResponse may already 50 // be populated with a previous response. We reset in case there's an HTTP 51 // error and we don't repopulate it in populateResponse. 52 passedResponse.reset() 53 54 response, err := connection.HTTPClient.Do(request) 55 if err != nil { 56 return connection.processRequestErrors(request, err) 57 } 58 59 return connection.populateResponse(response, passedResponse) 60 } 61 62 func (connection *UAAConnection) processRequestErrors(request *http.Request, err error) error { 63 switch e := err.(type) { 64 case *url.Error: 65 if _, ok := e.Err.(x509.UnknownAuthorityError); ok { 66 return UnverifiedServerError{ 67 URL: request.URL.String(), 68 } 69 } 70 return RequestError{Err: e} 71 default: 72 return err 73 } 74 } 75 76 func (connection *UAAConnection) populateResponse(response *http.Response, passedResponse *Response) error { 77 passedResponse.HTTPResponse = response 78 79 rawBytes, err := ioutil.ReadAll(response.Body) 80 defer response.Body.Close() 81 if err != nil { 82 return err 83 } 84 passedResponse.RawResponse = rawBytes 85 86 err = connection.handleStatusCodes(response, passedResponse) 87 if err != nil { 88 return err 89 } 90 91 if passedResponse.Result != nil { 92 decoder := json.NewDecoder(bytes.NewBuffer(passedResponse.RawResponse)) 93 decoder.UseNumber() 94 err = decoder.Decode(passedResponse.Result) 95 if err != nil { 96 return err 97 } 98 } 99 100 return nil 101 } 102 103 func (*UAAConnection) handleStatusCodes(response *http.Response, passedResponse *Response) error { 104 if response.StatusCode >= 400 { 105 return RawHTTPStatusError{ 106 StatusCode: response.StatusCode, 107 RawResponse: passedResponse.RawResponse, 108 } 109 } 110 111 return nil 112 }