CFML/ColdFusion · Railo · Server · Tomcat

Tuckey URLRewrite How-To


Today I will walk through how to put into practice use the Tuckey URL Rewrite java web filter under an Apache Tomcat web server.

URL rewriting is the method of converting complex URL parameters into more human readable format to allow more simple and memorable URLs. This can be an important function if you start using frameworks or content management systems which automatically generate long and at times cryptic URLs. While URL rewrite on the more popular Apache HTTP Server is relatively easy to set up using the default mod_rewrite module, reproducing this functionality on Tomcat requires a little more work.

Standard URL: http://www.example.com/list.cfm?product=fruit&page=1&order=asc&perpage=30
Rewrite URL: http://www.example.com/list/fruit/asc/30/1

The GitHub repository of the XML entries used in this article https://github.com/bengarrett/devtidbits/tree/master/post_635.

Installation

URLRewrite can be found from one of 2 sources. The official website at http://www.tuckey.org/urlrewrite/ the developer’s repository at Google Code http://code.google.com/p/urlrewritefilter/downloads/list.

Extracting the downloaded URLRewrite archive reveals a single WEB-INF folder which contains a lib folder and the file urlrewrite.xml. Both these items will need to be copied to the WEB-INF folder of your Tomcat server root directory. For example if example.com was located in /var/www/www.example.com or c:\www\www.example.com the lib folder and urlrewrite.xml would go in /var/www/www.example.com/WEB-INF/ or c:\www\www.example.com\WEB-INF.

Content of Tuckey URLRewrite 4.0’s archive
Content of WEB-INF with URLRewrite
Content Of A Clean WEB.XML

Generally for most default installations of Tomcat the WEB-INF folder will only contain the single file web.xml. We will need to edit web.xml using a text editor to enable URLRewrite on Tomcat but because it is an XML text file. It can be machined parsed so I’d recommend editing it using a source code text editor such as NotePad++ on Windows or Textmate on OS/X.

Add the following code to web.xml anywhere contained within the <web-app></web-app> tags.

<!-- URL ReWriter -->
<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    <!-- set the amount of seconds the conf file will be checked for reload
    can be a valid integer (0 denotes check every time,
    empty/not set denotes no reload check) -->
    <init-param>
        <param-name>confReloadCheckInterval</param-name>
        <param-value>0</param-value>
    </init-param>
    <!-- you can disable status page if desired
    can be: true, false (default true) -->
    <init-param>
        <param-name>statusEnabled</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>logLevel</param-name>
        <param-value>DEBUG</param-value>
    </init-param>
    <init-param>
        <param-name>statusEnabledOnHosts</param-name>
        <param-value>localhost</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>
Edited WEB.XML

Let’s quickly go through these settings.

confReloadCheckInterval is a numeric value in seconds that tells how frequently URLRewrite should check your urlrewrite.xml rules for any changes. Normally with Tomcat the modification of an XML configuration file requires a restart before the changes are reflected. You can set this value to -1 to disable automatic checking, while our value of 0 will mean that URLRewrite will check the urlrewrite.xml on every HTTP request. It is a great setting while testing and developing but a resource waste if used on a production server.

statusEnabled is a Boolean value that enables a URLRewrite status page that is reachable via a web browser at http://www.example.com/rewrite-status. It is probably best to disable this feature on production servers.

logLevel sets how much logging should be produced by URLRewrite. While the default setting is INFO, I suggest using DEBUG while you are testing. Through in a production environment you will probably want to use ERROR or FATAL to limit logging as URLRewrite can generate some large log files very quickly with more verbose log settings.

statusEnabledOnHosts allows you set which IP addresses and hosts that have access to the URLRewrite status page previously mentioned.

Finally the <filer-mapping> tag tells what kinds of methods to pass through via URLRewrite. The tags <url-pattern></url-pattern> should be left as is to apply URLRewrite to the whole site. While the 2 <dispatcher></dispatcher> tags mean that URLRewrite should be used for all HTTP REQUESTS and HTTP internal FORWARDing.

Once done, save your web.xml file and restart your Tomcat server. If all goes well you should be able to point your browser to http://www.example.com/rewrite-status and an UrlRewriteFilter 3.2.0 build 1 configuration overview should be shown. Yes that 3.2 version number is incorrectly listed in 4.0. Point your browser to http://www.example.com/test/status/ and you should be automatically forwarded to /rewrite-status. When this works then congratulations as you now have URLRewrite enabled on your server. Now I will give you some helpful example rules that may come in use. These rules all go in-between the <urlrewrite></urlrewrite> tags located in the urlrewrite.xml file within the WEB-INF folder. Whenever a page is requested on your Tomcat server the URLRewrite application will in a sequential order process ALL the rules contained in the urlrewrite.xml.

Pretty URL, SES Friendly URL Pass-Through

The most common use of URLRewrite would probably be to enable a 3rd party framework or CMS to use pretty URLs. The rule below is a generic setup that could be adapted for many uses. Generally speaking this should always be the LAST rule listed in your urlrewrite.xml rule set. The rule passes all URL requests to the index.cfm file except requests with URLs pointing to files or folders listed in the <condition></condition> tag regular expression value. So with this rule the URL http://www.example.com/list/apples would be displayed as is in the user’s browser but URLRewrite will actually pass http://www.example.com/index.cfm/list/apples to the Tomcat server. You do want to make sure that the page that contained within the <to></to> tag value is also listed in the (not equal) <condition></condition> value otherwise you could run into an infinite loop.

<rule enabled="true">
    <name>Generic Pretty URLs Pass-through</name>
    <condition type="request-uri" operator="notequal">^/(index.cfm|robots.txt|osd.xml|flex2gateway|cfide|cfformgateway|railo-context|admin-context|files|images|jrunscripts|javascripts|miscellaneous|stylesheets)</condition>
    <from>^/(.*)$</from>
    <to type="passthrough">/index.cfm/$1</to>
</rule>

Permanent Redirection

This rule is specifically for when you want to do a permanent redirection using the HTTP code 301. If we break this rule down, the <rule enable=""> Boolean enables you to selectively turn off this rule without the need to comment it out. The <name></name> tags contains the label you wish to use to describe the rule. <from></from> tag contains a regular expression to forward all requests for the documents.cfm page plus any URL parameters. While <to></to> is the new URL to redirect to. The attribute type tells URLRewrite to send a permanent direct code to the browser requesting the URL, while the attribute last = true tells URLRewrite not to process any further rules for this page request.

<rule enabled="true">
    <name>Permanent redirect example</name>
    <from>^/documents.html(.*)$</from>
    <to type="permanent-redirect" last="true">/file/list/document</to>
</rule>

Selective HTTPS Enforcement

If you have HTTPS setup on your server you can use URLRewrite to enforce certain folders, URL paths or files to only be served on an encrypted HTTPS protocol. The <condition></condition> tag is used to enforce additional policies as to when the rule should be implemented. The attribute type with a value of scheme and the attribute operator with a value of equal states that when the URL scheme (http, https, ftp, etc) is equal to HTTP then apply this rule.

<rule enabled="false">
    <name>Force HTTPS example</name>
    <note>Automatically redirects adminstration requests to a secure protocol.</note>
    <condition type="scheme" operator="equal">^http$</condition>
    <from>^/CFIDE/administrator/(.*)$</from>
    <to type="permanent-redirect" last="true">https://www.example.com/CFIDE/administrator/$1</to>
</rule>

Railo HTTPS Enforcement railo-content.

<rule enabled="false">
    <name>Force HTTPS example</name>
    <note>Automatically redirects adminstration requests to a secure protocol.</note>
    <condition type="scheme" operator="equal">^http$</condition>
    <from>^/railo-context/admin/(index|web|server).cfm$</from>
    <to type="permanent-redirect" last="true">https://www.example.com/railo-context/admin/$1.cfm</to>
</rule>

Conditions Based On URL Parameters

You can also apply conditions to user supplied URL parameters. In the example below the condition looks for the URL parameter named fruit and sees if its value is either kiwi, apple or orange. If the values match then it redirects to a replacement URL which also incorporates the parameter. The URL request http://www.example.com/list.html?fruit=apple would forward to http://www.example.com/list/fruit/apple.

<rule enabled="true">
    <name>Selective fruit example redirect</name>
    <condition type="parameter" name="fruit" operator="equal">(apple|kiwi|orange)</condition>
    <from>^/list.html(.*)$</from>
    <to type="permanent-redirect" last="true">list/fruit/%{parameter:fruit}</to>
</rule>

Extra Help

Advertisements

39 thoughts on “Tuckey URLRewrite How-To

  1. Thanks for the example. I get it to work under Linux, but under Windows 7 it does not work (either tomcat 5.5 and 6.0 and urlrewrite 3.2 and 4.0).
    Has anybody running urlrewrite under a Windows System and some tips for me?

    Best,

    Daniel

    1. This example was created and the screen shots were taken from a clean Tomcat 7 install for Windows 7 64-bit. Have you tried installing URLRewrite to a clean Tomcat installation instead of installing to an existing installation? Also have you checked the logs in your Tomcat installation directory? At the moment you really don’t provide enough information for people to help to troubleshoot.

  2. Thanks for the great post. I’m using tuckey’s urlrewrite filter in my project. I did some basic rewriting and it works great.

    Well, I want to change the url e.g. “www.mydomain.com/blog” to “blog.mydomain.com”.

    What is the correct rule for this situation?

    Thanks…

    1. Sorry for the late response.

      You would follow the much the same steps as the example under ‘Permanent Redirection’ as the 301 HTTPD status code is very important for search engines as Google. I haven’t tested this code but it should work.


      <rule enabled="true">
      <name>Permanent blog example</name>
      <condition name="host" operator="equal">www.mydomain.com</condition>
      <from>^/blog/(.*)$</from>
      <to type="permanent-redirect" last="true">http://blog.mydomain.com/$1</to>
      </rule>

  3. Hi,

    I’m a newbie to tomcat. I’ve installed tomcat on my unix system using the tar.gz distribution. I want to redirect request to one(let’s say XYZ) of my apis to other(let’s say ABC). So the request http://localhost:8080/XYZ/select?a=b should get redirected to http://localhost:8080/ABC/select?a=b.
    I placed the urlrewrite-4.0.0.jar inside pathToTomcatExtractionFolder/lib folder

    I edited the web.xml file present inside pathToTomcatExtractionFolder/conf/web.xml and added :

    UrlRewriteFilter
    org.tuckey.web.filters.urlrewrite.UrlRewriteFilter

    logLevel
    WARN

    UrlRewriteFilter
    /*

    I’ve placed urlrewrite.xml inside pathToTomcatExtractionFolder/conf/. and defined this rule inside it:

    /XYZ/select?(.*)
    /ABC/select?$1

    After this I restarted the tomcat but even then when I call http://localhost:8080/XYZ/select?a=b in my browser, it’s not getting redirected.

    Thanks in advance,
    Suryansh

      1. Hi,
        again thnx for the help.

        I’ve figured out the folder where I need to place this file and the redirection is also working, but I’m facing a problem that http://localhost:8080/XYZ/select?a=b is being redirected to http://localhost:8080/ABC/select? and not to http://localhost:8080/ABC/select?a=b. SO there must be some problem in the rule I’ve defined and I’m not able to figure this out.

        Again my rule is,

        from /XYZ/select?(.*) /from
        to type=”redirect” /ABC/select?$1 /to

    1. <rule>
      <from>^/some/olddir/(.*)$</from>
      <to type="redirect">/very/newdir/$1</to>
      </rule>

      <from>^/XYZ/select?(.*)$</from>
      <to type=”redirect”>/ABC/select?$1</to>

    2. I suggest re-reading the instructions carefully on the Tuckey website and starting again from scratch. You must be missing some critical setting that you are not listing here. Sorry I can not be of more help.

  4. Hi again Ben,

    The urlrewritefilter and my custom Authentication Filter don’t work together. I’m trying to redirect all the requests to login page if there is no session attribute. The urlrewrite filter ignores the authentication filter. What could be the problem?
    I’m using (/*) url pattern in my filter.

    Thanks.

  5. Hello! Trying to wrap my head around URL rewriting. Is there a simple rule for making URLs case insensitive? Trying to get around Tomcat’s case sensitive URLs to allow user’s typos to land at the correct page instead of 404. Thanks!!!

    1. Hi Philip sorry for the slow reply. Tomcat 6 and earlier has a setting to turn off caseSensitivity but it has been removed in Tomcat 7.

      http://tomcat.apache.org/tomcat-6.0-doc/config/context.html#Standard_Implementation

      Tuckey would allow to ignore case sensitivity as the [from] element has a casesensitive attribute that is by default set to off. Maybe something as simple as the following may work?

      (replace the square brackets with pointy brackets)

      [rule]
      [from]$1[/from]
      [to]$1[/to]
      [/rule]

  6. Hi Ben,
    I’m new to all this Url rewriting thing. I’m developing a dynamic web app in java using Eclipse Juno.

    Can u plz tell me where to put the URLREWRITEFILTER’s .xml files , in the Tomcat directory or in my project’s directory in Eclipse?
    And one more thing, can u plz give me a very small exmp as how can i get the URL of “index.jsp”
    http://localhost:8080/MyProject/index.jsp

    which is in my root directory be displayed as …..

    http://localhost:8080/MyProject/filter/page

    Thanks in advance…….

    1. Hi Rahul,

      It’s best you read the install instructions on the Tuckey Rewrite website. http://tuckey.org/urlrewrite/

      But the XML files go in your server’s WEB-INF directory. Where that is located is usually the web root but that isn’t always the case and can depend on your individual setup.

      I think what rules you are looking for can be found under URL Abstraction in the manual.

      http://urlrewritefilter.googlecode.com/svn/trunk/src/doc/manual/4.0/guide.html#urlabs

  7. Hey Ben,

    Nice information, I am trying to use LSDS (which is a Tomcat process from HP/Autonomy) that uses the extension of .page. My customer wants to only show .html, even though it is a .page backend. So I tried:
    <rule>
    <note>
    Redirect .html to .page
    </note>
    <from>^/(.*).html</from>
    <to type=”passthrough” >/$1.page</to>
    </rule>

    If I use redirect it works, but when I use passthrough it gives me a 404 (after changing the extension from page to html)

    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.utils.ServerNameMatcher DEBUG: looking for hostname match on current server name localhost
    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.UrlRewriteFilter DEBUG: checking for status path on /Component+Guide/Marketing/List/Basic+Bulleted+List.html
    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.UrlRewriter DEBUG: processing request for /Component+Guide/Marketing/List/Basic+Bulleted+List.html
    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.RuleBase DEBUG: Rule 0 run called with /Component+Guide/Marketing/List/Basic+Bulleted+List.html
    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.RuleBase DEBUG: Rule 1 run called with /Component+Guide/Marketing/List/Basic+Bulleted+List.html
    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.RuleBase DEBUG: matched “from”
    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.substitution.MatcherReplacer DEBUG: found 1
    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.substitution.MatcherReplacer DEBUG: replaced sb is /Component+Guide/Marketing/List/Basic+Bulleted+List.page
    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.RuleExecutionOutput DEBUG: needs to be forwarded to /Component+Guide/Marketing/List/Basic+Bulleted+List.page
    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.utils.ServerNameMatcher DEBUG: looking for hostname match on current server name localhost
    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.UrlRewriteFilter DEBUG: checking for status path on /Component+Guide/Marketing/List/Basic+Bulleted+List.page
    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.UrlRewriter DEBUG: processing request for /Component+Guide/Marketing/List/Basic+Bulleted+List.page
    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.RuleBase DEBUG: Rule 0 run called with /Component+Guide/Marketing/List/Basic+Bulleted+List.page
    Nov 04, 2013 10:58:38 AM org.apache.catalina.core.ApplicationContext log
    INFO: org.tuckey.web.filters.urlrewrite.RuleBase DEBUG: Rule 1 run called with /Component+Guide/Marketing/List/Basic+Bulleted+List.page

    Tips/Pointers/RTFMs appreciated

    1. Hi Andy .. I tried your Rewrite logic on a clean Tomcat install and it worked fine for me. So there maybe something else in your Tomcat or server set-up that is creating a conflict?

      I suggest downloading a copy of Tomcat to your local computer and setting up URLrewrite to test the logic. I for example used the from *.html to pass through to *.jsp and then ran http://localhost:8080/index.html and it worked to correctly display the ‘Tomcat If you’re seeing this, you’ve successfully installed Tomcat. Congratulations!’ page. At least that way you can then confirm your that the URLRewrite logic is sound and something else is the issue.


      <urlrewrite>
      <rule>
      <note>
      Redirect .html to .jsp
      </note>
      <from>^/(.*).html</from>
      <to type="passthrough">/$1.jsp</to>
      </rule>
      </urlrewrite>

  8. Excellent post Ben ,I would ask you a question ,is it possible to use URLRewriter for changing the host name of web Application ? for example from I would use carrefour.loyalcraft.com instead of localhost:8443/frontend?game=carrefour ? if true could you help me please ?

      1. thanks Ben for the reply , so i have resolved the problem with VirtualHost on Tomcat and now i can request my web app, for example, with this URL : aaa.loaylcraft.com or bbb.loyalcraft.com but my problem now is, according to the host name, i would add a parameter in the URL like this : aaa.loaylcraft.com would be changed to aaa.loaylcraft.com?param=aaa . i hope it can be done with URLRewriter.

  9. Hi Ben,

    I’m using Tomcat 6 and I have to do this on my project:

    user1.mydomain.com
    user2.mydomain.com
    user3.mydomain.com

    etc, etc… Every user will have their own subdomain.
    Is it possible to achieve using urlrewrite?

    Thanks! 🙂

  10. Hi Ben,
    I’m using eclipse configured with Tomcat 7.
    I can browse to: http://localhost:8090/fg/rewrite-status and see the rules.

    I use the default rule to test if it works:

    The rule means that requests to /test/status/ will be redirected to
    /rewrite-status
    the url will be rewritten.

    /test/status/
    %{context-path}/rewrite-status

    But it seems like there is no redirect/rewrite when I’m browsing to: http://localhost:8090/fg/test/status or http://localhost:8090/test/status.

    I’m getting HTTP error 404.

    Thanks in advance.

  11. Hi Ben,
    Referring to Conditions Based On URL Parameters,
    I’ve done something using UrlRewriteFilter which is actually required to make my site Google crawl-able.
    Here’s how it goes.

    (apple|kiwi|orange)
    ^/mysite/(.+)/(.*)$
    /mysite/content/%{parameter:fruit}

    It fails throwing java.lang.IllegalArgumentException: URLDecoder: Illegal hex characters in escape (%) pattern – %%7.
    As my variable contains underscores (_escaped_fragment_), where in it works fine with a parameter variable called ‘friuit’.
    Please help me get out of it.

    1. Hi Ben,
      My Url doesn’t have a % sign. The code that I had pasted in the above comment wasn’t displayed properly.
      I posted the same in a stackoverflow question.

      http://stackoverflow.com/questions/23803564/url-rewrite-filter-not-working-with-query-parameters-containing-special-characte

      The URL Rewrite Filter is not accepting a paramter named “_escsaped_fragment_” that means no special characters.
      Please see the question in the stackoverflow link and help me please.
      I even started a bounty there.

    1. There is no need to use Tuckey to redirect domain names. You could just set-up the domain name service provider of test.com to automatically redirect all requests to test1.com. This is usually either called domain name forwarding or redirection.

  12. Hi,

    It is a wonderful feature. Thanks for creating this.

    I’ve a specific requirement. Can you please help.

    I want to redirect the below two things:
    http://www.domain.com/myapp/getsomething/
    to
    http://www.domain.com/myapp/getsomething

    also
    http://www.domain.com/myapp/getsomething/?x=1&y=2&z=3

    to
    http://www.domain.com/myapp/getsomething?x=1&y=2&z=3

    Any quickhelp on this is much appreciated. I just need the regular expression for tag and tag. I’ve got the rest of the setup. The “domain” can change based on the environment we deploy.

    Thanks,
    Guru

    1. Hi Guruprasad,

      I have not tested these but Google suggests.

      Your from regex: ^(.*)\/(\?.*)?$
      Your to regex: $1$2

      Best of luck.

  13. Thanks Ben. It still seem to be a problem. I get the below error:
    The page isn’t redirecting properly

    Firefox has detected that the server is redirecting the request for this address in a way that will never complete.

    My web.xml

    UrlRewriteFilter
    org.tuckey.web.filters.urlrewrite.UrlRewriteFilter

    confPath
    /WEB-INF/urlrewrite.xml

    UrlRewriteFilter
    /*
    REQUEST
    FORWARD

    dispatcher
    org.springframework.web.servlet.DispatcherServlet

    contextConfigLocation
    classpath:/servlet-context.xml

    1

    dispatcher
    /

    My urlrewrite.xml

    Remove trailing slash
    ^(.*)\/(\?.*)?$
    $1$2

    When I run against:
    http://www.domain.com/myapp/getsomething/?x=1&y=2&z=3
    http://www.domain.com/myapp/getsomething/

    it always tries rewrites to:
    http://www.domain.com//getsomething

    and fails with the error “The page isn’t redirecting properly”.

    My problem is whenever I request the “http://www.domain.com/myapp/getsomething”, the dispatcher servlet is sending code 302 and redirecting with an extra “/”. I’m trying to solve it using the tuckey.

    Your quick help is much appreciated.

    1. Hi Guruprased,

      Unfortunately I can’t really help you as you cannot post code in the WordPress comments. Also I run a blog but I am not an expert with Tuckey. Your issue could be a simple server or a web application configuration issue and using Tuckey maybe an overkill solution or lead you to an endless redirection loop.

      But if you think Tuckey is your only solution. Can I suggest subscribing to http://stackoverflow.com/ and asking there?
      Use this question as a template for your own and most importantly use the same tags, ie java, regex, url-rewriting, tuckey-urlrewrite-filter.
      http://stackoverflow.com/questions/27969459/regex-in-tuckey-urlrewrite

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s