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

Resty Error Handling by the book - can't catch a 404 HTTP status #560

Closed
BigBoulard opened this issue Jul 13, 2022 · 2 comments
Closed

Resty Error Handling by the book - can't catch a 404 HTTP status #560

BigBoulard opened this issue Jul 13, 2022 · 2 comments

Comments

@BigBoulard
Copy link

BigBoulard commented Jul 13, 2022

Hi,

I struggle to understand who error handling is working using Resty.
I make a PUT API call that returns a 404 HTTP status code but I can catch it in the code below.

I've tried to use resp.IsError() without sucess.

I've read some similar topic here which uses the SetError method on a struct (Error or Response depending on the case), but this method is maybe specifically tied to a marshalling error when using the SetResult method.

Do you have king of a simple example to understand the good way to handle error using Resty?
That would be awesome.

Best.

func PutItems( items []string) ([]string, string, rest_errors.RestErr){
  resp, err := client.R().
  SetHeader("Accept", "application/json").
  SetBody(myBody).
  Put(myEndpoint)
  
  if err != nil { // 404 don't happen here apparently
       return nil, rest_errors.NewBadRequestError("API Gateway - http update user cars:" + err.Error())
  }
  
  if resp.IsError() { // 404 is not detected either here
      return nil, errors.New("Unknow error here")
  }

  var createdItems []string
  err2 := json.Unmarshal(resp.Body(), &createdItems)
  if err2 != nil {
     return nil, errors.New("error when unmarshalling items" + err2.Error())
  }
  
  return createdItems, nil
}
@peterjmorgan
Copy link

I'm confused by this too.

Right now, instead of using the if err != nil pattern, I'm using:

if test := CheckResponse(resp); test != nil {
    // do stuff with the error
   return nil, errors.New("..."+ test.Error)
}

I have structs for the errors for this API I'm working on so CheckResponse() looks like:

func CheckResponse(resp *resty.Response) *ErrorStruct {
    var jsonER ErrorStruct

    if resp.IsError() {
        err := json.Unmarshall(resp.Body(), &jsonER)
        if err != nil {
             // barf
        }
        return &jsonER
    }
    return nil
}

It feels weird because every other Go library I've used follows the convention of returning errors in a return value.

Curious if anyone has figured this out better.

@segevda
Copy link
Contributor

segevda commented Sep 29, 2022

@BigBoulard
the error return value on the Get/Put/Post/Execute/etc methods indicates whether the request was successfully delivered and a response was returned from the server. This is not different from the native go http client, here quoting from the docs for the Do() method:
An error is returned if caused by client policy (such as CheckRedirect), or failure to speak HTTP (such as a network connectivity problem). A non-2xx status code doesn't cause an error.

IsError() should indeed return true if the returned status code is 4xx or 5xx. Try running the following snippet:


import (
	"fmt"

	"github.com/go-resty/resty/v2"
)

func main() {
	cl := resty.New().SetBaseURL("https://httpbin.org")

	resp, err := cl.R().Put("status/404")
	if err != nil {
		panic(err)
	}

	if resp.IsError() {
		fmt.Println(resp.StatusCode()) // prints 404
	}
}

The way you handled the error in your PutItems function is perfectly fine - if IsError() you should create and return an error.

@peterjmorgan: it seems that what your doing in your CheckResponse function can be achieved by using SetError(&ErrorStruct{}). If this doesn't work, care to elaborate on what happens?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants