feign icon indicating copy to clipboard operation
feign copied to clipboard

Support Dynamic Targets

Open johnny2002 opened this issue 5 years ago • 7 comments

I am writting a RequestInterceptor, need to know current "Target" so that I can revise the url of the RequestTemplate. While, I found the RequestTemplate.target is still null when it come into RequestInterceptor.apply method. Suggest to put the "target" value before invoke the RequestInterceptors, and provide a getter of RequestTemplate.target.

johnny2002 avatar Jan 20 '20 03:01 johnny2002

So my suggested code illustrate:

In RequestTemplate, add:

public String target() {
    	return target;
    }

Then, the most important thing is that the target instance must not be null in RequestInterceptor.apply() method, so in SynchronousMethodHandler, add a line:

  public Object invoke(Object[] argv) throws Throwable {
    RequestTemplate template = buildTemplateFromArgs.create(argv);
    **template.target(this.target.name());**

Then in my interceptor:

    @Bean
    public RequestInterceptor cloudContextInterceptor() {
    	return new RequestInterceptor() {
    		@Override
			public void apply(RequestTemplate template) {
				String target = template.target();
				if (target.contains("$CLUSTER_ID")) {
					target = target.replace("$CLUSTER_ID", getClusterId(template));
					template.target(target);
				}

johnny2002 avatar Jan 20 '20 03:01 johnny2002

This is not really something that RequestInterceptor is meant for. The Target is immutable once created. Can you please explain what your intention is?

If you want to do dynamic host resolution, I suggest that you look into something like Ribbon or an alternative that can do that for you. Another option is to use our Request URI override support here:

https://github.com/OpenFeign/feign#interface-annotations

kdavisk6 avatar Jan 21 '20 18:01 kdavisk6

This is not really something that RequestInterceptor is meant for. The Target is immutable once created. Can you please explain what your intention is?

If you want to do dynamic host resolution, I suggest that you look into something like Ribbon or an alternative that can do that for you. Another option is to use our Request URI override support here:

https://github.com/OpenFeign/feign#interface-annotations

Our project is a very large application, need to divide a service to several cluster. e.g. CustomerService needs to be separated to CustomerService001, CustomerService002... Then we need will dispatch requests to different cluster according the customer number scope in RequestInterceptor. e.g. customer number from 0 to 1,000,000 will dispatch to CustomerService001, 1,000,001 to 2,000,000 dispatch to CustomerService002 ... We are not expected to change the target object, while we need the target name in RequestInterceptor.apply() method to determine whether we should dispatch the service to a cluster.

johnny2002 avatar Jan 23 '20 02:01 johnny2002

I think it must be very normal appeals to access the target. In my case, all micro service should sign the uri before request. The sign rule is common method and need know the app-name wihch define in @FiegnClient(name='xxx-service')

So can feign.SynchronousMethodHandler#invoke modify like this.

for (RequestInterceptor interceptor : requestInterceptors) {
  interceptor.apply(target,  template);
}

qrqhuang avatar Oct 10 '20 08:10 qrqhuang

I think it must be very normal appeals to access the target. In my case, all micro service should sign the uri before request. The sign rule is common method and need know the app-name wihch define in @FiegnClient(name='xxx-service')

So can feign.SynchronousMethodHandler#invoke modify like this.

for (RequestInterceptor interceptor : requestInterceptors) {
  interceptor.apply(target,  template);
}

https://blog.csdn.net/weixin_45357522/article/details/106745468

johnny2002 avatar Oct 12 '20 05:10 johnny2002

Based on these comments, what you are looking for is a DynamicTarget implementation or component available that allows users to provide a Consumer or Function that can resolve the endpoint at runtime. I can see the utility of this and I think that's a good idea.

I'll rename this issue to reflect the need. If there is enough interest, we'll convert this into an enhancement and move forward.

kdavisk6 avatar Dec 29 '20 19:12 kdavisk6

Based on these comments, what you are looking for is a DynamicTarget implementation or component available that allows users to provide a Consumer or Function that can resolve the endpoint at runtime. I can see the utility of this and I think that's a good idea.

I'll rename this issue to reflect the need. If there is enough interest, we'll convert this into an enhancement and move forward.

With 3.x, we can do it now. No need to change for this any more.

johnny2002 avatar Feb 05 '21 03:02 johnny2002