Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Cloud Netflix : Passing host request parameter via RequestInterceptor to FeignClient

I am building a Spring Cloud project (Brixton.M4 with Spring Boot 1.3.1) with Eureka, Zuul and FeignClient where I am trying to add multi tenancy support (Tenants are identified by subdomain : tenant1.myservice.com). To do so, I would like to somehow pass the original subdomain along requests that are forwarded from a service to the other via Feign but I can't seem to be able to find the right way to do it.

What I have is a client that exposes a @RestController which calls a @FeignClient to communicate with my backend which exposes server operations to the client through its own @RestController.

The @FeignClient using same interface as my @RestController on the server :

@FeignClient(name = "product")
public interface ProductService extends IProductService {

}

What I am currently trying to do is set a header in a RequestInterceptor :

@Component
public class MultiTenancyRequestInterceptor implements RequestInterceptor {

    private CurrentTenantProvider currentTenantProvider;

    @Autowired
    public MultiTenancyRequestInterceptor(CurrentTenantProvider currentTenantProvider) {
        this.currentTenantProvider = currentTenantProvider;
    }

    @Override
    public void apply(RequestTemplate template) {
        try {
            template.header("TENANT", currentTenantProvider.getTenant());
        } catch (Exception e) {
            // "oops"
        }
    }
}

My provider class is a simple component where I'm trying to inject a request / session scope bean :

@Component
public class CurrentTenantProvider {

    @Autowired
    private CurrentTenant currentTenant;
    //...
}

The bean (I tried both session and request scope) :

@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public CurrentTenant currentTenant() {
    return new CurrentTenant();
}

On the server, I use Hibernate multitenant provider that is supposed to catch the header value and use it to define which DB to connect to :

@Autowired
private HttpServletRequest httpRequest;

@Override
public String resolveCurrentTenantIdentifier() {
    return httpRequest.getHeader("TENANT");
}

It seems the Feign call to the server is done in another thread and out of the incoming request scope, so i'm not sure how to pass that value along.

It all works fine when I hardcode the tenant value in the RequestInterceptor so I know the rest is working properly.

I have also looked at many other posts about Zuul "X-Forwaded-For" header and cannot find it in the request received on the server. I have also tried adding a ZuulFilter to pass host name to next request but what I see is that original request to the Client is picked up by the ZuulFilter and I can add but not when the Feign request is sent to the backend service even if I map it in zuul (i guess that is intended ?).

I am not really sure what's the next step and would appreciate some suggestions.

like image 469
Damien Polegato Avatar asked Oct 31 '22 12:10

Damien Polegato


1 Answers

Hope that it's of any use for you but we're doing sth similar in Spring-Cloud-Sleuth but we're using a ThreadLocal to pass span between different libraries and approaches (including Feign + Hystrix).

Here is an example with the highlighted line where we retrieve the Span from the thread local: https://github.com/spring-cloud/spring-cloud-sleuth/blob/master/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceFeignClientAutoConfiguration.java#L123

like image 200
Marcin Grzejszczak Avatar answered Dec 04 '22 10:12

Marcin Grzejszczak