1// Copyright (c) 2015-2019 Jeevanandam M (jeeva@myjeeva.com), All rights reserved. 2// resty source code and usage is governed by a MIT style 3// license that can be found in the LICENSE file. 4 5package resty 6 7import ( 8 "encoding/json" 9 "fmt" 10 "io" 11 "net/http" 12 "strings" 13 "time" 14) 15 16// Response is an object represents executed request and its values. 17type Response struct { 18 Request *Request 19 RawResponse *http.Response 20 21 body []byte 22 size int64 23 receivedAt time.Time 24} 25 26// Body method returns HTTP response as []byte array for the executed request. 27// Note: `Response.Body` might be nil, if `Request.SetOutput` is used. 28func (r *Response) Body() []byte { 29 if r.RawResponse == nil { 30 return []byte{} 31 } 32 return r.body 33} 34 35// Status method returns the HTTP status string for the executed request. 36// Example: 200 OK 37func (r *Response) Status() string { 38 if r.RawResponse == nil { 39 return "" 40 } 41 42 return r.RawResponse.Status 43} 44 45// StatusCode method returns the HTTP status code for the executed request. 46// Example: 200 47func (r *Response) StatusCode() int { 48 if r.RawResponse == nil { 49 return 0 50 } 51 52 return r.RawResponse.StatusCode 53} 54 55// Result method returns the response value as an object if it has one 56func (r *Response) Result() interface{} { 57 return r.Request.Result 58} 59 60// Error method returns the error object if it has one 61func (r *Response) Error() interface{} { 62 return r.Request.Error 63} 64 65// Header method returns the response headers 66func (r *Response) Header() http.Header { 67 if r.RawResponse == nil { 68 return http.Header{} 69 } 70 71 return r.RawResponse.Header 72} 73 74// Cookies method to access all the response cookies 75func (r *Response) Cookies() []*http.Cookie { 76 if r.RawResponse == nil { 77 return make([]*http.Cookie, 0) 78 } 79 80 return r.RawResponse.Cookies() 81} 82 83// String method returns the body of the server response as String. 84func (r *Response) String() string { 85 if r.body == nil { 86 return "" 87 } 88 89 return strings.TrimSpace(string(r.body)) 90} 91 92// Time method returns the time of HTTP response time that from request we sent and received a request. 93// See `response.ReceivedAt` to know when client recevied response and see `response.Request.Time` to know 94// when client sent a request. 95func (r *Response) Time() time.Duration { 96 return r.receivedAt.Sub(r.Request.Time) 97} 98 99// ReceivedAt method returns when response got recevied from server for the request. 100func (r *Response) ReceivedAt() time.Time { 101 return r.receivedAt 102} 103 104// Size method returns the HTTP response size in bytes. Ya, you can relay on HTTP `Content-Length` header, 105// however it won't be good for chucked transfer/compressed response. Since Resty calculates response size 106// at the client end. You will get actual size of the http response. 107func (r *Response) Size() int64 { 108 return r.size 109} 110 111// RawBody method exposes the HTTP raw response body. Use this method in-conjunction with `SetDoNotParseResponse` 112// option otherwise you get an error as `read err: http: read on closed response body`. 113// 114// Do not forget to close the body, otherwise you might get into connection leaks, no connection reuse. 115// Basically you have taken over the control of response parsing from `Resty`. 116func (r *Response) RawBody() io.ReadCloser { 117 if r.RawResponse == nil { 118 return nil 119 } 120 return r.RawResponse.Body 121} 122 123// IsSuccess method returns true if HTTP status code >= 200 and <= 299 otherwise false. 124func (r *Response) IsSuccess() bool { 125 return r.StatusCode() > 199 && r.StatusCode() < 300 126} 127 128// IsError method returns true if HTTP status code >= 400 otherwise false. 129func (r *Response) IsError() bool { 130 return r.StatusCode() > 399 131} 132 133func (r *Response) fmtBodyString(sl int64) string { 134 if r.body != nil { 135 if int64(len(r.body)) > sl { 136 return fmt.Sprintf("***** RESPONSE TOO LARGE (size - %d) *****", len(r.body)) 137 } 138 ct := r.Header().Get(hdrContentTypeKey) 139 if IsJSONType(ct) { 140 out := acquireBuffer() 141 defer releaseBuffer(out) 142 if err := json.Indent(out, r.body, "", " "); err == nil { 143 return out.String() 144 } 145 } 146 return r.String() 147 } 148 149 return "***** NO CONTENT *****" 150} 151