In my pull, I went with a predicate textual name of
set-error( 404 )
mostly because I used the Send Error Page handler name for the servlet
handler that actually looks for the status code.
Thanks!
~Brad
*Developer Advocate*
*Ortus Solutions, Corp *
E-mail: brad(a)coldbox.org
ColdBox Platform:
Forgot to reply to this:
add a 'continue' param to the response code handler,
I'm not against adding this, however I would be unlikely to use
responseCode( value=404, continue=true )
as I'd want to have a cleaner predicate language. I'd rather a new
handler be introduced like the custom
send-error-page( 404 )
one I've been testing with that is readable and clear what it does.
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 Tue, Jul 7, 2020 at 8:51 PM Brad Wood <bdw429s(a)gmail.com> wrote:
> Genius idea. In all my tests I hadn't thought of setting the response
> code in the predicate and then letting it continue to the servlet and
> caching it there. I just tested this and it does appear to work well.
>
> I added this outer handler chain wrapper to my deployment info
>
> deploymentInfo.addOuterHandlerChainWrapper(next -> new
> HttpHandler() {
> @Override
> public void handleRequest(HttpServerExchange exchange) throws
> Exception {
> if( exchange.getStatusCode() > 399 &&
> exchange.getResponseContentLength() == -1 ) {
> ServletRequestContext src =
> exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
>
> ((HttpServletResponse)src.getServletResponse()).sendError(exchange.getStatusCode());
> } else {
> next.handleRequest(exchange);
> }
> }
> });
>
> (I don't know if the exchange.getResponseContentLength() check is needed
> or the best way to do that)
>
> And then I registered a custom handler I called *send-error-page* that
> has this handleRequest method:
>
> public void handleRequest(final HttpServerExchange exchange) throws
> Exception {
> exchange.setStatusCode(responseCode);
> next.handleRequest(exchange);
> }
>
> Then this predicate rule
>
> path(/box.json)->send-error-page(404)
>
> serves up my servlet's custom error page for that request.
>
> 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 Tue, Jul 7, 2020 at 6:39 PM Stuart Douglas <sdouglas(a)redhat.com>
> wrote:
>
>> 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
>>>>>>>>
>>>>>>>>