Skip to content

Cleanup bad request exception type #4777

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

Merged
merged 6 commits into from
Apr 4, 2025
Merged

Conversation

humandad
Copy link
Contributor

@humandad humandad commented Apr 3, 2025

What does this PR do?

  1. Changes the NewBadRequestException constructor to take an error instead of a string.

@humandad humandad requested a review from techfg April 3, 2025 19:58
@humandad humandad self-assigned this Apr 3, 2025
@humandad humandad marked this pull request as ready for review April 4, 2025 16:07
Copy link
Collaborator

@techfg techfg left a comment

Choose a reason for hiding this comment

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

@humandad -

Left some comments but didn't annotate every situations since there were a lot of the same question/suggestion/comment.

  1. I think anywhere we do not return the original error, we should make sure to slog it prior to returning. We want to have the actual error somewhere.
  2. There's a few places we BadRequestException that possibly should be a different exception type
  3. Some questions on how we define our custom error types - I think the key here is to be consistent across all of them (assuming that's possible)

In hindsight, possibly just having single error param might have been best. We end up doing fmt.Sprintf() anyway in most cases so not much different than fmt.Errorf() lol.

return exceptions.NewBadRequestException(pgErr.Message)
// We're intentionally hiding the details of the error
// for example: pgErr.Severity and pgErr.Code
return exceptions.NewBadRequestException(pgErr.Message, nil)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we slog here to capture full error?

}
}

msg := err.Error()
if strings.Contains(msg, "failed to encode") || strings.Contains(msg, "failed to decode") {
return exceptions.NewBadRequestException(msg)
return exceptions.NewBadRequestException(msg, nil)
Copy link
Collaborator

Choose a reason for hiding this comment

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

slog to capture full error since we're dropping it?

@@ -143,10 +143,10 @@ func (c *Connection) Signup(signupMethod *meta.SignupMethod, payload map[string]
return c.callListenerBot(signupMethod.SignupBot, payload)
}
func (c *Connection) ResetPassword(payload map[string]interface{}, authenticated bool) (*meta.LoginMethod, error) {
return nil, exceptions.NewBadRequestException("Google login: unfortunately you cannot change the password")
return nil, exceptions.NewBadRequestException("Google login: unfortunately you cannot change the password", nil)
Copy link
Collaborator

Choose a reason for hiding this comment

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

should this be a 403 Forbidden instead of 400?

}
func (c *Connection) ConfirmResetPassword(payload map[string]interface{}) (*meta.User, error) {
return nil, exceptions.NewBadRequestException("Google login: unfortunately you cannot change the password")
return nil, exceptions.NewBadRequestException("Google login: unfortunately you cannot change the password", nil)
Copy link
Collaborator

Choose a reason for hiding this comment

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

should this be a 403 Forbidden instead of 400?

@@ -161,5 +161,5 @@ func (c *Connection) CreateLogin(signupMethod *meta.SignupMethod, payload map[st
}, c.connection, c.session)
}
func (c *Connection) ConfirmSignUp(signupMethod *meta.SignupMethod, payload map[string]interface{}) error {
return exceptions.NewBadRequestException("Google login: unfortunately you cannot change the password")
return exceptions.NewBadRequestException("Google login: unfortunately you cannot change the password", nil)
Copy link
Collaborator

Choose a reason for hiding this comment

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

should this be a 403 Forbidden instead of 400?

// TODO: Using [0] results in losing the original error in some cases which results in not always returning
// an appropriate HTTP status code. For example, the following url which has an invalid format for userfileid
// param encounters HTTP 500 when it should be HTTP 400
// https://studio.uesio-dev.com:3000/site/userfiles/download?userfileid=my-bad-id&version=1734112100
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should still keep this comment & TODO I think since we're still returning (*op.Errors)[0] which won't always have the original error

if op.HasErrors() {
return wire.NewGenericSaveException(exceptions.NewBadRequestException("error with field population"))
// TODO: This error message should be better and possibly include messages
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should likely slog all the errors in op here since we're dropping them

type BadRequestException struct {
msg string
}
type BadRequestException BaseException
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we gain anything (other than the private vars due to same memory layout) by the type declaration here since BadRequestException won't get BaseExceptions methods and we're customizing them anyway. I think the options here are:

  1. Embed BaseException - Not sure if this should be the type BaseException or pointer to type *BaseException, would need to test
type BadRequestException struct {
  BaseException
  1. Just use the private package helpers w/out involving BaseException here.

I think there will be times that we have exceptions that just need the BaseException functionality so I'd lean towards option 1 so that we define custom exceptions all the same way, whether or not there is any custom Error function or just using the default provided by BaseException

}

type LoadException struct {
Message string `json:"message"`
error error
err error
Copy link
Collaborator

Choose a reason for hiding this comment

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

See comment for BadRequestException about embedding, vs not, vs type declaration vs just using privates. This one we expose Message so that it serializes - that requirement may change the general approach to having a baseexception. I think the key is that we want to try to have all our custom errors follow the same definition approach if possible.

}
}

type SaveException struct {
RecordID string `json:"recordid"`
FieldID string `json:"fieldid"`
Message string `json:"message"`
error error
err error
Copy link
Collaborator

Choose a reason for hiding this comment

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

See comments on BadRequestException and LoadException about how to define the custom errors.

@humandad humandad merged commit 86fcf1d into main Apr 4, 2025
5 checks passed
@humandad humandad deleted the cleanup-bad-request-exception-type branch April 4, 2025 19:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants