I'm building a project using Spring Boot and Angular 1.5.X and I am struggling to handle full page refreshes of Angular routes - typical "404 because the path I made doesn't actually exist" problem. I've done a fair bit of research and the solution that I keep seeing is to implement a .htaccess file with the following snippet in order to redirect all unknown requests back to the index (I pulled the following from this post)
RewriteEngine On
Options FollowSymLinks
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /#/$1 [L]
I have Tuckey's UrlRewriteFilter installed - according to this blog post since I don't have a WEB-INF folder - and it is working. It starts and it reads the urlrewrite.xml successfully. However, I don't know what to put in my urlrewrite.xml - I haven't the slightest clue of how to translate the above into something that the UrlRewriteFilter can understand. I've browsed the manual for the UrlRewriteFilter and I don't really know where / how to start.
Basically, what do I have to put in my urlrewrite.xml so that if I hit F5, my website doesn't puke back 404 errors?
Any help is appreciated.
Edit 1
I should mention that all of my API endpoints are prefaced with /api/**
in order to distinguish them from links on my front end - an example would be /api/open/getUser
and /api/secured/updateSettings
.
Edit 2
Couple things I've discovered so far. One is that the UrlRewriteFilter can actually support .htaccess files and I did get it (as far as I can tell) to load in by moving the .htacess into my Resources folder and tweaking the code sample in the above blog post slightly, changing this
private static final String CONFIG_LOCATION = "classpath:/urlrewrite.xml";
to
private static final String CONFIG_LOCATION = "classpath:/.htaccess";
and
Conf conf = new Conf(filterConfig.getServletContext(), resource.getInputStream(), resource.getFilename(), "MyProject");
to
Conf conf = new Conf(filterConfig.getServletContext(), resource.getInputStream(), resource.getFilename(), "MyProject", true);
The addition of the true
tells the filter to use a .htaccess file. Awesome, problem solved right? Not quite - it's hard to explain but it doesn't seem like the UrlRewriteFilter was/is reading the .htacess correctly. I was using an .htacess tester to verify that the regex's and rewrite conditions were working as I expected and they seemed to be. The tester said that they were fine. However, the UrlRewriteFilter would freak out and get stuck in some kind of loop, to the point that Java would throw a stack overflow exception (as to why, I've no idea - I can't seem to find a way to set the filter's logging level to debug via Java D:< ).
So clearly that didn't work - I am currently attempting to translate the .htaccess into urlrewrite.xml myself, and here is what I've managed to created so far.
<urlrewrite use-query-string="true">
<rule match-type="regex" enabled="true">
<note>
Any URI that ends with one of the following extensions will be allowed to continue on unimpeded.
Buried in the manual was the single line that said a "-" in the "to" will allow the request to
continue on unmodified.
</note>
<from>\.(html|css|jpeg|gif|png|js|ico|txt|pdf)$</from>
<to last="true">-</to>
</rule>
<rule match-type="regex" enabled="true">
<note>
Any URI that is prefaced with "/api/open/**" or "/api/secured/**" will be allowed through unmodified.
</note>
<condition type="request-uri" operator="equal">\/api\/(open|secured)\/([a-zA-Z0-9\/]+)</condition>
<from>^.*$</from>
<to last="true">-</to>
</rule>
<rule match-type="regex" enabled="false">
<note>
This one is supposed to be a "when all else fail" rule - if the other two rules don't match,
forward to the index and let Angular figure out the rest.
!! This one seems to be getting stuck in a loop of sorts !!
</note>
<from>^.*$</from>
<to last="true">/</to>
</rule>
</urlrewrite>
The first two seem to be working splendidly. The third rule (the one with enabled set to false for good reason) does not - it also appears to getting stuck in the same filter loop (or whatever is happening - the stack trace is so big that Intellij is like "nah man") as the .htacess method. Making progress.