Использование @Headers с динамическими значениями в клиенте Feign + Spring Cloud (Brixton RC2)
Можно ли установить динамические значения в заголовок?
@FeignClient(name="Simple-Gateway")
interface GatewayClient {
@Headers("X-Auth-Token: {token}")
@RequestMapping(method = RequestMethod.GET, value = "/gateway/test")
String getSessionId(@Param("token") String token);
}
Регистрация реализации RequestInterceptor добавляет заголовок, но нет возможности динамически устанавливать значение заголовка
@Bean
public RequestInterceptor requestInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate template) {
template.header("X-Auth-Token", "some_token");
}
};
}
Я нашел следующую проблему в github, и один из комментаторов (lpborges) пытался сделать что-то подобное, используя заголовки в аннотации @RequestMapping
.
https://github.com/spring-cloud/spring-cloud-netflix/issues/288
С уважением
Ответы
Ответ 1
Решение состоит в использовании аннотации @RequestHeader вместо синтаксических аннотаций
@FeignClient(name="Simple-Gateway")
interface GatewayClient {
@RequestMapping(method = RequestMethod.GET, value = "/gateway/test")
String getSessionId(@RequestHeader("X-Auth-Token") String token);
}
Ответ 2
@RequestHeader не работал для меня. Что работало было:
@Headers("X-Auth-Token: {access_token}")
@RequestLine("GET /orders/{id}")
Order get(@Param("id") String id, @Param("access_token") String accessToken);
Ответ 3
У меня есть этот пример, и я использую @HeaderParam вместо @RequestHeader:
import rx.Single;
import javax.ws.rs.Consumes;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
@Consumes(MediaType.APPLICATION_JSON)
public interface FeignRepository {
@POST
@Path("/Vehicles")
Single<CarAddResponse> add(@HeaderParam(HttpHeaders.AUTHORIZATION) String authorizationHeader, VehicleDto vehicleDto);
}
Ответ 4
Я использую @HeaderMap
, поскольку это кажется очень удобным, если вы работаете с Open feign. Используя этот способ, вы можете передавать ключи и значения заголовка динамически.
@Headers({"Content-Type: application/json"})
public interface NotificationClient {
@RequestLine("POST")
String notify(URI uri, @HeaderMap Map<String, Object> headers, NotificationBody body);
}
Теперь создайте симулированный REST-клиент для вызова конечной точки службы, создайте карту свойств заголовка и передайте ее в параметре метода.
NotificationClient notificationClient = Feign.builder()
.encoder(new JacksonEncoder())
.decoder(customDecoder())
.target(Target.EmptyTarget.create(NotificationClient.class));
Map<String, Object> headers = new HashMap<>();
headers.put("x-api-key", "x-api-value");
ResponseEntity<String> response = notificationClient.notify(new URI("https://stackoverflow.com/example"), headers, new NotificationBody());
Ответ 5
https://github.com/spring-cloud/spring-cloud-netflix/issues/760
https://github.com/OpenFeign/feign/#basics
17.3 Creating Feign Clients Manually
http://cloud.spring.io/spring-cloud-static/Dalston.SR4/single/spring-cloud.html#_creating_feign_clients_manually
POJO:
public class User...
службы:
@RestController
public class HelloController ...
public User getUser(@RequestParam("name") String name) {
User user = new User();
user.setName(name + "[result]");
System.out.println("name: " + name);
return user;
}
...
клиент:
public interface HelloClient {
@RequestLine("POST /getUser?name={name}")
User getUser(@Param("name") String name);
}
использование:
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.Client;
public class Demo {
private HelloClient helloClient;
@Autowired
public Demo(Decoder decoder, Encoder encoder, Client client) {
this.userAnotherService = Feign.builder().client(client)
.encoder(encoder)
.decoder(decoder)
// for spring security
.requestInterceptor(new BasicAuthRequestInterceptor("username", "password"))
.target(UserAnotherService.class, "http://your-service-name");
}
...
...method...
// output --> hello spring cloud![result]
System.out.println(helloClient.getUser("hello spring cloud!").getName());
...