How to get the original handler URI (with wildcards, etc.) in a HandlerInterceptor in Spring? - spring

I am collecting custom metrics for my controller endpoints via HandlerInterceptor. In postHandle I have everything I need and I would like to save the metrics for my endpoints along with the original route defined in the controller, so not the actual route filled with the data.
E.g. I have #GetMapping("/cats/{name}") and make GET request on /cats/tom I still want the defined route "cats/{name}"
I found that I can do this with the Object handler which is the parameter of postHandle -> I can cast it to HandlerMethod get the annotations of the method and find it from memberValues. This seems a bit overkill I also have to filter for Get-, Post-, Put-, Delete-, Patch-, RequestMapping annotations. Is there any easier or more straightforward way to do this? If so how? If not what else do I have to take into consideration with this solution?

It turns out Spring adds this data to the HttpServletRequest attributes. So it can be retrieved using:
String routePattern = (String) request.getAttribute("org.springframework.web.servlet.HandlerMapping.bestMatchingPattern");

Related

Is it possible to use a ResponseEntity Object as a resource for a JsonItemReaderBuilder?

I have output from a ResponseEntity object mapped to an entity using RestTemplate.exchange and I'm looking to pass that as the resource for a JsonItemReaderBuilder (using Spring Batch). As the ResponseEntity is not a resource, I know I need something in the middle but looking for recommendations. What would the best approach be?
I've tried converting the output to various JSON objects, streams, bytearrays, and lists with no luck. I also tried using a URLResource but the API call required headers and a body that didn't map well. I may have done that incorrectly but couldn't get that to work.

Spring Controller Url

I have question about controllers. Always when i working with controller im start to declare #RequestMapping for example if have UserController then is #RequestMapping("/user");
What if i want to declare another path in this same controller? For example im have #GetMapping("/info") and i will get info about user, but what if i want to declare on this same controller path localhost:8080/topic/blablabla? Is another solution than delete #RequestMapping from controller and make on every Get/PostMapping another path?
Defining a #RequestMapping at the controller level; it means narrowing it down to your criteria.
You can use the #RequestMapping annotation to map requests to controllers methods. It has various attributes to match by URL, HTTP method, request parameters, headers, and media types. You can use it at the class level to express shared mappings or at the method level to narrow down to a specific endpoint mapping. Read More
It is good you want to do, sometimes I need it too but as far as I research it is not supported now.

Spring controller method invocation advice

I have a controller that exposes the following endpoint:
#RequestMapping("/all-users")
List<User> getAllUsers() {
...
}
I have also an annotation that helps me out with versioning of those endpoints, which ends up on something like this:
#RequestMapping("/all-users")
#Version(version=1, latests=LATEST_ALL_USERS)
List<User> getAllUsers() {
...
}
Now I want to introduce an additional standard behavior to all handlers mapped wish method contains #Version annotation which will simply wrap the response object into another object which contains the current version and latest version of the invoked method. Some information to build this object are provided by #PathVariable parameters. I'm trying to find a hook that allows me that but no luck so far.
I tried first to have a custom RequestResponseBodyMethodProcessor but if I add it will not take any effect because the original RequestResponseBodyMethodProcessor comes before and I don't want to remove the ResponseBody from my endpoints.
Afterward I tried to go for the mapping instead, once I cannot handle it on the processor, maybe I could handle that on mapping time introducing my code pre and post method invocation, but got stuck on the point where mapping is registered where a method object is needed, not allowing me to introduce my advice code.
Is there any way to get this done?
Edit:
Some of the information needed to build the new returned object are provided as #PathVariables, and are available on end-point method call.

Validate a HTTP-Header field in a Spring RestController

I'm looking for a way to validate whether the custom header 'X-Client-Id' is set to a value defined in a Repository within an HTTP request sent to a REST-controller in SpringBoot.
I see tutorials (like this) which includes the header in the method like this: #RequestHeader(value="User-Agent"). I assume I would have to write that line to every method and inject a common validator-bean to verify the value.
Another stackoverflow answer seems to suggest using an HandlerInterceptor. I'm not sure though if that's applicable to header values and REST endpoints.
So what is the recommended way to validate all methods of a class/REST-controller whether a specific header is set or not?
Basically the easiest (and most logical) way is to catch the Request before it gets to your Controller. That can be achieved either with a HandlerInterceptor as the other answer states or with a simple Filter like OncePerRequestFilter.
Extend that class, override the doFilterInternal() method as doFilter() is final, extract the proper header value, check it against whatever you need and depending on the value, either throw an Exception or continue with the chain.

How to pass customized request to controller in spring mvc?

Generally, when user's form is submitted, request is passed to spring controller.
and Controllers are shaped like this
TestController(HttpServletRequest request, HttpServletResponse response)
I want to pass "MyHttpSevletRequest, MyHttpServletResponse" not "HttpSevletRequest, HttpServletResponse".
Is it possible?
I want to know is it possible, and how? in technique.
Don't say that "No need to to that, alternative way is here"
Any answer will be appreiciated. Thank you.
I dont know how to do it directly but I know a workaround to get what you intend to do done.
You can use spring aop methodbeforeadvice and afterreturningadvice to get hold of the request and response objects before and after they enter/leave the action method. Basically kind of a request response interceptor you would be doing. In that you can write a transformer method that would take the standard request and response object as input and output you with your custom request and response object(your custom class should implement the HttpServletRequest interface) and then override the request and reponse objects with your custom objects.

Resources