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

Issue #12505 - Server to Servlet Error Handling #12586

Merged

Conversation

janbartel
Copy link
Contributor

Fixes #12505

Addresses:

  • difference between jetty core error attributes and servlet api attributes
  • handling error generated in core before servlet context is selected

@gregw gregw marked this pull request as ready for review November 28, 2024 00:22
Copy link
Contributor Author

@janbartel janbartel left a comment

Choose a reason for hiding this comment

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

A couple of things

Copy link
Contributor

@gregw gregw left a comment

Choose a reason for hiding this comment

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

I approve, but then I have worked on this, so my review is not enough

Copy link
Contributor Author

@janbartel janbartel left a comment

Choose a reason for hiding this comment

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

I approve! But I can't officially as I've created the PR.

Copy link
Contributor

@lorban lorban left a comment

Choose a reason for hiding this comment

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

Just found a few nits.

{
return switch (name)
{
case ERROR_REQUEST_URI -> _httpServletRequest.getRequestURI();
Copy link
Contributor

Choose a reason for hiding this comment

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

You could call getRequest and cast it to HttpServletRequest instead of introducing the _httpServletRequest field.

@joakime joakime changed the title Jetty 12.1.x 12505 server to servlet errorhandling Issue #12505 - Server to Servlet Error Handling Dec 2, 2024
if (isProtectedTarget(pathInContext))
{
// Do nothing here other than set the error status so that the ServletHandler will handle as if a sendError
request.setAttribute(org.eclipse.jetty.server.handler.ErrorHandler.ERROR_STATUS, 404);
Copy link
Contributor

Choose a reason for hiding this comment

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

Its also possible to directly do a sendError directly here, which might be more clear, but might require some tweaks to the ServletChannelState to handle sendError from IDLE.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think it's any clearer - at this point we have a core Response, not a HttpServletResponse.

Copy link
Contributor

Choose a reason for hiding this comment

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

We do already know here it is a ServletContextRequest so we have access to the HttpServletResponse (checked directly above at the start of this method).

So you could do this servletContextRequest.getServletContextResponse().getServletRequestState().sendError(404, null);.

Currently this needs to set a special attribute to trigger calling sendError internally, when the call to sendError could be done right here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, we got into trouble last time by trying to handle the error here (with a Response.writeError that bypassed the ServletChannel etc), rather than letting the normal mechanism take care of it. IMHO that call chain isn't particularly clear either - (also, side note, that method is badly named, if it returns a ServletChannelState it shouldn't be called getServletRequestState).

@gregw what's your take on this? Want to try and take the short cut to sendError or set the attribute and flow through the normal execution path?

Copy link
Contributor

Choose a reason for hiding this comment

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

@lachlan-roberts At this point we have not entered the ServletHandler, so the ServletChannel state machine has not started. Thus I'm not sure that calling sendError here is exactly what we want to do. It might work, but it might also do other stuff that is not necessary. It is more likely to throw an ISE because the ServletChannelState will be IDLE.

The idea of this PR is to signal that a call to sendError is necessary, but to delay that until we are within the ServletChannelState machine.

Copy link
Contributor

Choose a reason for hiding this comment

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

It would take only 3-4 lines to be changed in ServletChannelState to make it work.

I would just prefer use of API, either sendError or something else, because someone working on a similar case in future will not know they have to set both the response status and this attribute to trigger a sendError if it hasn't entered the SerlvetChannel yet.

Copy link
Contributor

Choose a reason for hiding this comment

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

@lachlan-roberts I'm the other way. I like the ISE being thrown if sendError is being called outside of the scope it should be. If we want to cause a send error on entry to the ServletHandler, it is best to use a different mechanism.
In this case the mechanism is to have both the response status set AND the error attribute set. It is done this way because checking attributes is a little expensive, so we first check the status. But unfortunately checking the status is not enough as there are some strange circumstances where a status is spuriously set before arriving at the ServletHandler. So if it is non-zero, we then check the attribute to be sure an error dispatch was intended.

@janbartel perhaps we should put a comment to explain that?

Comment on lines +1202 to +1205
// At this point we have not entered the state machine of the ServletChannelState, so we do nothing here
// other than to set the error status attribute (and also status). When execution proceeds normally into the
// state machine the request will be treated as an error. Note that we set both the error status and request
// status because the request status is cheaper to check than the error status attribute.
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice

@janbartel janbartel merged commit 37d0b7c into jetty-12.1.x Dec 18, 2024
10 checks passed
@janbartel janbartel deleted the jetty-12.1.x-12505-server-to-servlet-errorhandling branch December 18, 2024 05:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

ErrorPageErrorHandler does not use the proper attributes for error handling
4 participants