Dynamic Context path causes issue when using path variable in spring boot

627 views Asked by At

I am trying to implement dynamic context path I have followed this [blog] (https://www.broadleafcommerce.com/blog/configuring-a-dynamic-context-path-in-spring-boot) I am able to achieve the required result the only issue I am facing is when I am using path variable in my controller my application returns 404.I have given below the sample code for better explanation

     @Configuration
    public class Config {
    
        @Bean
        public WrapRequestFilter wrapRequestFilter() {
            return new WrapRequestFilter();
        }
    
        @Bean
        public FilterRegistrationBean wrapRequestFilterRegistrationBean() {
            FilterRegistrationBean registrationBean = new FilterRegistrationBean();
            registrationBean.setFilter(wrapRequestFilter());
            registrationBean.setName("wrapRequestFilter");
            registrationBean.setOrder(-1000001);
            return registrationBean;
        }
    }

Filter Class

public class WrapRequestFilter extends OncePerRequestFilter {

    private static final String[] PATHS = new String[] { "/food", "/equipment" };

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException, ServletException, IOException {
        ServletContextFacadeRequestWrapper wrapper = new ServletContextFacadeRequestWrapper(request);
        String path = getMatchingContextPathForRequest(request);
        if (path != null) {
            wrapper.setContextPath(request.getContextPath() + path);
            String newPath = request.getServletPath().substring(path.length());
            if (newPath.length() == 0) {
                newPath = "/";
            }
            wrapper.setServletPath(newPath);
        }
        filterChain.doFilter(wrapper, response);
    }

    public String getMatchingContextPathForRequest(HttpServletRequest request) {
        for (String path : PATHS) {
            if (request.getServletPath().startsWith(path)) {
                return path;
            }
        }
        return null;
    }

}

Wrapper Class

public class ServletContextFacadeRequestWrapper extends HttpServletRequestWrapper {

private String contextPath;
private String servletPath;

public ServletContextFacadeRequestWrapper(HttpServletRequest request) {
    super(request);
}

@Override
public String getContextPath() {
    if (StringUtils.isNotBlank(contextPath)) {
        return contextPath;
    }
    return super.getContextPath();
}

@Override
public String getServletPath() {
    if (StringUtils.isNotBlank(servletPath)) {
        return servletPath;
    }
    return super.getServletPath();
}

@Override
public String getRequestURI() {
    String requestURI = super.getRequestURI();
    if (requestURI.equals(contextPath)) {
        return requestURI + "/";
    }
    return requestURI;
}

public void setContextPath(String contextPath) {
    this.contextPath = contextPath;
}

public void setServletPath(String servletPath) {
    this.servletPath = servletPath;
}

Controller Method 1

    @RestController
public class FruitsController {
    @PostMapping("/{source}/method2")
    public String fruitsMethod(@PathVariable("source") String source){

        return "method working";
    }
}

Controller Method 2

    @RestController
public class FruitsController {
    @PostMapping("/method2")
    public String fruitsMethod(){

        return "method working";
    }
}

The issue comes when I hit the given curl using path variable then except food or equipment I am able to get status as 200 with a message "method working" but If I remove path variable from my controller then I am able to get the required result that is when I add food or equipment then I am able to get 200 status with a message "method working" but if I write any other keyword other than food or equipment I am get 404.My main issue is I want to achieve the later scenario using path variable which I am not able to achieve can anyone tell me what is wrong with my code why I am not able to achieve the desired result.I want to achieve my desired result using Controller Method 1 approach

curl --location --request POST 'http://localhost:8080/food/method2'
0

There are 0 answers