palourde/uchiwa

View on GitHub
uchiwa/sensu/request.go

Summary

Maintainability
B
4 hrs
Test Coverage
package sensu

import (
    "crypto/tls"
    "fmt"
    "io"
    "io/ioutil"
    "net/http"
    "net/http/httptrace"
    "net/url"

    "github.com/sensu/uchiwa/uchiwa/helpers"
    "github.com/sensu/uchiwa/uchiwa/logger"
)

// ...
func (api *API) doRequest(req *http.Request) ([]byte, *http.Response, error) {
    if api.User != "" && api.Pass != "" {
        req.SetBasicAuth(api.User, api.Pass)
    }

    req.Close = api.CloseRequest

    if api.Tracing {
        trace := &httptrace.ClientTrace{
            ConnectStart: func(network, addr string) {
                logger.Customf("httptrace", "Dial started for request %s: %s %s", req.URL, network, addr)
            },
            ConnectDone: func(network, addr string, err error) {
                if err == nil {
                    err = fmt.Errorf("nil")
                }
                logger.Customf("httptrace", "Dial done with error=%s", err.Error())
            },
            GotConn: func(connInfo httptrace.GotConnInfo) {
                logger.Customf("httptrace", "Successful connection details: %+v", connInfo)
            },
            GotFirstResponseByte: func() {
                logger.Custom("httptrace", "Got first response byte for the request")
            },
            TLSHandshakeDone: func(connectionState tls.ConnectionState, err error) {
                if err == nil {
                    err = fmt.Errorf("nil")
                }
                logger.Customf("httptrace", "TLS handshake done with error=%s", err)
            },
        }
        req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
    }

    res, err := api.Client.Do(req)
    if err != nil {
        status, ok := err.(*url.Error)
        if !ok {
            return nil, nil, fmt.Errorf("Unexpected error, got %T, wanted *url.Error", err)
        }
        return nil, nil, status.Err
    }

    defer res.Body.Close()

    if api.Tracing {
        logger.Customf("httptrace", "Length of response body: %d bytes", res.ContentLength)
    }

    if res.StatusCode >= 400 {
        return nil, nil, fmt.Errorf("%v", res.Status)
    }

    if res.ContentLength < 0 {

        if helpers.StringInSlice("chunked", res.TransferEncoding) {
            body, err := ioutil.ReadAll(res.Body)
            if err != nil {
                return nil, nil, fmt.Errorf("Parsing response body returned: %v", err)
            }
            return body, res, nil
        } else {
            return nil, nil, fmt.Errorf("unknown content length of %d and not TransferEncoding == \"chunked\"", res.ContentLength)
        }
    }
    body := make([]byte, res.ContentLength)
    n, err := io.ReadFull(res.Body, body)

    if err != nil {
        if err == io.ErrUnexpectedEOF {
            logger.Warningf("Tried to read %d bytes, got %d", res.ContentLength, n)
            if api.Tracing {
                logger.Infof("Got %s", string(body[0:n]))
            }
        }
        return nil, nil, fmt.Errorf("Parsing response body returned: %v", err)
    }

    if api.Tracing {
        logger.Customf("httptrace", "Closing connection")
    }

    return body, res, nil

}