I need to write a client with multiple methods that require the apiKey as query string param. Is it possible to allow the client's user to pass the api key only to the method withApiKey
, so I can avoid to request the apiKey as first parameter of each method?
public interface Client {
@RequestLine("GET /search/search?key={apiKey}&query={query}&limit={limit}&offset={offset}")
SearchResponse search(@Param("apiKey") String apiKey, @Param("query") String query, @Param("limit") Integer limit, @Param("offset") Integer offset);
@RequestLine("GET /product/attributes?key={apiKey}&products={products}")
List<Product> getProduct(@Param("apiKey") String apiKey, @Param("products") String products);
public class Builder {
private String basePath;
private String apiKey;
public Client build() {
return Feign.builder()
.encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
.client(new ApacheHttpClient())
.logger(new Slf4jLogger())
.logLevel(Logger.Level.FULL)
.target(Client.class, basePath);
}
public Builder withBasePath(String basePath) {
this.basePath = basePath;
return this;
}
public Builder withApiKey(String apiKey) {
this.apiKey = apiKey;
return this;
}
}
}
Depending on the setup request-interceptors might work: https://github.com/OpenFeign/feign#request-interceptors
Hopefully the example below will help.
You can swap the builder out for just the interface annotation and then move the configuration to a configuration class, if you are using spring it could be like:
@FeignClient(
name = "ClerkClient",
url = "${clery-client.url}", // instead of the withBasePath method
configuration = {ClerkClientConfiguration.class}
)
public interface Client {
Then the ClerkClientConfiguration class can define the required config beans including a ClerkClientInterceptor
public class ClerkClientConfiguration {
@Bean
public RequestInterceptor clerkClientInterceptor() {
return new ClerkClientInterceptor();
}
Then the interceptor can have a value picked up from the config and added to the queries (or header etc)
public class ClerkClientInterceptor implements RequestInterceptor {
@Value("${clerk-client.key}")
private String apiKey
@Override public void apply(RequestTemplate template) {
requestTemplate.query( "key", apiKey);
}