Spring-cloud-netflix: How to configure @FeignCient with an HTTPS url (non-Eureka)?

Created on 25 Jan 2018  路  7Comments  路  Source: spring-cloud/spring-cloud-netflix

Hi,

I have a feign client defined like:

@FeignClient(name = "authserverTokenService", path="/authserver", url="${authserver.server}", configuration = AuthServerTokenServiceConfig.class)

The authserver service is not registered with Eureka. We specify the url in a properties file.

If I put in my properties file:

authserver.server=localhost:8087

it resolves correctly to http://localhost:8087 (looks like FeignClientsRegistrar adds the protocol?).

But beyond my local dev box, it needs to hit an HTTPS service.

If I try:

authserver.server=https://localhost:8087

it gives me an error, because the final host/url is: http://https://localhost:8087

I've tried putting the URL into the name attribute (per some other threads that I saw), but then I get:

0:31:54.651 [RMI TCP Connection(2)-127.0.0.1] ERROR [fweb,,,] o.s.boot.SpringApplication - Application startup failed (SpringApplication.java:771) 
java.lang.IllegalStateException: Service id not legal hostname (${authserver.listOfServers})
    at org.springframework.util.Assert.state(Assert.java:70)
    at org.springframework.cloud.netflix.feign.FeignClientsRegistrar.getName(FeignClientsRegistrar.java:238)
    at org.springframework.cloud.netflix.feign.FeignClientsRegistrar.registerFeignClient(FeignClientsRegistrar.java:181)

i.e. it doesn't seem to like properties in the name attribute.

What is the correct way to configure an @FeignClient with a property-based HTTPS url?

Thanks in advance,

yngwietiger

Most helpful comment

Thanks for looking. Yeah, I figured out the issue. It wasn't just https, it was any url value that already had a protocol, http or https.

We have a legacy application that was converted to a Spring Boot application. In the old code, we instantiate a PropertySourcesPlaceholderConfigurer that looks into a few different files. I had my properties defined in one of those files (not in application.properties). So, when FeignClientsRegistrar.getUrl() was called, the property value for url wasn't resolving. So url was getting built as "http://${authserver.server}". Eventually, ${authserver.server} would get resolved to "https://localhost:8087", making the final url value "http://https://localhost:8087".

Once I placed the properties in application.properties, everything worked fine, since FeignClientsRegistrar.environment could see them.

Long term, we plan to clean up our properties files in a way that's more compatible with Spring Boot.

In the meantime, I'm able to work around the issue by using spEL for the property values. For example:

@FeignClient(name = "authserverTokenService", path="/authserver", url="#{'${authserver.url}'}", configuration = AuthServerTokenServiceConfig.class)

That was a product of this: https://github.com/spring-cloud/spring-cloud-netflix/issues/1522

That causes FeignClientsRegistrar.getUrl() to not try to prepend a protocol. And ultimately, the url resolves to my property value.

Thoughts?

All 7 comments

@yngwietiger what version?

Tried both Dalston.SR4 and Dalston.SR5. Neither worked for me.

Here's what I see in the logs. Seems the URL gets prepended with "http://".

Caused by: feign.RetryableException: https: nodename nor servname provided, or not known executing GET http://https://localhost:8087/authserver/token?<PARAMS HERE>
    at feign.FeignException.errorExecuting(FeignException.java:67)
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:102)
    at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)
    at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
    at com.sun.proxy.$Proxy246.getAccessTokenByClientCredentials(Unknown Source)

FeignClientsRegistrar.getUrl() doesn't seem like it would be a problem, since it looks for "://" before prepending.

Hmm, I wrote a test that uses an https url and it works just fine. Can you provide a minimal sample that recreates the problem?

Thanks for looking. Yeah, I figured out the issue. It wasn't just https, it was any url value that already had a protocol, http or https.

We have a legacy application that was converted to a Spring Boot application. In the old code, we instantiate a PropertySourcesPlaceholderConfigurer that looks into a few different files. I had my properties defined in one of those files (not in application.properties). So, when FeignClientsRegistrar.getUrl() was called, the property value for url wasn't resolving. So url was getting built as "http://${authserver.server}". Eventually, ${authserver.server} would get resolved to "https://localhost:8087", making the final url value "http://https://localhost:8087".

Once I placed the properties in application.properties, everything worked fine, since FeignClientsRegistrar.environment could see them.

Long term, we plan to clean up our properties files in a way that's more compatible with Spring Boot.

In the meantime, I'm able to work around the issue by using spEL for the property values. For example:

@FeignClient(name = "authserverTokenService", path="/authserver", url="#{'${authserver.url}'}", configuration = AuthServerTokenServiceConfig.class)

That was a product of this: https://github.com/spring-cloud/spring-cloud-netflix/issues/1522

That causes FeignClientsRegistrar.getUrl() to not try to prepend a protocol. And ultimately, the url resolves to my property value.

Thoughts?

I don't think there's anything we need to do. Feel free to comment if you think there is.

java.lang.IllegalStateException: Service id not legal hostname (${service.id.checkout-gateway})
at org.springframework.util.Assert.state(Assert.java:73)
at org.springframework.cloud.openfeign.FeignClientsRegistrar.getName(FeignClientsRegistrar.java:103)
at org.springframework.cloud.openfeign.FeignClientsRegistrar.getName(FeignClientsRegistrar.java:278)
at org.springframework.cloud.openfeign.FeignClientsRegistrar.registerFeignClient(FeignClientsRegistrar.java:233)
at org.springframework.cloud.openfeign.FeignClientsRegistrar.registerFeignClients(FeignClientsRegistrar.java:219)
at org.springframework.cloud.openfeign.FeignClientsRegistrar.registerBeanDefinitions(FeignClientsRegistrar.java:144)
at org.springframework.context.annotation.ImportBeanDefinitionRegistrar.registerBeanDefinitions(ImportBeanDefinitionRegistrar.java:86)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.lambda$loadBeanDefinitionsFromRegistrars$1(ConfigurationClassBeanDefinitionReader.java:385)
at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromRegistrars(ConfigurationClassBeanDefinitionReader.java:384)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:148)

Getting this,
is the issue with resolving config from yml file?

Was this page helpful?
0 / 5 - 0 ratings