I have a requirement where i don't want to execute interceptors for all the rpc methods, How i can set the interceptors conditionally?
looking for something similarly.
https://chenyitian.gitbooks.io/gin-tutorials/content/tdd/21.html
execute interceptors for few routes
The interceptors all have access to the RPC method string (in the format of /package.service/method).
https://github.com/grpc/grpc-go/blob/master/interceptor.go#L43
You can check the method string before executing the interceptor body.
Related
How do we set the request body in case of WebClient.Builder? Here is my code -
WebClient.Builder webClientBuilder = WebClient.builder().baseUrl(clientMetadataServiceUri).defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).filters(exchangeFilterFunctions -> {
exchangeFilterFunctions.add(logRequest());
exchangeFilterFunctions.add(logResponse());
});
webClientBuilder.clientConnector(getHttpConnector()).build().get().exchange().doOnSuccess(clientResponse -> {...})
Where and how should I add the request body here?
I believe it cannot be done.
Generally, WebClient(or RestTemplate) is like a template which you use to call other Rest Service. You define this template once with all the customizations needed like interceptors,messageConverters, errorHandlers etc which you need to communicate with this particular Service.
Now coming to individual calls to the service, each call to the service may vary. For example you might be calling different methods like Get, Post.. etc. You might call different endpoints. You might call with/without body. Since you always use the same client(WebClient/RestTemplate) to communicate with that service, you cannot create a WebClient instance with body or method or url(you can only set baseUrl) which are specific to individual call.
This is similar to RestTemplateBuilder. You cannot find any method to set either endpoint or method or body.
You might create a separate instance of webclient for each call. But that is not how it is generally used or advisable(Generally you define a bean of type WebClient and Autowire it). Hence it is not available.
The issue is with get() like many other frameworks Spring WebFlux also doesn't support the request body for the get calls. In the case of post, it goes like this -
WebClient.Builder webClientBuilder = WebClient.builder().baseUrl(clientMetadataServiceUri).defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).filters(exchangeFilterFunctions -> {
exchangeFilterFunctions.add(logRequest());
exchangeFilterFunctions.add(logResponse());
});
webClientBuilder.clientConnector(getHttpConnector()).build().post().body(...).exchange().doOnSuccess(clientResponse -> {...})
I have a need to intercept Jersey resource calls and run code before/after each ResourceMethod call. I have a ModelProcessor and am able to intercept the calls:
for(Resource resource: resourceModel.getResources()) {
for (ResourceMethod resourceMethod : resource.getResourceMethods()) {
Resource.Builder resourceBuilder = Resource.builder(...);
resourceBuilder
.addMethod(resourceMethod)
.handledBy(new Inflector<ContainerRequestContext, Response>() {
#Override
public Response apply(ContainerRequestContext containerRequestContext) {
...
}
});
}
}
However, I can't figure out how to call the original ResourceMethod here.
You might consider using Jersey Filters or Interceptors.
From the documentation:
https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest/filters-and-interceptors.html#d0e9368
Filters and interceptors can be used on both sides, on the client and
the server side. Filters can modify inbound and outbound requests and
responses including modification of headers, entity and other
request/response parameters. Interceptors are used primarily for
modification of entity input and output streams. You can use
interceptors for example to zip and unzip output and input entity
streams.
Interceptors share a common API for the server and the client side.
Whereas filters are primarily intended to manipulate request and
response parameters like HTTP headers, URIs and/or HTTP methods,
interceptors are intended to manipulate entities, via manipulating
entity input/output streams. If you for example need to encode entity
body of a client request then you could implement an interceptor to do
the work for you.
So I think you want to use Interceptor because they will wrap the resource call and you will have access in the same method both before the resource call and after the resource call.
You might also go with Filters, but you will have to break your code to RequestFilter and ResponseFilter.
I have a LoginHandler and an Interceptor. I want the Interceptor to execute before the AuthenticationFilter. Is there a way to specify the order of execution?
UPDATED:
The title mentioned LoginHandler. I changed it to AuthenticationFilter.
A HandlerInterceptor from Spring will never execute before a filter.
The javax.servlet.Filter is part of the Java Servlet API and requests always first pass through Filter instances, before reaching a Servlet.
HandlerInterceptor instances are executed as part of the request handling inside the DispatcherServlet (which implements javax.servlet.Servlet). As mentioned the flow is Filter -> Servlet the result is that a HandlerInterceptor will always execute after a Filter.
So is what you want possible, no it isn't. No matter how much ordering you add to the HandlerInterceptor.
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");
In my current Spring Boot application i seem to hit a wall when trying to implement a REST request filter. My goal with the request filter was to read the header and body part and validate the incoming data and check if it meets the HMAC construction we are using.
So the request filter seemed not to work an alternative solutions is to use #ControllerAdvice.
Then the request validation can be implemented very easy. But i am not sure if it normally seen as an incorrect usage of the #ControllerAdvice annotation.
#ControllerAdvice
public class GenericWebControllerAdvice {
#ModelAttribute
public void authenticationFilter(#RequestHeader(value = "Authorization") String authHeader, #RequestBody String payload) {
// process authentication based on header info and body content
// calculate the hash and check if meets the security settings
// if the hash fails throw an exception that returns a http status code
}
}
Any comments on the solution or alternatives that are better?
No you should do the validation in the controller (ie method with #RequestMapping).
Spring supports JSR 303/349 bean validation. Thus if your request body is a POJO and you have the correct annotation Spring will automatically do the validation for you. There is a tutorial of that here:
http://www.leveluplunch.com/java/tutorials/017-validate-spring-rest-webservice-request/
As for request parameter validation (ie not bean validation) I have had to make my own transfer objects and exception handling. How you do global exception handling is covered in the Spring Reference guide but generally you extend and/or register a org.springframework.web.servlet.handler.SimpleMappingExceptionResolver. Ironically #ControllerAdvice can be used for exception handling but I find it better to extend and register an Exception Resolver. More info can be found here:
https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers
Edit based on OP comments and edits:
If your doing authentication or some other request based validation/authorization its probably best to use an Interceptor. Reference doc. #ControllerAdvice will probably not work as the request handling is too far a long. That is you want something before databinding happens.