diff --git a/request.go b/request.go index 7d209032..3bf236fd 100644 --- a/request.go +++ b/request.go @@ -324,7 +324,6 @@ func (r *Request) SetFileReader(param, fileName string, reader io.Reader) *Reque // SetMultipartFormData method allows simple form data to be attached to the request as `multipart:form-data` func (r *Request) SetMultipartFormData(data map[string]string) *Request { - for k, v := range data { r = r.SetMultipartField(k, "", "", strings.NewReader(v)) } @@ -575,18 +574,32 @@ func (r *Request) TraceInfo() TraceInfo { return TraceInfo{} } - return TraceInfo{ + ti := TraceInfo{ DNSLookup: ct.dnsDone.Sub(ct.dnsStart), - ConnTime: ct.gotConn.Sub(ct.getConn), - TCPConnTime: ct.connectDone.Sub(ct.dnsDone), TLSHandshake: ct.tlsHandshakeDone.Sub(ct.tlsHandshakeStart), ServerTime: ct.gotFirstResponseByte.Sub(ct.gotConn), - ResponseTime: ct.endTime.Sub(ct.gotFirstResponseByte), TotalTime: ct.endTime.Sub(ct.dnsStart), IsConnReused: ct.gotConnInfo.Reused, IsConnWasIdle: ct.gotConnInfo.WasIdle, ConnIdleTime: ct.gotConnInfo.IdleTime, } + + // Only calcuate on successful connections + if !ct.connectDone.IsZero() { + ti.TCPConnTime = ct.connectDone.Sub(ct.dnsDone) + } + + // Only calcuate on successful connections + if !ct.gotConn.IsZero() { + ti.ConnTime = ct.gotConn.Sub(ct.getConn) + } + + // Only calcuate on successful connections + if !ct.gotFirstResponseByte.IsZero() { + ti.ResponseTime = ct.endTime.Sub(ct.gotFirstResponseByte) + } + + return ti } //‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ diff --git a/request_test.go b/request_test.go index 89760454..219fb778 100644 --- a/request_test.go +++ b/request_test.go @@ -1476,7 +1476,6 @@ func TestReportMethodSupportsPayload(t *testing.T) { assertError(t, err) assertEqual(t, http.StatusOK, resp.StatusCode()) - } func TestRequestQueryStringOrder(t *testing.T) { @@ -1648,6 +1647,25 @@ func TestTraceInfoWithoutEnableTrace(t *testing.T) { } } +func TestTraceInfoOnTimeout(t *testing.T) { + client := dc() + client.SetHostURL("http://resty-nowhere.local").EnableTrace() + + resp, err := client.R().Get("/") + assertNotNil(t, err) + assertNotNil(t, resp) + + tr := resp.Request.TraceInfo() + assertEqual(t, true, tr.DNSLookup >= 0) + assertEqual(t, true, tr.ConnTime == 0) + assertEqual(t, true, tr.TLSHandshake == 0) + assertEqual(t, true, tr.TCPConnTime == 0) + assertEqual(t, true, tr.ServerTime == 0) + assertEqual(t, true, tr.ResponseTime == 0) + assertEqual(t, true, tr.TotalTime > 0) + assertEqual(t, true, tr.TotalTime == resp.Time()) +} + func TestDebugLoggerRequestBodyTooLarge(t *testing.T) { ts := createFilePostServer(t) defer ts.Close() @@ -1683,7 +1701,8 @@ func TestDebugLoggerRequestBodyTooLarge(t *testing.T) { SetFormData(map[string]string{ "first_name": "Alex", "last_name": strings.Repeat("C", int(debugBodySizeLimit)), - "zip_code": "00001"}). + "zip_code": "00001", + }). SetBasicAuth("myuser", "mypass"). Post(formTs.URL + "/profile") assertNil(t, err) @@ -1696,7 +1715,8 @@ func TestDebugLoggerRequestBodyTooLarge(t *testing.T) { SetFormData(map[string]string{ "first_name": "Alex", "last_name": "C", - "zip_code": "00001"}). + "zip_code": "00001", + }). SetBasicAuth("myuser", "mypass"). Post(formTs.URL + "/profile") assertNil(t, err) diff --git a/trace.go b/trace.go index 229ac040..025b7d9b 100644 --- a/trace.go +++ b/trace.go @@ -65,13 +65,13 @@ type TraceInfo struct { // Request. type clientTrace struct { getConn time.Time - gotConn time.Time - connectDone time.Time - gotFirstResponseByte time.Time dnsStart time.Time dnsDone time.Time + connectDone time.Time tlsHandshakeStart time.Time tlsHandshakeDone time.Time + gotConn time.Time + gotFirstResponseByte time.Time endTime time.Time gotConnInfo httptrace.GotConnInfo }