How to use a Servlet Filter to change/rewrite an incoming URL?
Asked Answered
M

5

204

How can I use a Servlet Filter to change an incoming URL from

http://nm-java.appspot.com/Check_License/Dir_My_App/Dir_ABC/My_Obj_123

to

http://nm-java.appspot.com/Check_License?Contact_Id=My_Obj_123

?


Update: according to BalusC's steps below, I came up with the following code:

public class UrlRewriteFilter implements Filter {

    @Override
    public void init(FilterConfig config) throws ServletException {
        //
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        String requestURI = request.getRequestURI();

        if (requestURI.startsWith("/Check_License/Dir_My_App/")) {
            String toReplace = requestURI.substring(requestURI.indexOf("/Dir_My_App"), requestURI.lastIndexOf("/") + 1);
            String newURI = requestURI.replace(toReplace, "?Contact_Id=");
            req.getRequestDispatcher(newURI).forward(req, res);
        } else {
            chain.doFilter(req, res);
        }
    }

    @Override
    public void destroy() {
        //
    }
}

The relevant entry in web.xml look like this:

<filter>
    <filter-name>urlRewriteFilter</filter-name>
    <filter-class>com.example.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>urlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

I tried both server-side and client-side redirect with the expected results. It worked, thanks BalusC!

Monody answered 27/4, 2010 at 20:59 Comment(5)
Related question: stackoverflow.com/questions/2723829/…Portiaportico
Which version of the servlet spec are you using ? How you forward requests changes with the different versions.Dart
See this post it also has a Filter that does what you wantDart
Please note that if your original URL contains parameters, i.e. nm-java.appspot.com/Check_License/Dir_My_App/Dir_ABC/My_Obj_123?**param1=A&param2=B** then these parameters will be also forwarded to next servlet/jsp. I didn't find a way to get rid of or replace original parameters (only by using HttpServletRequestWrapper). Any ideas?.. Update: it seems that http://ocpsoft.org/opensource/how-to-safely-add-modify-servlet-request-parameter-values/ addresses this problem.Adult
Thanks I was searching for an example on url rewriting and encryption .Expositor
P
295
  1. Implement javax.servlet.Filter.
  2. In doFilter() method, cast the incoming ServletRequest to HttpServletRequest.
  3. Use HttpServletRequest#getRequestURI() to grab the path.
  4. Use straightforward java.lang.String methods like substring(), split(), concat() and so on to extract the part of interest and compose the new path.
  5. Use either ServletRequest#getRequestDispatcher() and then RequestDispatcher#forward() to forward the request/response to the new URL (server-side redirect, not reflected in browser address bar), or cast the incoming ServletResponse to HttpServletResponse and then HttpServletResponse#sendRedirect() to redirect the response to the new URL (client side redirect, reflected in browser address bar).
  6. Register the filter in web.xml on an url-pattern of /* or /Check_License/*, depending on the context path, or if you're on Servlet 3.0 already, use the @WebFilter annotation for that instead.

Don't forget to add a check in the code if the URL needs to be changed and if not, then just call FilterChain#doFilter(), else it will call itself in an infinite loop.

Alternatively you can also just use an existing 3rd party API to do all the work for you, such as Tuckey's UrlRewriteFilter which can be configured the way as you would do with Apache's mod_rewrite.

Portiaportico answered 27/4, 2010 at 21:10 Comment(11)
Any doFilter() sample code somewhere that does the above ? Thanks.Monody
At what step exactly are you stucking? My answer almost writes code itself. Did you also note that the code references in blue are actually links to Javadocs which describes the class/method behaviour in detail? At any way, you can find here and here good JSP/Servlet tutorials, specifically this one about filters.Portiaportico
I followed the same for implementing filter but not getting success. Please help. The request is not redirecting to the destination resource class for service.Sybilla
@Actually I canot ask question from this account. This is the link for my another account - stackoverflow.com/questions/19089186/… sorry for this inconvenience.Sybilla
@Portiaportico I am using filter mechanism for authentication of Host Name for the service caller with the key provided to the caller. here I want to validate the caller and then forwarded to service url requested. Other wise it will return unauthorized exception. Please help me...after googling as lot I found this and then tried this with no success. Please seem my web.xml and also inside doFilter() method.Sybilla
I supose it is correct, but if the filter is one of the firsts in the chain, and RequestDispatcher#forward() is executed, the rest of the filters won't be executed. So, won't be a better way then doing this as a servlet?Korella
@datakey: just either rearrange the ordering or add <dispatcher>FORWARD</dispatcher> to filter mapping.Portiaportico
@Portiaportico can we do it without redirecting or calling forward?Cytokinesis
This solution works, but if we have chains of filters? As I understand this solution ruins the logic of filters - when there are chain of filters and every filter must do something before processing request and after processing request. But this solutions instead forwards request to certain servlet what is not its work.Extradite
@JimJim2000: just either rearrange the ordering or add <dispatcher>FORWARD</dispatcher> to filter mapping.Portiaportico
I've read about FORWARD is not what is suitable for me. And I can't understand how I can rearrange the ordering to get what I say. Because it can be possible only with something like request.setUrl(String newUrl);chain.doFilter(...);Extradite
G
22

You could use the ready to use Url Rewrite Filter with a rule like this one:

<rule>
  <from>^/Check_License/Dir_My_App/Dir_ABC/My_Obj_([0-9]+)$</from>
  <to>/Check_License?Contact_Id=My_Obj_$1</to>
</rule>

Check the Examples for more... examples.

Garboard answered 27/4, 2010 at 22:22 Comment(1)
Hi, The link pasted does not work anymore. Its 404 there. Request you to please change to some other source. Thanks.Columelliform
C
10

A simple JSF Url Prettyfier filter based in the steps of BalusC's answer. The filter forwards all the requests starting with the /ui path (supposing you've got all your xhtml files stored there) to the same path, but adding the xhtml suffix.

public class UrlPrettyfierFilter implements Filter {

    private static final String JSF_VIEW_ROOT_PATH = "/ui";

    private static final String JSF_VIEW_SUFFIX = ".xhtml";

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpServletRequest = ((HttpServletRequest) request);
        String requestURI = httpServletRequest.getRequestURI();
        //Only process the paths starting with /ui, so as other requests get unprocessed. 
        //You can register the filter itself for /ui/* only, too
        if (requestURI.startsWith(JSF_VIEW_ROOT_PATH) 
                && !requestURI.contains(JSF_VIEW_SUFFIX)) {
            request.getRequestDispatcher(requestURI.concat(JSF_VIEW_SUFFIX))
                .forward(request,response);
        } else {
            chain.doFilter(httpServletRequest, response);
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {

    }

}
Comose answered 29/6, 2016 at 10:53 Comment(0)
C
4

In my case, I use Spring and for some reason forward did not work with me, So I did the following:

public class OldApiVersionFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        if (httpServletRequest.getRequestURI().contains("/api/v3/")) {
            HttpServletRequest modifiedRequest = new HttpServletRequestWrapper((httpServletRequest)) {
                @Override
                public String getRequestURI() {
                    return httpServletRequest.getRequestURI().replaceAll("/api/v3/", "/api/");
                }
            };
            chain.doFilter(modifiedRequest, response);
        } else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void destroy() {}
}

Make sure you chain the modifiedRequest

Charlinecharlock answered 9/3, 2022 at 23:20 Comment(4)
Maybe the reason "forrward" didn't fork for you is because it's "forward"...Deoxidize
You could have edited the typo overwriting a whole comment line!Charlinecharlock
Doing so would have altered the sense of your reply, Youans, as I couldn't take for granted if it was either a typo while writing your answer or a mistake in the source code you tried. You could have done the proper edit, as you are the only who knows what's the correct case, but you didn't, either. By the way, I made a typo, also, but I cannot fix it. I meant "work" instead of "fork"... d'oh!Deoxidize
@Deoxidize it is not in the code! However I see your point, but even if it was code it is not like it was written by a robotCharlinecharlock
R
-1

I have checked your program and necessary correction have been done. Hope your problem will be solved.

Use Servlet Version 3.0

package mypackage;

import java.io.IOException;
import java.util.Enumeration;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet Filter implementation class RequestRedirectingFilter
 */
@WebFilter("/Dir_My_App/*")
public class RequestRedirectingFilter implements Filter {

    private ServletContext context;
    
    public void init(FilterConfig fConfig) throws ServletException {
        this.context = fConfig.getServletContext();
        System.out.println("RequestRedirectingFilter initialized.....................");
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException,ServletException {
        System.out.println("I am here........");
        HttpServletResponse res=(HttpServletResponse)response;
        res.sendRedirect("http://nm-java.appspot.com/Check_License?Contact_Id=My_Obj_123");
        
    }

    public void destroy() {
        //we can close resources here
    }

}
 

You can deploy this program in tomcat 9

Riptide answered 8/3, 2024 at 3:43 Comment(1)
Sorry, you got the problem backwards. Re-read the question and the currently accepted answer.Portiaportico

© 2022 - 2025 — McMap. All rights reserved.