Feign + Ribbon request interception AFTER target host is choosen - netflix-feign

What I'm currently doing (which is very simple and convenient way):
Feign.builder()
.client(RibbonClient.create())
...
.requestInterceptor(new MyInterceptor())
But interception occur before ribbon actually resolve target host.
Problem is, that one header that I want to add, have to be created based on the name of the target host.
Is there anyway I can manipulate headers after host is resolved?

I have found following solution for this problem. Instead of using Feign interceptor I use RibbonClient delegate:
Feign.builder()
.client(RibbonClient.builder().delegate(new MyDelegate())
...
MyDelegate extends feign.Client.Default class and overrides public Response execute(Request request, Request.Options options) method.
In this way I can access target host by URI.create(request.url()).getHost().
Then I create new Request, add my header and run super.execute(newRequest, options) as the last instruction.

Related

Is a centralized processing of request header data possible?

Let me explain what my problem is:
In a Web API project I am facing the issue that every single request which is sent to my controller has to contain some header data which should be processed before the controller action runs.
So as far as I know, I could include a new argument on every single action and decorate it with a FromHeader Attribute. Currently there are about 2000 actions from several controllers where I would have to change the parameter signature. So it would be a much prettier solution, if I could centralize the processing of this header data.
I am looking for some code to overwrite which is between the constructor of the controller class and the execution of the controller's action. Does anybody know a method for overriding or a pattern to accomplish this requirement? May be there is a possibility to extend the routing to the action
public override void OnActionExecuting(ActionExecutingContext context)
{
/*
PUT YOUR CODE HERE ;-)
*/
base.OnActionExecuting(context);
}

Spring: Get Registered URL Pattern in Controller from HttpRequest

Is there a way to get the registered URL pattern (In Controller) from the incoming HTTP request.
For Example, If my controller code is
#RestController
#RequestMapping("greeting")
public class Greeting {
#GetMapping("/{text}")
public String echo(#PathVariable("text") String text) {
return text;
}
}
Incoming request is http://localhost:8080/greeting/Hello,
I want to get the mapping value /greeting/{text}. Can I achieve the same using any Interceptor or Handler?
I have registered all the original mapping URLs like /greeting/{text}, /users/find/{id} etc., and want to perform some validation if the incoming request falls into any of those registered requests. I could have achieve the same using one custom method level annotation but I don't want to change all the codes now. It would be nice if I can achieve the same from a single Interceptor or extending any spring handlers.
The above snippet is a sample one. I have 4 to 5 spring applications with different apis and want create a common security package which can achieve the same.
You can access this from
final String pattern = request.getAttribute(org.springframework.web.servlet.HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE):
Source: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/HandlerMapping.html#BEST_MATCHING_PATTERN_ATTRIBUTE
HttpServletRequest request
request.getCurrentUrl() can get the url

Retrofit and usage of absolute URLs

How can you handle in Retrofit absolute URLs for some calls?
I am using a combination of dagger, retrofit and OKHttp. I provide a #Singleton RestAdapter with the selected endpoint (Production, Staging, etc) which it is formed from the BASE URL.
#Provides
#Singleton
RestAdapter providesRestAdapter(Endpoint endpoint,
ObjectMapper jacksonObjectMapper,
Client client,
ApiRequestInterceptor headers) {
return new RestAdapter.Builder() //
.setClient(client) //
.setEndpoint(endpoint) //
.setConverter(new JacksonConverter(jacksonObjectMapper))
.setLogLevel(RestAdapter.LogLevel.FULL)
.setRequestInterceptor(headers) //
.build();
}
The problem is that the REST service, for some cases, returns the URL for the content to be loaded in ABSOLUTE format meaning something like http://someurl.com/resource?sort=ascendent and not the preferable /resouce?sort=ascendent (without the BASE_URL)
Now the question is how I can create the interface of the service to deal with such scenario?
I was thinking something like:
public interface PlaceholdersService {
#GET("{placeholderHref}")
public void getPlaceholder(#EncodedPath("placeholderHref") String placeholderHref);
}
The problem is that I am not sure if the BASE URL set in the Endpoint previously when creating the RestAdapter will be added (can't test it at the moment).
Another though was to create a new RestAdapter specially for this case with an Endpoint set to a null or empty string fixed point like Endpoints.newFixedEndpoint(null) or Endpoints.newFixedEndpoint("").
Any suggestions?
Thanks
Digging a little bit I just realised there is an open issue for this manner in Github https://github.com/square/retrofit/issues/333
It has been moved the discussion to the V2 of the library to discuss if will be supported or not in that version.
This means that if supported, won't do it for a while. Is there any suggestion or workaround you can suggest to surpass this issue for the moment?
I had a similar problem and I solved it by creating new adapter with specified URL and use an empty path in my interface. Here is my question and my own answer.
Hope it helps.

How to get complete path in grails controller

I want to use something similar to HttpServletRequest.getPathInfo(); which returns the entire path of request. This is used in java, I am trying to find something similar in Grails.
Thanks.
The request object is an instance of the Servlet API's HttpServletRequest interface.
You should try that in your controller : (in order to show the entire path of the request in the webpage)
def index = { render request.forwardURI }

Specify run time parameter dependency in Unity

I have a class which needs a string as a parameter in its constructor but this parameter will be decided by the calling code. At the same point of time, the life time of this class has to be tied to per HTTP request. So, I created a custom PerWebRequestTimelineManager and used that for my target type in the config file. But since the string in the constructor has to be dynamically determined, I cannot use the ConstructorInjection via the config file. I can use an abstract factory to solve the problem of dynamic dependency, but I am not sure about the implementation: Can you check the code below and validate the approach. Specifically the RegisterType and Resolve calls seem a bit out of place though the successive Resolve calls across the application will be able to retrieve the same instance.:
public class PerformanceTracerFactory : IPerformanceTracerFactory
{
private readonly IPerformanceTracer tracer;
public IPerformanceTracer CreateInstance(string operationTitle)
{
_container.RegisterType<IPerformanceTracer, PerformanceTracer>(new InjectionConstructor(operationTitle));
return _container.Resolve<IPerformanceTracer>();
}
}
Relevant portion of config file:
<register type="IPerformanceTracer" mapTo="PerformanceTracer">
<lifetime type="PerWebRequest"/>
</register>
<register type="IPerformanceTracerFactory" mapTo="PerformanceTracerFactory"/>
I have another question. In case if the above way of configuring and injecting the dependency using code is correct, then I think I do not need the config entries. I can always use the suitable overload to push the custom lifetime manager. In case, I would want to achieve the same thing using only config file, then how do I code the solution?
If you use a container-based factory you don't have to register/resolve your IPerformanceTracer in each call.
Register the mapping IPerformanceTracer --> PerformanceTracer once in your config file and use a ParameterOverride when you resolve your interface.
public IPerformanceTracer CreateInstance(string operationTitle)
{
return _container.Resolve<IPerformanceTracer>(new ParameterOverride("nameOfTheParameterInTheConstructorOfPerformanceTracer", operationTitle);
}

Resources