1

I have been searching for the answer and many answers didn't solve my problem even though they solved very similar problems.

So My problem is this : I have a path variable which may contain character "/". The same value also contains other special characters such as "." "+" "=" etc .basically all valid Base64 characters.

But Spring MVC throws 404 with logs saying no handler found. I tried using regular expressions in path variable as well but to no avail. so below id my code snippets :

http://localhost:8080/sale/public/viewSaleDetails/b91a03730a746a2b27e1c7bbbd94ddf6a9df593301cd96c606348df5eed235da.FkJJbOqEM8Xvhffe6FwUdQ8/mMCD4+fxpY7w5L9kbJ8=

is my URL. If you see it has / in path variable value. along with "." and "+" and "=". Spring maps this correctly if I remove / between character "m" and "8". but with / in value it just doesnt work. I tried a lot of things including character encoding filter,regex in pathvariable etc. Please help.

Also I dont want to use request parameters as far as possible.

@RequestMapping(value = "/public/viewSaleDetails/{id}", method = RequestMethod.GET)

is my mapping. Also the url is hit from the browser as it is without any URL encoding. I tracked it on browser network bar and it doesnt encode it as expected. I am using Spring 4.2.8 RELEASE version with java 8 and tomcat 8

Shailesh Vaishampayan
  • 1,766
  • 5
  • 24
  • 52
  • i'm not sure if Spring can handle "/" in the PathVariables, i think it won't work, however you can use some url rewriter to transform your PathVariable from public/viewSaleDetails/{id} to a RequestParam public/viewSaleDetails?id=xx before reaching your controller. – Mouad EL Fakir Feb 01 '17 at 23:53

1 Answers1

0

There is open issue in spring Jira according matching slashes in path. And due to discussion it is not reasonable to change mathing strategy on framework level. The issue was created due to this stackoverflow post and I suggest creating value resolver according to the answer.

Here is example code for such resolver:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.List;

@SpringBootApplication
public class SampleSpringApp {
    public static void main(String[] args) {
        SpringApplication.run(SampleSpringApp.class, args);
    }
}

@RestController
class SampleController {
    @RequestMapping("/records/**")
    public String getId(Id id) {
        return id.id;
    }
}

@Configuration
@EnableWebMvc
class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new IdResolver());
    }
}

class IdResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return Id.class.isAssignableFrom(parameter.getParameterType());
    }

    @Override
    public Object resolveArgument(MethodParameter parameter,
                                  ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest,
                                  WebDataBinderFactory binderFactory) throws Exception {    
        String basePath = ((String) webRequest.getAttribute(
                HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE,
                RequestAttributes.SCOPE_REQUEST
        )).replace("**", "");
        String id = ((String) webRequest.getAttribute(
                HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE,
                RequestAttributes.SCOPE_REQUEST
        )).replace(basePath, "");
        return new Id(id);
    }
}

class Id {
    public final String id;

    Id(String id) {
        this.id = id;
    }
}
Community
  • 1
  • 1
Yevhenii Melnyk
  • 553
  • 4
  • 16