Skip to content

Spring MVC can wrongly return 405 http code when using annotated controllers with other handler mapping methods (router functions for example) #31563

New issue

Have a question about this project? No Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “No Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? No Sign in to your account

Closed
FBibonne opened this issue Nov 7, 2023 · 3 comments
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: declined A suggestion or change that we don't feel we should currently apply

Comments

@FBibonne
Copy link
Contributor

FBibonne commented Nov 7, 2023

This issue stands for Spring framework 5.3.30 (spring-webmvc artifact) but the code seems to be the same in Spring 6

I use together annotated controllers and functional endpoints to handle http request in spring MVC and it happens that Spring MVC returns an 405 http code (Method Not Allowed) which is not expected.

For example : I declare an @PutMapping method in an annotated controller (class PersonController) to handle PUT /persons/{id} and I declare a functional endpoint (configuration class PersonConfig) to handle GET /persons/{id}. When I request GET /persons/{id}, the application returns a 405 http code (Method Not Allowed) because according to the annotated controller, the pattern /persons/{id} is only processed with PUT. That is not what is expected : when requested with GET /persons/{id} the application is expected to process the request with the method personHandler.

It happens because the implementation of handleNoMatch in RequestMappingInfoHandlerMapping seems to break the contract of AbstractHandlerMethodMapping.lookupHandlerMethod : when a request doen't match, handleNoMatch may raise an exception to explain why it doesn't match and so doesn't return null. Therefore lookupHandlerMethod doesn't return null as expected if no match. Then the DispatcherServlet stops searching in others handlerMapping if there is a match for the request.

In such a case, maybe exceptions like HttpRequestMethodNotSupportedException should be treated as null value returns and only raised if no other handlerMapping matches.

Class PersonConfig

@Configuration
public class PersonConfig {

    private static final String ID = "1";
    private static final String NAME = "Fabrice";
    private static final Person PERSON=new Person(ID, NAME);

    @Bean
    public RouterFunction<ServerResponse> personsGetters(){
        return route().path("/personsas", mapper->
                mapper.GET("/{id}", this::personHandler)
                        .GET(this::personHandler)).build();
    }

    public ServerResponse personHandler(ServerRequest req){
        if ((req.pathVariables().containsKey("id") && ID.equals(req.pathVariables().get("id")))
                || req.pathVariables().isEmpty()){
            return EntityResponse.fromObject(PERSON).build();
        }else{
            return ServerResponse.notFound().build();
        }

    }

}

Class PersonController

@RestController
@RequestMapping("/persons")
public class PersonController {

    @PutMapping("/{id}")
    public Person updatePerson(@RequestBody Person person, @PathVariable("id") String id){
        System.out.println("Update person with id "+id+" with "+person);
        return person;
    }

}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Nov 7, 2023
@sdeleuze
Copy link
Contributor

sdeleuze commented Nov 7, 2023

Can you please test with Spring Boot 3.2.0-RC2 and Spring Framework 6.1.0-RC2 if you still see this issue? I suspect #30278 could resolve it.

@sdeleuze sdeleuze added status: waiting-for-feedback We need additional information before we can continue in: web Issues in web modules (web, webmvc, webflux, websocket) labels Nov 7, 2023
@FBibonne
Copy link
Contributor Author

FBibonne commented Nov 7, 2023

This issue doesn't happen with Spring Framework 6.1 : the reorder of the registered mappings solved it

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Nov 7, 2023
@sdeleuze
Copy link
Contributor

sdeleuze commented Nov 7, 2023

Thanks for the quick feedback, I will close this issue since such change would be too breaking for 6.0.

@sdeleuze sdeleuze closed this as not planned Won't fix, can't repro, duplicate, stale Nov 7, 2023
@sdeleuze sdeleuze added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged or decided on status: feedback-provided Feedback has been provided labels Nov 7, 2023
No Sign up for free to join this conversation on GitHub. Already have an account? No Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

3 participants