Arvind N
Arvind N

Reputation: 241

Tomcat 8 URL Rewrite Issues

I have got the tomcat 8 rewrite to work but seems to missing something in rewrite.config that is causing the last condition to not execute. For benefit of others, i have the RewriteValve to work for my specific application and not globally. What works for me is given below.

In my app's META-INF context.xml file i have included below line

<Valve className="org.apache.catalina.valves.rewrite.RewriteValve" asyncSupported="true"/>

In my app's WEB-INF, i have a rewrite.config file that says below things after incorporating the feedback seen in the other tomcat 8 rewrite thread, regarding issue with using {REQUEST_FILENAME} being null. I have not used the REQUEST_FILENAME and my config looks like below.

RewriteCond %{REQUEST_URI} .*\.(css|js|html|png|jpg|jpeg|gif|txt|ico) [OR]
RewriteCond %{REQUEST_URI} ^\/api\/ [OR] 
RewriteRule ^(.*)$ - 

RewriteRule ^(.*)$ /index.html 

Now if URI is a js,css etc or if the URI starts with /api/ i see the rewrite rule is being evaluated and no substitution is being done. i.e below urls seem to work ok and no substitution is being done. localhost:8080/api/abc/xyz , localhost:8080/css/abc.min.css

But for some reason the last rule is not getting hit at all even when the URI has a valid one to get hit by it.For ex. URL like localhost:8080/def/ghi should have got redirected to index.html, but it seem to not getting rewritten. I am not sure what am i missing in the rewrite.config causing this behavior. I could move to a ! condition to do the rewrite too, but just want to get my understanding clear when i use Mulitple RewriteRule combination.

Any help is appreciated.

Upvotes: 12

Views: 14949

Answers (2)

mhvelplund
mhvelplund

Reputation: 2351

I found this question because I had a similar problem. I spent hours looking for a solution that didn't require me to whitelist specific file types. Eventually I decompiled org.apache.catalina.valves.rewrite.RewriteValve and found the answer.

My case is similar, but my Angular app is nested inside an older non-Angular app. That means that the URL to it someting like http://localhost:8080/mywebapp/ng/index.html (the app's base-href is thus "/mywebapp/ng").

I had no luck with rules using REQUEST_URI, REQUEST_FILENAME, or SCRIPT_FILENAME. What worked for me was SERVLET_PATH (no idea why).

I wound up with a solution including these two files:

/META-INF/context.xml:

<?xml version='1.0' encoding='utf-8'?>
<Context>
    <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
</Context>

/WEB-INF/rewrite.config:

RewriteCond %{SERVLET_PATH} !-f
RewriteRule ^/ng/(.*)$ /ng/index.html [L]

The result is that everything which is not a real file gets served by the Angular app.

Note: This worked on Tomcat 8.0 with an AoT compiled Angular2 (v4.0.0) app nested in an existing web-application.

Upvotes: 18

Arvind N
Arvind N

Reputation: 241

I seem to have got it fixed. There are couple of things i found and sharing it for others. The below thing worked finally for me. Below are the contents in rewrite.config. It should be placed in webapps//WEB-INF/ directory.

RewriteCond %{REQUEST_URI} .*\.(css|js|html|png|jpg|jpeg|gif|txt|ttf|json|woff|ico)$ [OR]
RewriteCond %{REQUEST_URI} ^(/api/).*$ [OR]
RewriteRule ^(.*)$ - [L]

RewriteRule ^(.*)$ /index.html 

There are a couple of things that were needed. The way i ensure my app is the default app is by adding below snippet in HOST configuration in server.xml. Please note that if you are using this approach to make your app the default app the valve adding should be done in the Context block in server.xml and it works and putting the same in your application/META-INF/context.xml does not seem to do the trick. It surely loads the configuration but rewrite does not happen. The PreResources thing kept in the application/META-INF/context.xml seems to work fine.

server.xml snippet

<Host name="localhost"  appBase="webapps"
            unpackWARs="false" autoDeploy="false" deployOnStartup="false">

        <Context path="" docBase="myapp" reloadable="false">
            <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" asyncSupported="true"/>
        </Context>  
        ....
</Host>

HTH, Thanks

Upvotes: 12

Related Questions