Basically I think the only way you can solve this is to attach the error
code to the exchange somehow, then have a handler that reads the error code
and calls sendError later.Basically write a new response-code handler that
sets the code then calls the next handler (so the request gets to Servlet),
then add a handler to the Servlet deployment that calls sendError if the
exchange status code is > 400.
We could actually add this to Undertow very simply, just add a 'continue'
param to the response code handler, then always call sendError in servlet
if the incoming request response is >400.
Can you try this out, and if it works I can look at getting it into
Undertow.
Stuart
On Wed, 8 Jul 2020 at 02:35, Brad Wood <bdw429s(a)gmail.com> wrote:
Stuart, any further suggestions or answers to my outstanding
questions? So
far, everything you've suggested doesn't work for various reasons I've
shared here. I also have a number of outstanding questions such as how I
could access the deployment information for the servlet's error pages from
inside an HTTPHandler running in the initial handler chain that fires in
the XNIO worker.
Thanks!
~Brad
*Developer Advocate*
*Ortus Solutions, Corp *
E-mail: brad(a)coldbox.org
ColdBox Platform:
http://www.coldbox.org
Blog:
http://www.codersrevolution.com
On Fri, Jul 3, 2020 at 3:55 PM Brad Wood <bdw429s(a)gmail.com> wrote:
> After a few hours of experimenting, I was able to answer a few of my own
> questions, but not all of them.
>
> - Yes, it is possible to contribute a custom handler to the predicate
> language-- this is actually pretty sweet. I didn't realize just how
> generic the parser was.
> - In order to get "picked up", the builder class must be listed in
> the
> *META-INF/services/io.undertow.server.handlers.builder.HandlerBuilder*
> file
> - That custom handler suggested by Stuart in the previous message
> ONLY works if the predicate chain is wrapped "inside" the servlet
initial
> handler. Otherwise, the servletcontext classes are missing. This
> unfortunately, makes it a no-go for me to be able to use.
>
> The rest of my questions still stand however in so far as how I can
> accomplish what I need.
>
> During my experiments today, I also played with the error-file handler,
> but it also is of no use. Since the response-code handler ends the
> exchange, any error pages declared in the error file handler are never
> used!
>
> error-file( response-codes={404},
> file="C:\sandbox\predicatetest\custom404.html" )
> path('/box.json') -> response-code(404)
>
> I even tried creating a custom handler that sets the status code but
> continues the exchange, but then that just serves the original file anyway,
> which causes the error-file handler to do nothing since the response stream
> is already started.
>
> Thanks!
>
> ~Brad
>
> *Developer Advocate*
> *Ortus Solutions, Corp *
>
> E-mail: brad(a)coldbox.org
> ColdBox Platform:
http://www.coldbox.org
> Blog:
http://www.codersrevolution.com
>
>
>
> On Fri, Jul 3, 2020 at 12:02 PM Brad Wood <bdw429s(a)gmail.com> wrote:
>
>> You probably need to write a custom one that looks like this (plus the
>>> relevant predicate languge bits):
>>
>>
>> Stuart, if I can branch the conversation here back to your idea of a
>> custom handler for a bit...
>>
>> I'm still toying with this, and while the handleRequest() code you have
>> makes perfect sense, I think I'm missing a lot of context on how you were
>> suggesting this would work.
>>
>> - The code you put in your message-- were you suggesting that should
>> be added to the Undertow core as a built in handler or just a custom class
>> I would put in my project?
>> - Would this handler require the predicates be processed downstream
>> of the servlet initial handler in order to work? Because if so, that
>> appears to be a no-go since handlers like the rewrite only appear to work
>> upstream of the servlet
>> - Is it possible to register custom handlers of my own creation with
>> the predicate language or were you suggesting a handler that could only be
>> manually configured? I'm familiar with the handler builder pattern that
>> the built in handlers use, but I'm unclear on how builders get registered
>> with the predicate handler parser.
>> - Actually, I just reviewed the code again now and I see
>> the loadHandlerBuilders() method in the PredicatedhandlersParser class
>> appears to be scanning the classpath for builders. Interesting.... Does
>> Undertow need to be loaded by the same class loader that loaded my custom
>> handlers for this to work? I'm not super familiar with the ServiceLoader
>> stuff
>> - I'm not against building a custom handler that I ship alongside
>> Undertow that provides what I'm looking for, but I'm still interested
in
>> having the conversation of how we can improve undertow's core offering.
>>
>> Thanks!
>>
>> ~Brad
>>
>> *Developer Advocate*
>> *Ortus Solutions, Corp *
>>
>> E-mail: brad(a)coldbox.org
>> ColdBox Platform:
http://www.coldbox.org
>> Blog:
http://www.codersrevolution.com
>>
>>
>>
>> On Thu, Jul 2, 2020 at 7:01 PM Stuart Douglas <sdouglas(a)redhat.com>
>> wrote:
>>
>>> Hmm, this is because the servlet status code is only triggered by a
>>> sendError method, not by just setting the code.
>>>
>>> You probably need to write a custom one that looks like this (plus the
>>> relevant predicate languge bits):
>>>
>>> public class SendErrorHandler implements HttpHandler {
>>>
>>> private final int code;
>>>
>>> public SendErrorHandler(int code) {
>>> this.code = code;
>>> }
>>>
>>> @Override
>>> public void handleRequest(HttpServerExchange exchange) throws
>>> Exception {
>>> ServletRequestContext src =
>>> exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
>>> ((HttpServletResponse)src.getServletResponse()).sendError(code);
>>> }
>>> }
>>>
>>> Stuart
>>>
>>>
>>>
>>> On Fri, 3 Jul 2020 at 09:40, Brad Wood <bdw429s(a)gmail.com> wrote:
>>>
>>>> Thanks for the reply Stuart. I've tried this with no success, but
>>>> perhaps I'm doing it wrong.
>>>>
>>>> List<PredicatedHandler> ph =
>>>> PredicatedHandlersParser.parse(predicatesLines, _classLoader);
>>>> servletBuilder.addOuterHandlerChainWrapper(next ->
>>>> Handlers.predicates(ph,next));
>>>>
>>>> When the response-code handler fires, I still get no response body.
>>>>
>>>> On a related note, when I move the predicates into an outer handler
>>>> chain wrapper, my default response listener also doesn't fire at
all.
>>>>
>>>> On an unrelated train of thought, I've been trying to see if I can
get
>>>> the default response listener to automatically dispatch the correct
error
>>>> page, but that hasn't been going well either. If I don't use the
outer
>>>> handler chain idea, but try to capture the empty response in a default
>>>> response listener, I can return a static message using the Sender class
>>>>
>>>> Sender sender = exchange.getResponseSender();
>>>> sender.send(errorHTMLString);
>>>>
>>>> But if I try to run something this in my default response listener to
>>>> invoke my error pages
>>>>
>>>> ServletRequestContext src =
>>>> exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
>>>> HttpServletResponseImpl response = src.getOriginalResponse();
>>>> response.doErrorDispatch( exchange.getStatusCode(),
>>>> exchange.getReasonPhrase() );
>>>>
>>>> Then it's as though nothing happens and I still get an empty
response.
>>>>
>>>> Thanks!
>>>>
>>>> ~Brad
>>>>
>>>> *Developer Advocate*
>>>> *Ortus Solutions, Corp *
>>>>
>>>> E-mail: brad(a)coldbox.org
>>>> ColdBox Platform:
http://www.coldbox.org
>>>> Blog:
http://www.codersrevolution.com
>>>>
>>>>
>>>>
>>>> On Thu, Jul 2, 2020 at 6:17 PM Stuart Douglas
<sdouglas(a)redhat.com>
>>>> wrote:
>>>>
>>>>> The predicate languages are executed before the Servler handlers, so
>>>>> they won't be handled by Servlet error pages.
>>>>>
>>>>> If you are setting this all up programmatically you could use
>>>>> io.undertow.servlet.api.DeploymentInfo#addOuterHandlerChainWrapper to
setup
>>>>> the predicate handler after the initial servlet one, which should
mean that
>>>>> the servlet error handling will handle the response code.
>>>>>
>>>>> Stuart
>>>>>
>>>>> On Fri, 3 Jul 2020 at 08:25, Brad Wood <bdw429s(a)gmail.com>
wrote:
>>>>>
>>>>>> When I configure an error page similar to this:
>>>>>>
>>>>>> servletBuilder.addErrorPage( new ErrorPage( "404.html",
404));
>>>>>>
>>>>>> This works great when I hit a path in my browser that
doesn't
>>>>>> exist. The contents of the *404.html* file is served with a
>>>>>> response code of *404*.
>>>>>>
>>>>>> However, if I also use the predicate language to define
something
>>>>>> like:
>>>>>>
>>>>>> path(/box.json)->response-code(404)
>>>>>>
>>>>>> and then I hit *localhost/box.json* in my browser, I get a *404*
>>>>>> status code but with no response body.
>>>>>>
>>>>>> - The docs say the response-code handler ends the exchange,
but
>>>>>> should it still respect the error pages?
>>>>>> - How can I modify my use of Undertow to respect the error
pages
>>>>>> when using the response-code handler?
>>>>>> - I've seen in the docs the ability to have a
>>>>>> *addDefaultResponseListener()* but I'm not sure if it is
the
>>>>>> correct solution for this, nor how I would access the error
page
>>>>>> configuration dynamically as to not need to duplicate my
work.
>>>>>>
>>>>>> Thanks!
>>>>>>
>>>>>> ~Brad
>>>>>>
>>>>>> *Developer Advocate*
>>>>>> *Ortus Solutions, Corp *
>>>>>>
>>>>>> E-mail: brad(a)coldbox.org
>>>>>> ColdBox Platform:
http://www.coldbox.org
>>>>>> Blog:
http://www.codersrevolution.com
>>>>>>
>>>>>> _______________________________________________
>>>>>> undertow-dev mailing list
>>>>>> undertow-dev(a)lists.jboss.org
>>>>>>
https://lists.jboss.org/mailman/listinfo/undertow-dev
>>>>>
>>>>>