Search code examples
jakarta-eeservletstuckey-urlrewrite-filter

UrlRewriteFilter send params to controller


I have simple JSF application. And trying to understand UrlRewriteFilter.

First I have URL like: http://testSite/autocomplete?action=lookup&id=45

I want to get params action and id but in the same time I need user (and google-bot) never seen this type of URL but always http://testSite/lookup/45

I make this rewriting of url but cannot send params to the servet-controller. Please help.

This is web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <!-- URL ReWriter -->
    <filter>
        <filter-name>UrlRewriteFilter</filter-name>
        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>UrlRewriteFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>


    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>AutoCompleteServlet</servlet-name>
        <servlet-class>com.ajax.AutoCompleteServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>AutoCompleteServlet</servlet-name>
        <url-pattern>/autocomplete</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

urlrewrite.xml:

<?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 use-query-string="true">

    <rule>
        <from>/index.jsp</from>
        <to type="redirect">%{context-path}/</to>
    </rule>

    <rule>
        <from>^/autocomplete\?action=lookup&amp;id=(.*)</from>
        <!--  <run class="com.ajax.AutoCompleteServlet" method="doGet" />-->
        <to type="redirect">%{context-path}/lookup/$1</to>
    </rule>
    <rule>
        <from>^/lookup/(.*)</from>
        <run class="com.ajax.AutoCompleteServlet" method="doPost">
            <init-param>
                <param-name>action</param-name>
                <param-value>lookup</param-value>
            </init-param>
            <init-param>
                <param-name>id</param-name>
                <param-value>$1</param-value>
            </init-param>
        </run>
    </rule>
</urlrewrite>

And Servlet:

package com.ajax;

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.util.HashMap;
import java.util.Iterator;

public class AutoCompleteServlet extends HttpServlet {

    private ServletContext context;
    private ComposerData compData = new ComposerData();
    private HashMap composers = compData.getComposers();

    @Override
    public void init(ServletConfig config) throws ServletException {
        this.context = config.getServletContext();
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {

        String action = request.getParameter("action"); // Always null ???
        String targetId = request.getParameter("id"); // Always null ????

    }
}

Solution

  • That's indeed expected behavior. You're redirecting to an URL with those parameters in path info instead of query string.

    You've basically 2 options:

    1. Add a rule which performs a forward (no redirect!), see also "Clean a URL" in documentation.

      <rule>
          <from>^/lookup/(.*)$</from>
          <to>/autocomplete?action=lookup&amp;id=$1</to>
      </rule>
      
    2. Change the servlet to grab those parameters from path info instead.

      String[] params = request.getPathInfo().substring(1).split("/");
      String action = params[0]; // "lookup"
      String id = params[1]; // "45"
      // ...
      

    Unrelated to the concrete problem, if the "dirty" URL was already published into the web beforehand and is already indexed by searchbots, you'd really better use <to type="redirect-permanent"> (HTTP 301) instead of <to type="redirect"> (HTTP 302). This will instruct the searchbots to remove the URL from the index instead of keeping as alternate URL.