Re: Embedded Jetty and Angular 6: only rewrite URLs that don`t match any servlet or files

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: Embedded Jetty and Angular 6: only rewrite URLs that don`t match any servlet or files

PETER CURRIVAN

Nicolas Therrien et al.,

 

Thank you for sharing your custom RewriteHandler for use with Angular 6 routing.  I am having trouble using it, however, because I am using XML configuration (non-embedded Jetty).  My problem is I do not know how to access a reference to the WebAppContext in my jetty-rewrite.xml file.  Whereas you have instantiated the WebAppContext and the Html5PushStateConditionalRewriteHandler in a single Java file, and can simply pass the reference, I am seemingly forced to configure these objects in separate Jetty IoC XML files (jetty-web.xml configures the WebAppContext and jett-rewrite.xml configures the Html5PushStateConditionalRewriteHandler).

 

Do you (or anyone else reading this) know a way I might access a reference to the WebAppContext configured in jetty-web.xml from within jetty-rewrite.xml?  Or perhaps another way to access the “mappedServlet” within the custom RewriteHandler?

 

I tried adding an id to the WebAppContext in jetty-web.xml and using a Ref tag in jetty-rewrite.xml but the reference comes back null.

 

jetty-web.xml:

<Configure id="webAppContext" class="org.eclipse.jetty.webapp.WebAppContext">

 

jetty-rewrite.xml:

<Configure id="Server" class="org.eclipse.jetty.server.Server">

  <Call name="insertHandler">

    <Arg>

      <New class="my.package.Html5PushStateConditionalRewriteHandler">

        <Arg name="webAppContext"><Ref refid="webAppContext"/></Arg>

 

Thanks,

Peter Currivan


_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: Embedded Jetty and Angular 6: only rewrite URLs that don`t match any servlet or files

Joakim Erdfelt-8
"rewrite URLs that don`t match any servlet or files"

Why not just have a Error handler on status code 404 instead?
This is the easiest approach.
Make it return whatever you want, rewrite it, etc...

Alternatively, if you don't rely on welcome files, you could map your welcome files to a servlet name.
That way it runs if the incoming path doesn't match a servlet, and not a directly mentioned static file name.
Make your servlet do what you need.

Option 3 is to provide your own DefaultServlet behavior (mapped to `<url-pattern>/</url-pattern>`.
Lets call this MyDefaultServlet.
If you get called, then you'll know that you have matched no Servlets.
Then it's just a matter of returning the static file (if it exists), or rewriting the URL it that doesn't match.
Check out the code for DefaultServlet, you'll essentially want to have a different doGet()

protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException
    {
        if(!_resourceService.doGet(request,response))
        {
            // didn't serve a static file, do your special logic here.
            response.sendRedirect("/other/path/that/I/want/to/rewrite/to");
         }
    }




Joakim Erdfelt / [hidden email]


On Fri, Nov 30, 2018 at 12:49 PM PETER CURRIVAN <[hidden email]> wrote:

Nicolas Therrien et al.,

 

Thank you for sharing your custom RewriteHandler for use with Angular 6 routing.  I am having trouble using it, however, because I am using XML configuration (non-embedded Jetty).  My problem is I do not know how to access a reference to the WebAppContext in my jetty-rewrite.xml file.  Whereas you have instantiated the WebAppContext and the Html5PushStateConditionalRewriteHandler in a single Java file, and can simply pass the reference, I am seemingly forced to configure these objects in separate Jetty IoC XML files (jetty-web.xml configures the WebAppContext and jett-rewrite.xml configures the Html5PushStateConditionalRewriteHandler).

 

Do you (or anyone else reading this) know a way I might access a reference to the WebAppContext configured in jetty-web.xml from within jetty-rewrite.xml?  Or perhaps another way to access the “mappedServlet” within the custom RewriteHandler?

 

I tried adding an id to the WebAppContext in jetty-web.xml and using a Ref tag in jetty-rewrite.xml but the reference comes back null.

 

jetty-web.xml:

<Configure id="webAppContext" class="org.eclipse.jetty.webapp.WebAppContext">

 

jetty-rewrite.xml:

<Configure id="Server" class="org.eclipse.jetty.server.Server">

  <Call name="insertHandler">

    <Arg>

      <New class="my.package.Html5PushStateConditionalRewriteHandler">

        <Arg name="webAppContext"><Ref refid="webAppContext"/></Arg>

 

Thanks,

Peter Currivan

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: Embedded Jetty and Angular 6: only rewrite URLs that don`t match any servlet or files

Nicolas Therrien
In reply to this post by PETER CURRIVAN
Hi Peter,

Glad you found this example useful as to how HTML5 pushstate can be achieved with Jetty. The XML version is quite different as you can see and, unfortunately, I don`t have as much experience with it. I was using Tomcat + XML before we switched to microservices and Embedded Jetty. I never really used XML configuration with Jetty.

I still gave a look at the snippet you included and if passing arguments to a handler is in fact allowed, then I think you may be on the right path. Perhaps someone on this list knows what to do in order to get a reference to the context.

An alternative to using parameters would be to use annotations directly in the handler class. I assume that your backend is already using annotations for your servlets etc. Perhaps its possible that Jetty will scan for annotations in rewrite handlers as well? I am really not sure about this, just trying to give you another possibility to look at.

If you're stuck and must use XML descriptors but are flexible on the JEE implementation, I know that Tomcat has a better URL rewriting method. It uses the same rewrite format as Nginx which allows conditional statements. You could easily do a prototype to verify this and then make the switch if it proves useful. Here's a link to the page showing that conditional rewrite is supported on Tomcat:

The following has nothing to do with your question, just a bit of a thought at a macro scale. Can your app be converted to a microservice?  I personally have had a much better experience since I moved away from the application server model. I find myself with more options and more flexibility when it comes to keeping up with ever changing technology trends. 

Should I had failed to find the rewriting solution I shared previously, I would have decoupled my web ui from my backend and moved forward as follows:

1) host the angular application on nginx and let the javascript client connect to the backend through REST APIs or websocket only. 
2) host backend on standard JEE container with only a clean cut API to worry about. No server pages. Easy to test the API and increase code coverage.

I've seen this model in use and it works quite well. Nginx is excellent at hosting frontend apps.  JEE is excellent at hosting backend apps. Best of both worlds and scalable too.

That being said, I hope you'll find a solution and please share it with us if you find one!  I'd be interested in knowing how it can be done via XML.

Cheers,

Nicolas Therrien

Senior Software Developer

https://www.motorolasolutions.com/content/dam/msi/images/logos/corporate/msiemailsignature.png

o: +1.819.931.2053  



On Fri, Nov 30, 2018 at 1:49 PM PETER CURRIVAN <[hidden email]> wrote:

Nicolas Therrien et al.,

 

Thank you for sharing your custom RewriteHandler for use with Angular 6 routing.  I am having trouble using it, however, because I am using XML configuration (non-embedded Jetty).  My problem is I do not know how to access a reference to the WebAppContext in my jetty-rewrite.xml file.  Whereas you have instantiated the WebAppContext and the Html5PushStateConditionalRewriteHandler in a single Java file, and can simply pass the reference, I am seemingly forced to configure these objects in separate Jetty IoC XML files (jetty-web.xml configures the WebAppContext and jett-rewrite.xml configures the Html5PushStateConditionalRewriteHandler).

 

Do you (or anyone else reading this) know a way I might access a reference to the WebAppContext configured in jetty-web.xml from within jetty-rewrite.xml?  Or perhaps another way to access the “mappedServlet” within the custom RewriteHandler?

 

I tried adding an id to the WebAppContext in jetty-web.xml and using a Ref tag in jetty-rewrite.xml but the reference comes back null.

 

jetty-web.xml:

<Configure id="webAppContext" class="org.eclipse.jetty.webapp.WebAppContext">

 

jetty-rewrite.xml:

<Configure id="Server" class="org.eclipse.jetty.server.Server">

  <Call name="insertHandler">

    <Arg>

      <New class="my.package.Html5PushStateConditionalRewriteHandler">

        <Arg name="webAppContext"><Ref refid="webAppContext"/></Arg>

 

Thanks,

Peter Currivan

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://urldefense.proofpoint.com/v2/url?u=https-3A__www.eclipse.org_mailman_listinfo_jetty-2Dusers&d=DwICAg&c=q3cDpHe1hF8lXU5EFjNM_A&r=P3_1pTtMQK06fFymYIWbyyzVU6nc0CcwfuZhLhexammvaiCaU0ieHeI7BWvfbbjE&m=Whwhzf2Dpi3RaUUDZwzWF0VV3CKHexK0i9qITo3-yIA&s=yg8hFh1RvW761mam8bB5sHTgAr7WOZp_c7aEwsedDvE&e=

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
Reply | Threaded
Open this post in threaded view
|

Re: Embedded Jetty and Angular 6: only rewrite URLs that don`t match any servlet or files

Nicolas Therrien
In reply to this post by Joakim Erdfelt-8
Hi Joakim,

Those are interesting workarounds. I haven't tried the DefaultServlet idea, but I remember you had suggested using the error handler back when i first asked about pushstate in the original thread. I tried several techniques but it didn`t work for me. I actually lost a lot of time trying to find a way to make one that would work. Here's what I had tried:

Note: i used parentheses below to indicate whether or not handlers are set inside the webapp context or chained together at a higher level. The main webapp context has its own error handler built in.

(WebAppContext -> Servlet -> CustomErrorHandler -> ErrorHandlingServlet)
This was your suggestion. I couldn't get it to work because I couldn't figure out how to get the error handling servlet to return the index.html along with the appropriate parameter. Perhaps if you gave us an example as to how to return the index.html file with parameters?   This could work in theory.

Rewrite Handler -> (WebAppContext -> Servlet -> DefaultErrorHandler)
This didn't work because we can't do conditional handling in the rewriter. Images and servlet would all return the contents of index.html.  There is no support for conditional rewriting on Jetty.

(WebAppContext -> Servlet -> DefaultErrorHandler) -> RewriteHandler -> WebAppContext...
While this would fix my earlier problem of not being able to feed the rewritten path in the file server, this didn't work because the error handler would stop the chain.

(WebAppContext -> Servlet -> null error handler) -> RewriteHandler -> WebAppContext...
This didn't work because the Default error handler would still stop the chain. If error handler is null, the code for WebAppContext instantiates a DefaultErrorHandler automatically. 

(WebAppContext -> Servlet ->  CustomPassthroughErrorHandler ) -> RewriteHandler -> WebAppContext...  
In this attempt, i created a custom error handler which would ignore errors and let them trough so the chain can keep going. Jetty has a loop detection thing that prevents feeding the path back into the same context.

(WebAppContext with no welcome page -> Servlet -> CustomPassthroughErrorHandler) -> Rewrite Handler -> CustomAngularContext... 
In this attempt, I was trying to separate Servlet contexts from File contexts so that Jetty would no longer view this as a loop. I think at that point I felt this was becoming ridiculous so I decided to write the conditional rewrite handler. I felt a conditional rewriter was not only simpler but also a better design because it does what it is meant to do.

By the way, in retrospective, I think the fact that the webapp context automatically instantiates a default error handler if the handler is null, that could be a design issue... 


Seems like searches to fix this kind of problems on Java servers is trending. I ran a new search today, and I found this new example example for JBoss Wildfly server which also performs rewriting. Interestingly enough, they too have support for conditional rewriting, see the xml section which checks that the requested resource is neither a real file or servlet path:

On Fri, Nov 30, 2018 at 2:40 PM Joakim Erdfelt <[hidden email]> wrote:
"rewrite URLs that don`t match any servlet or files"

Why not just have a Error handler on status code 404 instead?
This is the easiest approach.
Make it return whatever you want, rewrite it, etc...

Alternatively, if you don't rely on welcome files, you could map your welcome files to a servlet name.
That way it runs if the incoming path doesn't match a servlet, and not a directly mentioned static file name.
Make your servlet do what you need.

Option 3 is to provide your own DefaultServlet behavior (mapped to `<url-pattern>/</url-pattern>`.
Lets call this MyDefaultServlet.
If you get called, then you'll know that you have matched no Servlets.
Then it's just a matter of returning the static file (if it exists), or rewriting the URL it that doesn't match.
Check out the code for DefaultServlet, you'll essentially want to have a different doGet()

protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException
    {
        if(!_resourceService.doGet(request,response))
        {
            // didn't serve a static file, do your special logic here.
            response.sendRedirect("/other/path/that/I/want/to/rewrite/to");
         }
    }




Joakim Erdfelt / [hidden email]


On Fri, Nov 30, 2018 at 12:49 PM PETER CURRIVAN <[hidden email]> wrote:

Nicolas Therrien et al.,

 

Thank you for sharing your custom RewriteHandler for use with Angular 6 routing.  I am having trouble using it, however, because I am using XML configuration (non-embedded Jetty).  My problem is I do not know how to access a reference to the WebAppContext in my jetty-rewrite.xml file.  Whereas you have instantiated the WebAppContext and the Html5PushStateConditionalRewriteHandler in a single Java file, and can simply pass the reference, I am seemingly forced to configure these objects in separate Jetty IoC XML files (jetty-web.xml configures the WebAppContext and jett-rewrite.xml configures the Html5PushStateConditionalRewriteHandler).

 

Do you (or anyone else reading this) know a way I might access a reference to the WebAppContext configured in jetty-web.xml from within jetty-rewrite.xml?  Or perhaps another way to access the “mappedServlet” within the custom RewriteHandler?

 

I tried adding an id to the WebAppContext in jetty-web.xml and using a Ref tag in jetty-rewrite.xml but the reference comes back null.

 

jetty-web.xml:

<Configure id="webAppContext" class="org.eclipse.jetty.webapp.WebAppContext">

 

jetty-rewrite.xml:

<Configure id="Server" class="org.eclipse.jetty.server.Server">

  <Call name="insertHandler">

    <Arg>

      <New class="my.package.Html5PushStateConditionalRewriteHandler">

        <Arg name="webAppContext"><Ref refid="webAppContext"/></Arg>

 

Thanks,

Peter Currivan

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users
_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://urldefense.proofpoint.com/v2/url?u=https-3A__www.eclipse.org_mailman_listinfo_jetty-2Dusers&d=DwICAg&c=q3cDpHe1hF8lXU5EFjNM_A&r=P3_1pTtMQK06fFymYIWbyyzVU6nc0CcwfuZhLhexammvaiCaU0ieHeI7BWvfbbjE&m=8a8S9CvgexbMN-nlNHHhSLKVeBwDHVUoicIYnYp94o4&s=cvfmhyimKnCzxfDd7CU8RsY9A_ieVbWEgwoqMyTdmcQ&e=

_______________________________________________
jetty-users mailing list
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jetty-users