Base interface:

public interface SomeEndpoint {
    @RequestMapping(method = RequestMethod.GET, value = "/check")
    void check(@PathVariable("resource") String resource);
}

Feign client:

@FeignClient(value = "some-service", path = "/api/{resource}")
public interface SomeClient extends SomeEndpoint {
}

Usage example:

public class SomeTest {
    private final SomeClient someClient;

    @Autowired
    public SomeTest(SomeClient client) {
        this.someClient = someClient;
    }

    public void test() {
        someClient.check("hello");
    }
}

Output:

Exception in thread "main" java.lang.IllegalArgumentException: Illegal character in path at index 24: http://some-service/api/{resource}/check
 at java.net.URI.create(URI.java:852)
  at org.springframework.cloud.netflix.feign.ribbon.LoadBalancerFeignClient.execute(LoadBalancerFeignClient.java:56)
  at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:97)
  at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)
  at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
  at com.sun.proxy.$Proxy74.upload(Unknown Source)
  at SomeTest.test()
  ...
Caused by: java.net.URISyntaxException: Illegal character in path at index 24: http://some-service/api/{resourse}/check
  at java.net.URI$Parser.fail(URI.java:2848)
  at java.net.URI$Parser.checkChars(URI.java:3021)
  at java.net.URI$Parser.parseHierarchical(URI.java:3105)
  at java.net.URI$Parser.parse(URI.java:3053)
  at java.net.URI.<init>(URI.java:588)
  at java.net.URI.create(URI.java:850)
  ... 7 more

Comment From: ryanjbaxter

Curious to know if this only occurs when using a sub interface?

Comment From: yikjiunfs

I'm facing a similar issue as well. However I sub-classed the controller instead of the feign client.

Example code but should be similar.

@FeignClient("SomeService")
public interface FeignClient {
  @RequestMapping(path = "/{id}", method = RequestMethod.GET)
  getId(@PathVariable("id") long id)
}
public class BaseController {
  @Autowired
  FeignClient client;

  @RequestMapping(path = "/{id}", method = RequestMethod.GET)
  public String getId(@PathVariable("id") long id) {
    client.getId(id);
  }
}

@RequestController
@RequestMapping("/api")
public class Controller extends BaseController {
  @Override
  public String getId(@PathVariable("id") long id) {
    super.get(id);
  }
}

Error is

Caused by: java.lang.IllegalArgumentException: Illegal character in path at index 19: http://SomeService/{id}
 at java.net.URI.create(URI.java:852)
 at org.springframework.cloud.netflix.feign.ribbon.LoadBalancerFeignClient.execute(LoadBalancerFeignClient.java:56)
 at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:97)
 at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)
 at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:108)
 at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:301)
 at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:297)
 at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
 ... 28 common frames omitted

I've traced the error to this method in SynchronousMethodHandler where argv no longer contains the actual id anymore. Hence, the URI in downstream became http://SomeService/{id} instead of http://SomeService/1 as it should be.

@Override
  public Object invoke(Object[] argv) throws Throwable {
    RequestTemplate template = buildTemplateFromArgs.create(argv);

Comment From: ryanjbaxter

I guess I dont see the point in doing that. Why wouldnt Controller just use FeignClient directly?

Comment From: yikjiunfs

The use case here is that we're in the midst of transitioning our v1 APIs to v2 APIs. The above code lies in our gateway. Extending the old controller would allow us to retain all our v1 APIs while selectively route certain routes to the v2 APIs. In Controller, we would call super, then call FeignClientV2, and compare the results. This is to ensure that the v2 APIs are backward compatible with the old responses and that we don't break anything.

The fuller code probably looks like this.

@RequestController
@RequestMapping("/api")
public class Controller extends BaseController {
  @Autowired
  FeignClientV2 clientV2;

  @Override
  public String getId(@PathVariable("id") long id) {
    String oldResponse = super.get(id); // exception is thrown here
    String newResponse = clientV2.get(id);
    if (!oldResponse.equals(newResponse)) {
      // do some logging
    }
    return oldResponse;
  }
}

Sorry for not giving the full use case previously because it seems irrelevant to the issue at hand. Is this supposed to happen when sub-classing the controller? off-topic: Is there a better way to achieve what I want?

Comment From: spencergibb

Doesn't seem relevant to the feign issue

Comment From: spencergibb

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

Comment From: Jeevananthammoorthy

Hello Folks, Today i faced the same issue and i found the solution. The problem with my code snippet was,have passed null value for ID attribute. public String getId(@PathVariable("id") long id) so while making the feign request, url path variable attribute is not getting replaced with pathVariable(ID) rather then replacing the actual id value. When id as null -> http://SomeService/{id} When id as proper value -> id = 123 ->http://SomeService/123. Correct me, if am wrong @spencergibb Thanks