Environment:

  • Spring 2.3.0.RELEASE

  • JDK 1.8

Steps to reproduce:

  • Add spring.mvc.servlet.path=/test in application.properties.

  • Define Controller,use @RestController in controller class, then use @GetMapping("/test") at one method, finally,use @GetMapping("/test1") at other method.

  • start project,visit urls that I want to test.

I expect that:

  • I visit http://localhost:8080/test/test, I got result.

  • I visit http://localhost:8080/test/test1, I got result too.

  • I visit http://localhost:8080/test, HTTP ERROR 404

  • I visit http://localhost:8080/test1, HTTP ERROR 404

Actually:

  • I visit http://localhost:8080/test/test, I got result.

  • I visit http://localhost:8080/test/test1, I got result too.

  • I visit http://localhost:8080/test, I got result.It confused me!

  • I visit http://localhost:8080/test1, HTTP ERROR 404

In fact,I find that WebFlux use spring.webflux.base-path=/test has some problems

This is link of My demo: https://github.com/DogeC0in/BugFinder

Comment From: rstoyanchev

Please avoid cross-posting: https://github.com/spring-projects/spring-boot/issues/22158

Comment From: rstoyanchev

This is a very old part of the code. My best guess is as that this is so for 2 reasons:

  1. For Servlet mappings by extension in which case the pathInfo is null and hence there is no path within the servletPath, i.e. the whole thing is the servletPath.
  2. Even for Servlet mapping by prefix, returning "" isn't a good outcome, because if you have two Servlets mapped to different prefixes (e.g. "/foo" and "/bar"), then requests to "/foo" and to "/bar" would both appear as "" to the application and it would haver no way to differentiate between the two.

My advice is to not use mappings where the servletPath prefix is also duplicated in an application mapping. I would also advise against using a mapping by servletPath prefx, and against relying on the servletPath in any way, in the first place if you can avoid it. It's fraught with bigger issues then just such corner cases.

If you must have a Servlet mapped to "/test" then in your application mappings use "/test1" and "/test2", and if you want also one for "/test" which correspond to URLs "/test/test1", "/test/test2", and "/test" respectively.

Comment From: DogeC0in

@rstoyanchev So,only by agreement, It can't be avoided? Actually,I want http://localhost:8080/test/test work , but http://localhost:8080/test is also available . And I have a suspicion that WebMvcProperties did not worked.

Comment From: bclozel

@DogeC0in We can't change this behavior without breaking legitimate use cases; Rossen pointed out that your setup is flawed in the first place, so this can't be avoided unless you can change this situation with your application. I don't think there's an issue with WebMvcProperties as it's configuring the expected feature in Spring MVC.

Comment From: rstoyanchev

So,only by agreement, It can't be avoided?

Correct, you need to avoid having both the Servlet and an application mapping using the exact same path because they overlap. Make the application mapping different, e.g. "/test1" and "/test2" so you'll have "/test/test1" and "/test/test2" working correctly. Then input path "/test" is for the whole Servlet.