Explain Codes LogoExplain Codes Logo

How to use a servlet filter in Java to change an incoming servlet request URL?

java
url-rewriting
servlet-filter
http-response
Nikita BarsukovbyNikita Barsukov·Jan 19, 2025
TLDR

To manipulate the incoming URL in a Java web application, you need to create a Filter that employs an HttpServletRequestWrapper to alter the original request. The methods to override are getRequestURI and getRequestURL. Here's a small demonstration:

public class UrlRewriteFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletRequestWrapper wrappedRequest = new HttpServletRequestWrapper(httpRequest) { @Override // This is where the magic happens! public String getRequestURI() { // Shadow the original URI with the shiny new one. 😎 return "/newPath"; } @Override // Here is another trick up our sleeve! public StringBuffer getRequestURL() { // "Abracadabra" and the URL transforms! return new StringBuffer("http://example.com/newPath"); } }; // The grand finale - pass on the spectacle to the next performer in the chain! chain.doFilter(wrappedRequest, response); } }

This piece of code serves to rewrite the request URL before the request is processed further. Register this filter for any incoming requests matching the url-pattern you intend to manipulate.

The wisdom behind the curtain

For a robust, efficient and mischief-free URL rewriting practice, it's wise to understand and apply these advanced concepts and practices:

Delving deep into URL redirection and forwarding

Sometimes, you might want to redirect the party to a whole different venue (URL) or even a different server. Here, you need to use the HttpServletResponse.sendRedirect() for a client-side magic show:

... if (/* the party needs more jazz! */) { HttpServletResponse httpResponse = (HttpServletResponse) response; // Off we go to a groovier place! httpResponse.sendRedirect("/newRedirectedURL"); } ...

On other occasions, you might want to switch the stages without the audience (client) realizing it, essentially a server-side trick. This calls for RequestDispatcher.forward(), a smooth move that goes unnoticed:

... RequestDispatcher dispatcher = request.getRequestDispatcher("/newForwardedURL"); // Stealthily forwarding to the next act! dispatcher.forward(request, response); ...

Evading the loop of doom

Prevent your filter from spinning into an infinity loop by checking whether the URL already got its makeover:

... if (!httpRequest.getRequestURI().equals("/newPath")) { // Let the show go on if we have a new act! chain.doFilter(wrappedRequest, response); } else { // Avoid repeating the same act! chain.doFilter(request, response); } ...

More drama with Tuckey

For the real juicy stuff, consider Tuckey's UrlRewriteFilter. It supports complex URL rewriting with regex pattern matching:

<filter> <filter-name>UrlRewriteFilter</filter-name> <!-- The mastermind behind the scene! --> <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class> </filter>

With it, you can also define XML rule tags for UrlRewriteFilter in your WEB-INF/urlrewrite.xml:

<rule> <!-- Initial act -- from humble beginnings --> <from>^/oldPath(/.*)?$</from> <!-- Finally, the grand transformation! --> <to type="forward">/newPath$1</to> </rule>

After the transformation: what now?

Ensure proper request handling after URL modifications by letting chain.doFilter() handle whether the original or the modified request should proceed.

The fine print

Remember to register your filter for specific URL patterns to avoid unnecessary performance drop:

... <filter-mapping> <filter-name>UrlRewriteFilter</filter-name> <!-- Only show it to the selected audience --> <url-pattern>/*</url-pattern> </filter-mapping> ...

Piecing the puzzle together

The server-side vs. client-side saga

Remember, sendRedirect (client-side redirect) entails two requests and may cause perceivable latency in the client (a browser). In contrast, RequestDispatcher.forward (server-side forward) is faster but happens unseen.

Handling special actors on the stage

In regex rules, be cautious about escaping special characters—a negligent escape can lead to an unexpected twist!

Don't reinvent the wheel; repaint it!

Consider studying implementations in open-source projects. They offer ready blueprint and functional insights.

Context is everything

Tailor your URL transformation according to the context. An API call, for instance, may require you to preserve backward compatibility.