diff --git a/client.go b/client.go index 1a14c6d5..f4ed8b0b 100644 --- a/client.go +++ b/client.go @@ -18,11 +18,12 @@ import ( "strings" "time" + utls "github.com/refraction-networking/utls" + "golang.org/x/net/publicsuffix" + "github.com/imroc/req/v3/http2" "github.com/imroc/req/v3/internal/header" "github.com/imroc/req/v3/internal/util" - utls "github.com/refraction-networking/utls" - "golang.org/x/net/publicsuffix" ) // DefaultClient returns the global default Client. @@ -70,8 +71,11 @@ type Client struct { roundTripWrappers []RoundTripWrapper responseBodyTransformer func(rawBody []byte, req *Request, resp *Response) (transformedBody []byte, err error) resultStateCheckFunc func(resp *Response) ResultState + onError ErrorHook } +type ErrorHook func(client *Client, req *Request, resp *Response, err error) + // R create a new request. func (c *Client) R() *Request { return &Request{ @@ -981,6 +985,13 @@ func (c *Client) SetProxy(proxy func(*http.Request) (*urlpkg.URL, error)) *Clien return c } +// OnError set the error hook which will be executed if any error returned, +// even if the occurs before request is sent (e.g. invalid URL). +func (c *Client) OnError(hook ErrorHook) *Client { + c.onError = hook + return c +} + // OnBeforeRequest add a request middleware which hooks before request sent. func (c *Client) OnBeforeRequest(m RequestMiddleware) *Client { c.udBeforeRequest = append(c.udBeforeRequest, m) diff --git a/request.go b/request.go index 4a40df75..2e0fceb6 100644 --- a/request.go +++ b/request.go @@ -15,6 +15,7 @@ import ( "time" "github.com/hashicorp/go-multierror" + "github.com/imroc/req/v3/internal/dump" "github.com/imroc/req/v3/internal/header" "github.com/imroc/req/v3/internal/util" @@ -285,9 +286,11 @@ func (r *Request) SetFile(paramName, filePath string) *Request { }) } -var errMissingParamName = errors.New("missing param name in multipart file upload") -var errMissingFileName = errors.New("missing filename in multipart file upload") -var errMissingFileContent = errors.New("missing file content in multipart file upload") +var ( + errMissingParamName = errors.New("missing param name in multipart file upload") + errMissingFileName = errors.New("missing filename in multipart file upload") + errMissingFileContent = errors.New("missing file content in multipart file upload") +) // SetFileUpload set the fully custimized multipart file upload options. func (r *Request) SetFileUpload(uploads ...FileUpload) *Request { @@ -695,8 +698,6 @@ func (r *Request) do() (resp *Response, err error) { resp.result = nil resp.error = nil } - - return } // Send fires http request with specified method and url, returns the @@ -705,6 +706,9 @@ func (r *Request) Send(method, url string) (*Response, error) { r.Method = method r.RawURL = url resp := r.Do() + if resp.Err != nil && r.client.onError != nil { + r.client.onError(r.client, r, resp, resp.Err) + } return resp, resp.Err }