Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring boot HandlerInterceptor loadbalancing

I'm implementing a (sort of) load balancing HandlerInterceptor using Spring Boot.

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    String uri = request.getRequestURI();
    if (shouldUseServer1(uri)) {
        response.sendRedirect(server1Uri);
    } else {
        response.sendRedirect(server2Uri);
    }
}

The idea is, that based on the url, we either redirect to one service or another. The application doesn't have any explicit RequestMappings (yet).

Now the problem is, when the interceptor is called, the request is redirected to the default Spring error handler. As a result the URI stored in the HttpServletRequest is replaced by /error (effectively denying the access to the original URI).

Is there any way to intercept a request before it is rerouted to the error handler (or to get the original uri)?

like image 452
irundaia Avatar asked Jun 15 '26 11:06

irundaia


1 Answers

EDIT:

Because of the way Spring MVC handles requests with no mapping, you'll either need a filter:

@Component
public class CustomFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        request.getSession().setAttribute("ORIGINAL_REQUEST_URI", request.getRequestURI());
        chain.doFilter(request, response);

        // alternatively, ignore the last 2 lines
        // and just do your redirects from here 
        // and don't continue the filter chain
    }

  @Override
  public void destroy() {}

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

}

Otherwise, if you'd rather not rely on the session, you'll need to make the DispatcherServlet throw an exception in case no handler mapping is found, and then send the redirect from a @ControllerAdvice error handler:

@ControllerAdvice
class NoHandlerFoundExceptionExceptionHandler {

  @ExceptionHandler(value = NoHandlerFoundException.class)
  public ModelAndView
  defaultErrorHandler(HttpServletRequest req, NoHandlerFoundException e) throws Exception {
    String uri = // resolve the URI
    return new ModelAndView("redirect:" + uri);
  }
}

To avoid duplication, you may want to have a common class that you'll call from both the interceptor and the error handler.

like image 134
Miloš Milivojević Avatar answered Jun 17 '26 23:06

Miloš Milivojević



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!