My intention is to redirect to another site whenever the
User-Agent has detected the mobile keyword. I have a solution for this approach where I have the file name for mobile version start with
m and reside at the location same as desktop version. I try not to branch out another path for mobile version to keep maintenance easy.
Unfortunately the
Filter call was unintentionally looping on itself. This seems to me that for every new redirection
Filter call, the mobile keyword validation will get invoked and the new redirection is sent again. And this process will go on endlessly. This is so not good, I was trapped!
This is what happened on my code:
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
if( httpServletRequest.getHeader("User-Agent").indexOf("Mobile") != -1 ) {
httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/m" + httpServletRequest.getRequestURI().substring(httpServletRequest.getRequestURI().lastIndexOf("/")+1, httpServletRequest.getRequestURI().length()));
}
else {
chain.doFilter(request, response);
}
According to the advice from expert. I'm going to need additional validation to stop the process after I reach to that URI. Thus, what I need to do is to put additional validation as below:
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
if( httpServletRequest.getHeader("User-Agent").indexOf("Mobile") != -1 ) {
// stop redirect if the site has reach
if( httpServletRequest.getRequestURI().equalsIgnoreCase(httpServletRequest.getContextPath() + "/" + httpServletRequest.getRequestURI().substring(httpServletRequest.getRequestURI().lastIndexOf("/")+1, httpServletRequest.getRequestURI().length()))) {
chain.doFilter(request, response);
}
else {
httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/m" + httpServletRequest.getRequestURI().substring(httpServletRequest.getRequestURI().lastIndexOf("/")+1, httpServletRequest.getRequestURI().length()));
}
}
else {
chain.doFilter(request, response);
}
Tested and worked as expected. I did also tried to forward the request as shown below:
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
if( httpServletRequest.getHeader("User-Agent").indexOf("Mobile") != -1 ) {
request.getRequestDispatcher("m" + httpServletRequest.getRequestURI().substring(httpServletRequest.getRequestURI().lastIndexOf("/")+1, httpServletRequest.getRequestURI().length())).forward(request, response);
}
else {
chain.doFilter(request, response);
}
I find this working as well but for subsequent call on
doFilter, the
httpServletRequest.getRequestURI() will always stuck on the old URI. I think this is due to the reason URL is forward on server site, but not reflected on client site.