-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Issue #12505 - Server to Servlet Error Handling #12586
Conversation
…12505-server-to-servlet-errorhandling
There was a problem hiding this 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
jetty-ee10/jetty-ee10-webapp/src/test/java/org/eclipse/jetty/ee10/webapp/WebAppContextTest.java
Outdated
Show resolved
Hide resolved
...e11/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletChannelState.java
Outdated
Show resolved
Hide resolved
jetty-ee9/jetty-ee9-webapp/src/test/java/org/eclipse/jetty/ee9/webapp/WebAppContextTest.java
Outdated
Show resolved
Hide resolved
jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ContextHandler.java
Show resolved
Hide resolved
...0/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletContextHandler.java
Show resolved
Hide resolved
There was a problem hiding this 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
There was a problem hiding this 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.
There was a problem hiding this 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.
jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/Dispatcher.java
Outdated
Show resolved
Hide resolved
{ | ||
return switch (name) | ||
{ | ||
case ERROR_REQUEST_URI -> _httpServletRequest.getRequestURI(); |
There was a problem hiding this comment.
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.
jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/Dispatcher.java
Show resolved
Hide resolved
...e10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/ServletChannelState.java
Outdated
Show resolved
Hide resolved
...1/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ErrorPageErrorHandler.java
Outdated
Show resolved
Hide resolved
jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/Dispatcher.java
Show resolved
Hide resolved
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); |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
...1/jetty-ee11-servlet/src/main/java/org/eclipse/jetty/ee11/servlet/ServletContextHandler.java
Show resolved
Hide resolved
…12505-server-to-servlet-errorhandling
…12505-server-to-servlet-errorhandling
// 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice
Fixes #12505
Addresses: