6

I am working on a Java web app hosted on a Tomcat server. I have to set up redirects from www to non-www and from http to https. I want the following three URLs:

to redirect to

For this purpose, I am using UrlRewriteFilter version 4.0.3 by tuckey.org. Here is my urlrewrite.xml file:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN" "http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd"> 
<urlrewrite> 
  <rule> 
    <name>Redirect www to non-www and http to https</name> 
    <condition type="request-url" operator="equal">(^http://example.com|^http://www.example.com|^https://www.example.com)</condition> 
    <from>^(.*)$</from> 
    <to type="permanent-redirect" last="true">https://example.com$1</to> 
  </rule> 
</urlrewrite> 

The redirects work but the website does not load and the browser shows message:

This page isn’t working
example.com redirected you too many times.

I used a redirect checker and found out that after the initial redirect to https://example.com/, another redirect to https://example.com/ followed and then another one and so on – the URL redirects to itself. I don't understand what produces this infinite loop. Any help would be appreciated!

Update: I have no solution yet. If I remove the first URL from the condition element, the other two redirects work and things are OK but the question is how to set up the redirect from http://example.com.

I tried another approach – setting up the redirect to https in the web.xml file by pasting the following code:

<security-constraint> 
  <web-resource-collection> 
    <web-resource-name>all</web-resource-name> 
    <url-pattern>/*</url-pattern> 
  </web-resource-collection> 
  <user-data-constraint> 
    <transport-guarantee>CONFIDENTIAL</transport-guarantee> 
  </user-data-constraint> 
</security-constraint> 

The result is the same – https://example.com redirects to itself in an infinite loop. The only difference in this case is that the redirects are with status code 302. Any ideas about what causes this problem and how to solve it?

Update: Here is the output of the curl command when using the UrlRewriteFilter:


Results from running: curl http://example.com

Response Header

HTTP/1.1 301 Moved Permanently   
Server: nginx admin   
Date: Fri, 04 May 2018 13:24:16 GMT   
Content-Type: text/plain   
Content-Length: 0   
Connection: keep-alive   
Location: https://example.com/   
X-Cache: HIT from Backend  

Results from running: curl https://example.com/

Response Header

HTTP/1.1 301 Moved Permanently   
Date: Fri, 04 May 2018 11:58:51 GMT   
Server: Apache-Coyote/1.1  
Location: https://example.com/   
Content-Length: 0   
Content-Type: text/plain

Hash
  • 4,647
  • 5
  • 21
  • 39
Rick77
  • 241
  • 3
  • 21
  • Can you set condition to (pseudoish): (ifNotStartsWith(https)|^https://www.example.com) Not sure of the syntax(regex?) here but anyways if the URL is not HTTPS you would always want to redirect, right? – Jokkeri Apr 30 '18 at 06:28
  • @Jokkeri Yes, I have already tried `^http$` and `^https$`. It doesn't work either. – Rick77 Apr 30 '18 at 08:37
  • Not sure if escaping will make any difference but try something like this: `^(http:\/\/example.com(.*)|http:\/\/www.example.com(.*)|https:\/\/www.example.com(.*))` – Jokkeri Apr 30 '18 at 09:33
  • 1
    See if this thread helps https://stackoverflow.com/questions/44953464/urlrewritefilter-www-and-https-redirect – Tarun Lalwani May 02 '18 at 16:21
  • 3
    @Rick77 Judging from your curl examples you have a nginx running. Is this correct? It might be a trickier to determine the scheme because nginx connects to Tomcat via plain HTTP - see [this answer](https://stackoverflow.com/a/19599143/7941889). This would explain why removing the first URL from your condition works fine (no rule for `example.com` anymore). Have a look at [another answer](https://stackoverflow.com/a/32090722/7941889) to the same question which might give you a hint how to apply a custom header you could use to determine the scheme. Or you could handle the redirect in nginx. – Franz Fellner May 05 '18 at 18:32
  • @FranzFellner Thanks for your comment, it is very useful. In my case the x-forwarded-proto header is not set and I don't have access to nginx on the production server. So I'll have to ask the hosting provider to do the setting. – Rick77 May 09 '18 at 12:23

3 Answers3

4

I would simplify the rule like below

<rule>
   <name>Ensure HTTPS</name>
   <condition type="scheme" operator="notequal" next="or">https</condition>
   <condition name="host" operator="notequal">www.example.com</condition>
   <from>^/(.*)$</from>
   <to type="redirect">https://example.com/$1</to>
</rule>

Also make sure the certificate is valid for example.com as well as pointed out in below thread

UrlRewriteFilter: www and https redirect

Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265
  • The rule looks better written in this way but this does not solve the problem. The certificate is valid for both example.com and www.example.com – Rick77 May 03 '18 at 08:48
  • Can you add the output of `curl -v https://example.com/` to your question? Also are connecting directly to server or anything other webserver in between? – Tarun Lalwani May 03 '18 at 08:49
1

My knowledge of curl might be a bit outdated, but I thought you have to do curl -L url to follow redirects.

Also, are you sure the issue is not with your client?

Abinash
  • 276
  • 1
  • 6
  • I don't have curl installed and I am using an online tool to run it. So the problem is not with my client. If I run `curl –L http://example.com` I get an error message (because of the infinite redirect loop I guess). – Rick77 May 08 '18 at 09:56
0

It seems, Response from https://example.com always has below headers:

Location: https.example.com
response Code: 301

It is browser's behavior to act on and redirect. You may need find a way to remove these headers. Hope this helps to some extent.