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

Improve error handling, expose error and error_description #108

Merged
merged 11 commits into from
Sep 21, 2021

Conversation

logangingerich
Copy link
Contributor

https://linear.app/workos/issue/SDK-66/improve-error-handling-in-go-sdk

Exposes error and error_description in error body to improve error handling.

@logangingerich logangingerich requested a review from a team as a code owner June 15, 2021 16:33
@linear
Copy link

linear bot commented Jun 15, 2021

SDK-66 Improve error handling in Go SDK

See this PR for example: workos/workos-ruby#106

Status string
RequestID string
Message string
Err string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we expand these names to Error and ErrorDescription?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maxdeviant I'm looking at it now and just remembered why I did the naming this way 😅 . It seems that Error might be a reserved name in this case, as using it seems to introduce a slew of errors:

./http.go:37:18: HTTPError.Error is a field, not a method
./http.go:37:18: cannot use HTTPError{...} (type HTTPError) as type error in return argument:
	HTTPError does not implement error (missing Error method)
./http.go:57:6: type HTTPError has both field and method named Error

Is there a different nomenclature that might work? Shouldn't be an issue with ErrorDescription.

}

func (e HTTPError) Error() string {
return fmt.Sprintf("%s: request id %q: %s", e.Status, e.RequestID, e.Message)
return fmt.Sprintf("%s: request id %q: %s %s %s", e.Status, e.RequestID, e.Message, e.Err, e.ErrDescription)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of these properties are going to be mutually-exclusive (for example, we won't have a message alongside an error and error_description.

We should probably adjust the string representation based on which properties are present.

@@ -25,23 +27,39 @@ func TryGetHTTPError(r *http.Response) error {
} else {
msg = string(body)
}
if e := gjson.GetBytes(body, "error").Str; e != "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We removed gjson as a dependency in #115, so we'll have to adjust our approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maxdeviant I've been working on this but can't seem to use your logic to accomplish the same behavior I was getting through gjson.GetBytes(body, "error") or gjson.GetBytes(body, "error_description")

If you have any pointers, I'd appreciate it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, just attempting to use the same logic and extract error description doesn't seem to work:

func getJsonErrorDescription(b []byte) string {
	var response struct{ ErrorDescription string }

	if err := json.Unmarshal(b, &response); err != nil {
		return ""
	}

	return response.ErrorDescription
}

@mthadley mthadley self-assigned this Sep 17, 2021
The previous implementation worked, but relied on the JSON parser
failing on plain-text responses. Seems better to be explicit about when
we decide to treat the response as JSON.
`r` is already being used for `http.Response` in this file.
@mthadley
Copy link
Contributor

@logangingerich @maxdeviant

I think I have this working correctly again, without the old gjson dependency. Take a look when convenient!

In the rare case that we send back invalid JSON with `Content-Type` set
as JSON, it'll probably be more useful for the developer to see the
entire body instead of the decoding error message.
@@ -1,18 +1,37 @@
package workos

import (
"github.com/stretchr/testify/require"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Not sure if this was a gofmt change or a manual one, but AFAIK it's idiomatic to keep the imports for the standard library separate from external imports.

Separate internal from external dependencies
@logangingerich logangingerich merged commit 364f86f into master Sep 21, 2021
@logangingerich logangingerich deleted the feature/sdk-66-improve-error-handling-in-go-sdk branch September 21, 2021 16:39
@maxdeviant maxdeviant mentioned this pull request Sep 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants