Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add user defined OnBeforeRequest middlewares on all response paths, improve documentation #372

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
50 changes: 40 additions & 10 deletions client.go
Expand Up @@ -125,6 +125,7 @@ type Client struct {
udBeforeRequest []RequestMiddleware
preReqHook PreRequestHook
afterResponse []ResponseMiddleware
udAfterResponse []ResponseMiddleware
lggomez marked this conversation as resolved.
Show resolved Hide resolved
requestLog RequestLogCallback
responseLog ResponseLogCallback
}
Expand Down Expand Up @@ -364,22 +365,31 @@ func (c *Client) NewRequest() *Request {
//
// return nil // if its success otherwise return error
// })
//
// Please note that reading the request body on a middleware will drain it,
// making it unavailable on the following middlewares and at request time.
// For more information see https://golang.org/pkg/net/http/httputil/#DumpRequest
func (c *Client) OnBeforeRequest(m RequestMiddleware) *Client {
c.udBeforeRequest = append(c.udBeforeRequest, m)
return c
}

// OnAfterResponse method appends response middleware into the after response chain.
// Once we receive response from host server, default Resty response middleware
// gets applied and then user assigened response middlewares applied.
// gets applied and then user assigned response middlewares applied.
// Note that these middleware will execute on all paths, including request failure
// client.OnAfterResponse(func(c *resty.Client, r *resty.Response) error {
// // Now you have access to Client and Response instance
// // manipulate it as per your need
//
// return nil // if its success otherwise return error
// })
//
// Please note that reading the response body on a middleware will drain it,
// making it unavailable on the following middlewares and at further consumption.
// For more information see https://golang.org/pkg/net/http/httputil/#DumpResponse
func (c *Client) OnAfterResponse(m ResponseMiddleware) *Client {
c.afterResponse = append(c.afterResponse, m)
c.udAfterResponse = append(c.udAfterResponse, m)
return c
}

Expand Down Expand Up @@ -792,18 +802,17 @@ func (c *Client) GetClient() *http.Client {
// error.
func (c *Client) execute(req *Request) (*Response, error) {
defer releaseBuffer(req.bodyBuf)
// Apply Request middleware
// Apply Request middlewares on the *resty.Request instance
var err error

// resty middlewares
// Apply resty OnBeforeRequest middlewares
for _, f := range c.beforeRequest {
if err = f(c, req); err != nil {
return nil, wrapNoRetryErr(err)
}
}

// user defined on before request methods
// to modify the *resty.Request object
// Apply user-defined OnBeforeRequest middlewares
for _, f := range c.udBeforeRequest {
if err = f(c, req); err != nil {
return nil, wrapNoRetryErr(err)
Expand All @@ -825,16 +834,22 @@ func (c *Client) execute(req *Request) (*Response, error) {
return nil, wrapNoRetryErr(err)
}

// Execute HTTP request
req.Time = time.Now()
resp, err := c.httpClient.Do(req.RawRequest)

// Build Response from HTTP response
response := &Response{
Request: req,
RawResponse: resp,
}

// Response handling: on happy path execute resty OnAfterResponse middlewares
// on all paths execute user-defined middlewares on the *resty.Response instance

if err != nil || req.notParseResponse || c.notParseResponse {
response.setReceivedAt()
c.applyResponseMiddlewares(response)
return response, err
}

Expand All @@ -848,6 +863,7 @@ func (c *Client) execute(req *Request) (*Response, error) {
body, err = gzip.NewReader(body)
if err != nil {
response.setReceivedAt()
c.applyResponseMiddlewares(response)
return response, err
}
defer closeq(body)
Expand All @@ -856,6 +872,7 @@ func (c *Client) execute(req *Request) (*Response, error) {

if response.body, err = ioutil.ReadAll(body); err != nil {
response.setReceivedAt()
c.applyResponseMiddlewares(response)
return response, err
}

Expand All @@ -864,14 +881,26 @@ func (c *Client) execute(req *Request) (*Response, error) {

response.setReceivedAt() // after we read the body

// Apply Response middleware
// Apply internal and OnAfterResponse middlewares
err = c.applyResponseMiddlewares(response)

return response, wrapNoRetryErr(err)
}

// Apply user defined Response middlewares on the given response
func (c *Client) applyResponseMiddlewares(response *Response) error {
var err error
for _, f := range c.udAfterResponse {
if err = f(c, response); err != nil {
break
}
}
for _, f := range c.afterResponse {
if err = f(c, response); err != nil {
break
}
}

return response, wrapNoRetryErr(err)
return err
}

// getting TLS client config if not exists then create one
Expand Down Expand Up @@ -965,8 +994,9 @@ func createClient(hc *http.Client) *Client {
addCredentials,
}

// user defined request middlewares
// user defined request and response middlewares
c.udBeforeRequest = []RequestMiddleware{}
c.udAfterResponse = []ResponseMiddleware{}

// default after response middlewares
c.afterResponse = []ResponseMiddleware{
Expand Down