Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jetty-users] Embedded Jetty and Angular 6: only rewrite URLs that don`t match any servlet or files

ErrorPageErrorHandler errorPageMapper = new ErrorPageErrorHandler();
errorPageMapper.addErrorPage(404, "/myerror");
context.setErrorHandler(errorPageMapper);

context.addServlet(MyErrorServlet.class, "/myerror");

Now you can handle any 404 error with your custom MyErrorServlet.class

Pay attention to the DispatcherType, it should be ERROR.
Pay attention to the HttpServletRequest.getAttributes() that have meaning in this state.

and all of the ERROR_* constants.

Joakim Erdfelt / joakim@xxxxxxxxxxx


On Mon, Sep 10, 2018 at 4:59 PM Nicolas Therrien <nicolas.therrien@xxxxxxxxxxxxxxxxxxxxx> wrote:
Hi,

I want to add an Angular 6 application to an existing embedded Jetty web server (version 9.4.12.v20180830). I am having a problem getting client-side page routing to work properly.

For example:
Is a valid Angular route, but does not exist as a file.
I can navigate to it either via a link on the home page  (index.html) or by typing: http://localhost:8080/#/mypage in my browser.

If I type http://localhost:8080/mypage,  I get a 404.

That is because for client-side routing feature to work properly, HTML 5 PushState must be supported. From my understanding, what this means is that the server must rewrite URLs so that they reach the angular page on /index.html. Using the above example, "/mypage" would have to be rewritten to "/index.html" with an original path attribute set to the requested path.

Here is are links to Angular documentation: 

I've been working at it for a few days and am stuck. I have found how to do url rewriting with Jetty, using a RewriteHandler. The rewriting works, but is affecting all URLs, including valid ones. This causes script files and images to be replaced with contents of index.html.

I need URLs associated with other servlets (such as websocket servlets and rest apis) to be left untouched, and I need URLs for real files (such as images and other angular assets) to be left untouched.

I have been looking for something in the like of Ngnx:
try_files $uri $uri/ /index.html; 

Which translates into "try the URI as-is, if that doesn`t work, treat the URI as a folder, if that doesnt work then use index.html"

So I tried this with Jetty:

// Create the web app context
WebAppContext context = new WebAppContext();
context.setContextPath("/");
context.setWelcomeFiles(new String[] {"index.html"});
String resLocation = WebServer.class.getResource("/webapp").toString();
context.setResourceBase(resLocation);

// Enable URL Rewriting to support HTML 5 PushState
RewriteHandler rewrite = new RewriteHandler();
rewrite.setRewriteRequestURI(true);
rewrite.setRewritePathInfo(false);
rewrite.setOriginalPathAttribute("requestedPath");

RewriteRegexRule html5pushState = new RewriteRegexRule();
html5pushState.setRegex("/.*");
html5pushState.setReplacement("/index.html");
rewrite.addRule(html5pushState);

// Handler Structure
HandlerList handlers = new HandlerList();
rewrite.setHandler(context);
handlers.setHandlers(new Handler[] { context, rewrite}); 
server.setHandler(handlers);


I was hoping this would do the trick. My rationale was that using a HandlerList would cause Jetty to call each handler in the list in the order specified until a response is matched.  Calling context first would lookup all the existing webapps for a file or servlet.  Then calling rewrite would rewrite the URL and then because context is also a child of rewrite I was hoping this would cause Jetty to try again using the rewritten URL, in which case would be index.html.

Unfortunately, It doesn`t work because "context" returns a 404 to the client directly. The rewrite handler is never called.


I've been looking for Conditional statements in Jetty and couldn`t find any. In fact, I was able to do this kind of conditional rewrite with Tomcat using a RewriteValve:
ctx.addValve(new RewriteValve());

and a text file (rewrite.config):

RewriteCond %{REQUEST_URI} -f
RewriteRule ^(.*)$ - [L]

RewriteRule ^(.*)$ /index.html


Notice how the rewrite rule is conditional.   The rewrite occurs only if the URL cannot be matched to a file.



How can this kind of conditional rewriting be done under Jetty?

If a custom handler must be written, how would you guys query the server to figure out if a given path matches a servlet or a file?

Your help would be very much appreciated.

Nicolas Therrien

Senior Software Developer

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

o: +1.819.931.2053  

_______________________________________________
jetty-users mailing list
jetty-users@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/jetty-users

Back to the top