negated header expressions are not evaluated correctly. I have these two controller methods:
Code:
@RequestMapping(method = RequestMethod.POST, headers="content-type!=application/xml")
public String create(...) {
...
}
@RequestMapping(method = RequestMethod.POST, headers="content-type=application/xml")
public ResponseEntity<String> create(...) {
...
}
If the content-type header on the request is set to application/xml, the first controller is invoked.
Using a debugger, I've traced this to faulty logic in ServletAnnotationMappingUtils.checkHeaders():
For the first method, the variable 'found' is true and the variable 'negated' is true for a request with the header "Content-Type: application/xml". However, the check
Code:
if(!found) {
return negated;
}
causes the enclosing loop to continue, so that the method eventually ends up at the on the last line, causing the wrong result to be returned.
ServletAnnotationMappingUtils.checkHeaders (correctly) also returns true for the second controller method. Control flow then returns to
Code:
AnnotationMethodHandlerAdapter$ServletHandlerMethodResolver.resolveHnadlerMethod
.
Code:
RequestSpecificMappingInfoComparator
and don't change the list of matches, so the first method is incorrectly returned as the controller method.
If I change my controller class and reverse the method definitions, the other create method is chosen. I suspect this bug can be reproduced by reversing the method definition order in
Code:
ServletAnnotationControllerTests$NegatedContentTypeHeadersController
, which should cause
Code:
ServletAnnotationControllerTests.negatedContentTypeHeaders
to fail.
I've re-opened SPR-7346 and added this post as a comment.