improve raw request/response content dump for ghttp.Client

This commit is contained in:
John
2020-04-24 00:00:52 +08:00
parent 83eb8be064
commit 7edec099ab
6 changed files with 31 additions and 38 deletions

View File

@ -19,13 +19,13 @@ import (
// dumpTextFormat is the format of the dumped raw string
const dumpTextFormat = `+---------------------------------------------+
| ghttp %s |
| %s |
+---------------------------------------------+
%s
%s
`
// ifDumpBody determine whether to output body according to content-type
// ifDumpBody determines whether to output body according to content-type.
func ifDumpBody(contentType string) bool {
// the body should not be output when the body is html or stream.
if gstr.Contains(contentType, "application/json") ||
@ -66,43 +66,34 @@ func getResponseBody(resp *http.Response) string {
if errReadBody != nil {
return ""
}
// so that the response body can be read again.
// So the response body can be read again.
resp.Body = ioutil.NopCloser(bytes.NewBuffer(bytesBody))
return gconv.UnsafeBytesToStr(bytesBody)
}
// getRequest returns the request related to the response.
// will return the copy of request when the request failed.
func (r *ClientResponse) getRequest() *http.Request {
if r.Response != nil && r.Request != nil {
return r.Request
}
// r.req is the copy of request when the http request failed.
if r.req != nil {
return r.req
}
return nil
}
// RawRequest returns the raw text of the request.
// RawRequest returns the raw content of the request.
func (r *ClientResponse) RawRequest() string {
// ClientResponse can be nil.
if r == nil {
return ""
}
req := r.getRequest()
if req == nil {
if r.request == nil {
return ""
}
// DumpRequestOut writes more request headers than DumpRequest, such as User-Agent.
bs, err := httputil.DumpRequestOut(req, false)
bs, err := httputil.DumpRequestOut(r.request, false)
if err != nil {
return ""
}
return fmt.Sprintf(dumpTextFormat, "REQUEST ", gconv.UnsafeBytesToStr(bs), getRequestBody(req))
return fmt.Sprintf(
dumpTextFormat,
"REQUEST ",
gconv.UnsafeBytesToStr(bs),
getRequestBody(r.request),
)
}
// RawResponse returns the raw text of the response.
// RawResponse returns the raw content of the response.
func (r *ClientResponse) RawResponse() string {
// ClientResponse can be nil.
if r == nil || r.Response == nil {
@ -113,7 +104,12 @@ func (r *ClientResponse) RawResponse() string {
return ""
}
return fmt.Sprintf(dumpTextFormat, "RESPONSE", gconv.UnsafeBytesToStr(bs), getResponseBody(r.Response))
return fmt.Sprintf(
dumpTextFormat,
"RESPONSE",
gconv.UnsafeBytesToStr(bs),
getResponseBody(r.Response),
)
}
// Raw returns the raw text of the request and the response.

View File

@ -215,30 +215,28 @@ func (c *Client) DoRequest(method, url string, data ...interface{}) (resp *Clien
if len(c.authUser) > 0 {
req.SetBasicAuth(c.authUser, c.authPass)
}
// Sending request.
var r *http.Response
// do not return nil even if the request fails
resp = &ClientResponse{}
for {
if r, err = c.Do(req); err != nil {
if resp.Response, err = c.Do(req); err != nil {
if c.retryCount > 0 {
c.retryCount--
time.Sleep(c.retryInterval)
} else {
// we need a copy of the request when the request fails.
resp.req = req
resp.request = req
return resp, err
}
} else {
resp.request = resp.Request
break
}
}
resp.Response = r
// Auto saving cookie content.
if c.browserMode {
now := time.Now()
for _, v := range r.Cookies() {
for _, v := range resp.Response.Cookies() {
if v.Expires.UnixNano() < now.UnixNano() {
delete(c.cookies, v.Name)
} else {

View File

@ -9,15 +9,14 @@ package ghttp
import (
"io/ioutil"
"net/http"
"time"
"github.com/gogf/gf/util/gconv"
)
// ClientResponse is the struct for client request response.
type ClientResponse struct {
req *http.Request // just a copy of the request when the request failed.
*http.Response
request *http.Request
cookies map[string]string
}
@ -49,7 +48,7 @@ func (r *ClientResponse) GetCookieMap() map[string]string {
// ReadAll retrieves and returns the response content as []byte.
func (r *ClientResponse) ReadAll() []byte {
body, err := ioutil.ReadAll(r.Body)
body, err := ioutil.ReadAll(r.Response.Body)
if err != nil {
return nil
}
@ -64,5 +63,5 @@ func (r *ClientResponse) ReadAllString() string {
// Close closes the response when it will never be used.
func (r *ClientResponse) Close() error {
r.Response.Close = true
return r.Body.Close()
return r.Response.Body.Close()
}

View File

@ -44,7 +44,7 @@ func Test_BindMiddleware_Basic1(t *testing.T) {
r.Response.Write("8")
})
s.SetPort(p)
//s.SetDumpRouterMap(false)
s.SetDumpRouterMap(false)
s.Start()
defer s.Shutdown()
@ -248,7 +248,7 @@ func Test_Middleware_Hook_With_Static(t *testing.T) {
})
})
s.SetPort(p)
//s.SetDumpRouterMap(false)
s.SetDumpRouterMap(false)
s.SetServerRoot(gdebug.TestDataPath("static1"))
s.Start()
defer s.Shutdown()
@ -701,7 +701,7 @@ func Test_Middleware_Panic(t *testing.T) {
})
})
s.SetPort(p)
//s.SetDumpRouterMap(false)
s.SetDumpRouterMap(false)
s.Start()
defer s.Shutdown()
time.Sleep(100 * time.Millisecond)

View File

@ -349,7 +349,7 @@ func Test_Router_DomainGroup(t *testing.T) {
})
})
s.SetPort(p)
//s.SetDumpRouterMap(false)
s.SetDumpRouterMap(false)
s.Start()
defer s.Shutdown()

View File

@ -70,7 +70,7 @@ func Test_Router_Hook_Fuzzy_Router(t *testing.T) {
r.Response.Write(r.Router.Uri)
})
s.SetPort(p)
//s.SetDumpRouterMap(false)
s.SetDumpRouterMap(false)
s.Start()
defer s.Shutdown()