@Override
  public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) resp;

    request.setCharacterEncoding(httpEncoding);
    response.setCharacterEncoding(httpEncoding);

    String path = RequestUtils.getPathInfo(request);

    if (httpCache == false) {
      ResponseUtils.setBufferOff(response);
    }

    if (bypassRequestUrls != null && bypassRequestUrls.accept(request, path)) {
      chain.doFilter(request, response);
      return;
    }

    HttpMethod httpMethod = HttpMethod.valueOf(request.getMethod());

    if (corsRequestProcessor != null) {
      corsRequestProcessor.setHeaders(request, response);
      if (httpMethod == HttpMethod.OPTIONS) {
        response.setStatus(HttpServletResponse.SC_OK);
        return;
      }
    }

    RouteInfo route = router.lookup(request, path, httpMethod);
    request = fileUploadResolver.transform(request);
    RequestContext ctx = new RequestContext(request, response, path, httpMethod, route);

    try {
      if (route == null || route == RouteInfo.NOT_FOUND) {
        throw new ActionNotFoundException(path);
      }

      InterceptorChainImpl interceptorChain =
          new InterceptorChainImpl(WebConfig.getInterceptors(), ctx);
      interceptorChain.invoke();

      ResultInfo result = interceptorChain.getResult();
      if (result != null) {
        ResultHandler<Object> handler = resultHandlerResolver.lookup(result.getResultClass());
        handler.handle(ctx, result.getResultObject());
      }
    } catch (Exception e) {
      handleError(ctx, e);
    } finally {
      if (ctx != null) {
        ctx.destory();
      }
    }
  }