2
votes

I hope someone can point out where I'm going wrong here. I'm trying to create a simple filter that works something like Paul Tuckey's URLRewriteFilter, but stripped down to do only what I need it to do.

I can't get it to stop looping back on the original URI. I've snooped around the URLRewriteFilter code and it seems to be doing basically the same thing I'm doing. Here's my filter code:

public static final String dispatcherURI = "/Dispatcher?q=";
public void doFilter(final ServletRequest request, final ServletResponse response,
                     final FilterChain chain)
        throws IOException, ServletException {
    final HttpServletRequest rq = (HttpServletRequest)request;
    final HttpServletResponseWrapper rsw =
        new HttpServletResponseWrapper((HttpServletResponse)response);
    final String uri = rq.getRequestURI();
    if (uriIsDispatchable(uri)) {
        final String forwardPath = dispatcherURI+uri;
        rq.getRequestDispatcher(forwardPath).forward(rq, rsw);
        LOG.info("Forward From: "+uri+", To: "+forwardPath);
    }
    else {
        try { chain.doFilter(request, response); }
        catch (Exception e) {
            LOG.error(e);
            throw new RuntimeException(e);
        }
    }
}

// checks URI against an ArrayList of URIs that should be ignored.
private static boolean uriIsDispatchable (final String uri) {
    boolean result = true;
    for (String i : ApplicationValues.uriIgnore) {
        if (uri.indexOf(i) == 0) {
            result = false;
            break;
        }
    }
    return result;
}

Here's the filter entry in web.xml

<filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>myapp.filter.URLRewrite</filter-class>
</filter>
<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Some notes on the code: A URI like /home should be forwarded to a dispatcher servlet like so: /Dispatcher?q=/home the dispatcher servlet then determines what code to execute based on what's in the query string.

The filter correctly ignores the URIs in the "uriIgnore" ArrayList (including /Dispatcher), but the forward keeps looping on /home. For completeness sake, here's the contents of the uriIgnore ArrayList which is searched in the uriIsDispatchable method above:

public static final List<String> uriIgnore = new ArrayList<String>(4);
static {
  uriIgnore.add("/Dispatcher");
  uriIgnore.add("/netbeans-tomcat-status-test");
  uriIgnore.add("/resources");
  uriIgnore.add("/robots.txt");
}

Also, I'm running the latest Tomcat 6 proxied behind Apache.

Any help is appreciated. Thanks.

3

3 Answers

2
votes

I think when the program execute the statement: rq.getRequestDispatcher(forwardPath).forward(rq, rsw); it will call the doFilter() method again, and then the program will be an endless loop. I think you can add a parameter to tell the url is from another doFilter() or not, so it can recognize and then forward the url or not.

1
votes

I'll get around to figuring this out when I have time to peruse the URLRewrite Filter code further, but in the meantime it seems that if I really want the highest performance URL rewriting, I'll just let mod_rewrite and Apache do it.

My solution (I'm sure there's a better way to do this also):

# .htaccess file contents
# Apache has the same docroot as the Java web app.
# Java webapp is running on port 8084
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f [NC,OR]
RewriteCond %{REQUEST_FILENAME} !-d
# directory where images, static html files and JS scripts are located.
# Apache will serve these.
RewriteRule ^resources - [L,NC]
# obviously, we want Apache to serve robots.txt
RewriteRule ^robots.txt$ - [L,NC]
RewriteRule ^(.*)$ http://localhost:8084/Dispatcher?q=$1 [L,P,QSA]
</IfModule>
0
votes

Same infinite loop problem here, configure urlrewriter to filter only REQUEST, not FORWARD, try something like this in your web.xml:

 <filter-mapping>
     <filter-name>UrlRewriteFilter</filter-name>
     <url-pattern>/*</url-pattern>
     <dispatcher>REQUEST</dispatcher>
 </filter-mapping>

In this case rule processing does not executed again after forwarded.