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

Return XML formatted error messages #156

Merged
merged 1 commit into from
Sep 26, 2024

Conversation

mosiac1
Copy link
Contributor

@mosiac1 mosiac1 commented Sep 23, 2024

We noticed a regression in our testing suite for internal plugins which seems to be cause by bfbcaf2, specifically the upgrade from io.airlift:airlift version 249 to 266 which bumps the jetty version to 12.0.13.

The test added in this PR passed on io.airlift:airlift version 252, which would indicate what caused the regression was added in jetty 12.0.12.

The root cause is that a RequestLoggerController has unclosed sessions when the Airlift Boostrap lifecycle is getting closed.
This is because runtime exceptions (that do not inherit from WebApplicationException) thrown during request processing (here thrown in the credentials provider plugin, but anywhere works really) causes jetty to not call our response filter RequestFilter#filter(ContainerRequestContext, ContainerResponseContext), thus not closing the request logger session.

I'm looking into how to fix this regression.

@mosiac1
Copy link
Contributor Author

mosiac1 commented Sep 23, 2024

@ragnard you are probably most familiar with jetty and airlift, any idea why this is happening? This would seem like a jetty bug, but I haven't isolated it to that.

@mosiac1 mosiac1 changed the title Add test for exception propagation from plugins Return XML formatted error messages Sep 24, 2024
@mosiac1
Copy link
Contributor Author

mosiac1 commented Sep 24, 2024

The ContainerResponseFilter works correctly if there is ExceptionMapper which processes the exceptions.

Repurposed the PR to add a mapper for any Throwable that returns an error response formatted based on https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingRESTError.html

@mosiac1 mosiac1 force-pushed the feat/plugin-exceptions branch 2 times, most recently from 67bf1ea to ea32780 Compare September 24, 2024 17:29
@mosiac1 mosiac1 force-pushed the feat/plugin-exceptions branch 2 times, most recently from 6e80013 to 342ce27 Compare September 24, 2024 17:50
@JsonInclude(JsonInclude.Include.NON_NULL)
@JacksonXmlRootElement(localName = "Error")
public record ErrorResponse(String code, String message, String resource, Optional<String> requestId)
{ }
Copy link
Member

Choose a reason for hiding this comment

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

Please add compact constructor with notNull checks

Copy link
Member

Choose a reason for hiding this comment

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

Some of them may be null though right? They're being excluded with the @JsonIncludeannotation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, but since we saw Optional works I'm in favour of using that and maintaining null safety. We can remove the @JsonInclude annotation.
We can always come up with values for code, message and resource.

Copy link
Member

Choose a reason for hiding this comment

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

Happy to maintain null safety, but we should then make sure we never construct one of these with a null value. We don't want to have our exception handling logic result in an unhandled exception because of a null check when constructing the response

Copy link
Member

@Randgalt Randgalt left a comment

Choose a reason for hiding this comment

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

A few comments

@mosiac1 mosiac1 force-pushed the feat/plugin-exceptions branch 2 times, most recently from e251b50 to bd722f5 Compare September 26, 2024 11:17
Comment on lines 70 to 74
ErrorResponse response = new ErrorResponse(
status.reason(),
throwable.getMessage(),
containerRequest.getRequestUri().getPath(),
requestId);
Copy link
Member

Choose a reason for hiding this comment

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

Should we create a constructor that takes in optionals for all fields and uses a default if the optional is empty?

For instance, if the exception has a null message (which may happen) we'd fail at the requireNonNull stage and then we lose all the information for the other fields that may be present.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point!
I think making all the fields optionals is a bit verbose. The code and resources should always be resolvable (since these are the response status code and the request path), so we can make just the message an optional.

@mosiac1 mosiac1 merged commit 7fecc58 into trinodb:main Sep 26, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

3 participants