Neto Fontes opened SPR-15765 and commented
Spring MVC already supports exact match binding for header name & value defined in @RequestMapping.
This improvement would additionally allow to map a request by defining a matching regular expression for the value field so that we wouldn’t need to create additional handler methods to map all variation of the possible header values.
E.g: For a given REST API that takes the header X-Override with possible values true or false which are case-insensitive we would need to have one @RequestMapping per each possible way to write true: true, True, TRUE, tRue, and on…
Instead we could have a regular expression in the header value which matches true in all possible ways to write it.
Proposal of usage:
@RequestMapping(
method = RequestMethod.PATCH,
headers = "X-Override?=^(?i)(true)$"
)
public ResponseEntity overridingOperation( ... ) { ... }
@RequestMapping(
method = RequestMethod.PATCH,
headers = "X-Override?=^(?i)(false)$"
)
public ResponseEntity nonOverridingOperation( ... ) { ... }
@RequestMapping(
method = RequestMethod.GET,
headers = "X-Priority?=^(?i)(high|medium|low)$"
)
public ResponseEntity processRequest( ... ) { ... }
The ?= would indicate that the following sequence is a regular expression.
1 votes, 2 watchers
Comment From: spring-projects-issues
Neto Fontes commented
I'm happy to contribute with the implementation if this ticket gets accepted.
Comment From: spring-projects-issues
Rossen Stoyanchev commented
The request makes sense on its own. However I am wondering if it makes sense to add it.
First evaluating every header condition as a regex could have potential impact on existing applications that make use of header conditions. Or is the wildcard after the header name in your example meant to be an indicator that the value is a regex? I can also see similar requests being made for other conditions (params, consumes, etc) which would multiply the effect.
A simple alternative is to map by presence, i.e. headers="X-Override", and then validate the header value inside the controller method. Of course the more you have to repeat this, the less attractive this alternative becomes. If you have it in a lot of places, another option is to create a custom HandlerMethodArgumentResolver (similar to HeaderMethodArgumentResolver which can automate getting and validating a header's value.
That leads to the question what do you want to happen if someone sends X-Override but using the wrong value? In other words do you see this more as a part of request mapping (and eventually a 404 response if no match) or more of a validation feature (eventually a 400 with error details).
It sounds to me like you would want validation first and foremost (leading to 400) and then, maybe, layered over with a high level mapping in case you want different handler methods to handle the same URL depending on presence or absence of headers. In other words if the real goal is validation it doesn't make sense to push that into the mappings.
Comment From: spring-projects-issues
Neto Fontes commented
Yes, the wildcard after the header name meant to be a indicator that the value is a regex. The indicator should be changed to any character not allowed in the header name part according to the RFC section 2.2 and section 4.2: (),\/:;<=>@\[\]{}?. This would prevent any potencial impact on existing applications out there.
I think we could potentially expand this feature to be used in the other conditions as well, this would be great!
The intention here is not to use this feature as a validation but as a resource binding. If it happens that the value doesn't match the regex, I would expect to see a 404 response. This would make easier to use annotation based tools to document REST APIs (i.e.: Swagger) as the request conditions for a given API would be described in the @RequestMapping already. Also, it would make your controller implementation way cleaner as you would have different handler methods for different conditions which improves code readability.
Comment From: bclozel
It seems that, given the current web programming model, it's not clear whether we should support that as a mapping feature or as a request binding feature with validation. This can be argued both ways and is hard to include by default as a result.
Given the lack of demand and clarity for this, we're closing this issue for now.