Feign is a great way to communicate between services and send data like a JSON request body, single header or multiple headers and much more. Spring Cloud has it’s own way of defining Feign clients, it’s done with Spring MVC annotations.
Usually it’s a common requirement that applications can localize messages. For localizing the messages, you might want to use your browser’s language, which is sent in the Accept-Language header.
Let’s consider the following structure for your application. One service which is called by the client, let’s call it test-app and one service which is called by the test-app service, let’s call it translator.
If you are communicating between test-app and translator with Feign, you will simply lose the original header information.
Fortunately, you can use Spring MVC annotations to pass the header to the translator service as a simple parameter.
Let’s see in practice, how you can implement this with Spring Boot.
One controller is needed for the translation service which looks the following:
@RestController("/message") public class TranslationController { @RequestMapping public MessageResponse message(@RequestHeader(value = "Accept-Language") String language) { String message = "english"; if (Locale.GERMANY.equals(Locale.forLanguageTag(language))) { message = "german"; } return new MessageResponse(message); } } class MessageResponse { private String message; // getters/setters/constructor omitted }
Of course, if it would be a real translation service, it should accept a message parameter as well and there are tons of other things to look out for if you are dealing with real translation, I just wanted to keep it simple for the sake of clarity.
The important thing here is that the controller method accepts a parameter which is coming from the Accept-Language HTTP header which we will pass with the Feign client on the app side.
On the app side, I have the Feign client in the following way:
@FeignClient(name = "translation", url = "http://localhost:9001") public interface TranslationClient { @RequestMapping("/message") MessageResponse message(@RequestHeader("Accept-Language") String language); }
As you can see, I used the very same Spring MVC annotation for passing the language header.
And here’s an example controller which triggers the functionality:
@RestController("/test") public class TestController { @Autowired private TranslationClient client; @RequestMapping public TestResponse get(@RequestHeader("Accept-Language") String language) { MessageResponse messageResponse = client.message(language); String message = messageResponse.getMessage(); return new TestResponse(message); } } class TestResponse { private String value; // getters/setters/constructor omitted }
Also don’t forget the @EnableFeignClients annotation from the Application class.
Now if you start both services and open your favorite REST client (e.g. Postman) and trigger the URL http://localhost:9000/test and put the necessary header (i.e. Accept-Language: de-DE ) information into the request, you will get the localized message.
The code can be found on my GitHub page. If you are interested in more topics, make sure you follow me on Twitter and shout out if you have questions.
I think it is a design flaw. Http headers should be passed along the servlet chain automatically.
I agree. The whole point of Feign is to abstract all network-related stuff.
Good day! Thank you very much, this information was very helpful. Have a nice day!