I have 2 microservices, ProductStore and InvoiceStore.

I want ProductStore to provide product information through an API and InvoiceStore to call that API to get product information from ProductStore. But ProductStore needs Authorization information to check user authentication so I use @RequestHeader("Authorization") String auth as argument variable in my FeignAPI to send it to ProductStore. But it reported that he did not receive the Authorization data when i test it.

I use @RequestHeader like that because I see it in the examples of feign-reactive all feature

I don't know if I did something wrong somewhere or I misunderstood the usage of @RequestHeader.

Help me please! Here is my code.

My ProductStore provides API to be able to get product information.

    @GetMapping("products")
    public ResponseEntity<String> test(@RequestHeader("Authorization") String authorization) {
        log.debug("Authorization is {}", authorization);
        return ResponseEntity.ok().body("all products");
    }

And my InvoiceStore call that API with feign-reactive WebReactiveFeign.

I followed the instructions in the readme of Playtika feign-reactive and applied it to my project as follows

First, I write FeignAPI

@Headers({ "Accept: application/json" })
public interface FeignClientAPI {

    @RequestLine("GET /products")
    Mono<String> getProducts(@RequestHeader("Authorization") String authorization);
}

And then, I build the client in IvoiceService

@Service
@Transactional
public class InvoiceService {
    private final FeignClientAPI client = WebReactiveFeign.<FeignClientAPI>builder().target(FeignClientAPI.class, "http://localhost:8082");

    public Mono<String> testFeign(String authorization){
        log.debug("Call api with authorization: {}", authorization);
        return client.getTest(authorization);
    }
}

And then, I create an API

    @GetMapping("/invoice/test")
    public Mono<ResponseEntity<String>> getProducts(@RequestHeader("Authorization") String authorization) {
        return invoiceService.testFeign(authorization)
            .switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.NOT_FOUND)))
            .map(response -> ResponseEntity.ok().body(response));
    }

Finally, I shoot an GET request to localhost:8083/invoice/test and I got an error

{
    "title": "Internal Server Error",
    "status": 500,
    "detail": "[400 Bad Request] during [GET] to [http://localhost:8082/products] [FeignClientAPI#getTest(String)]: [{\n  \"title\" : \"Bad Request\",\n  \"status\" : 400,\n  \"detail\" : \"Required request header 'Authorization' for method parameter type String is not present\",\n  \"path\" : \"/products\",\n  \"message\" : \"error.http.400\"\n}]",
    "path": "/invoice/test",
    "message": "error.http.500"
}

Tell me where i did wrong, Please!!! Thank you for everything.

2

There are 2 best solutions below

2
On

your code is totally wrong and i think you should get compile time error because testFeign(String authorization) need a string input but when you call it ( invoiceService.testFeign().switchIfEmpty ... ) you are not passing any input to it.

i should check the main code ,but i think you are passing null value as authorization in client side ( probably ).

0
On

I found the solution to this problem.

I misinterpreted how to use reactive feign before, which resulted in it not working.

I've added @EnableReactiveFeignClients and @EnableFeignClients for my spring boot app

@EnableReactiveFeignClients
@EnableFeignClients
public class AnswerStoreApp {
// main method
}

and then, I create an interface with @ReactiveFeignClient(name = "my-other-service")

@ReactiveFeignClient(name = "my-other-service")
public interface FeignClientService {

    @GetMapping("/api/questions/test-feign")
    Mono<String> demo(@RequestHeader("Authorization") String authorize);

    // More request
}

finally, I can use FeignClientService to get the data that I need

@Autowired
private FeignClientService feignClientService;

// Some method

@GetMapping("/invoice/test")
    public Mono<ResponseEntity<String>> getProducts(@RequestHeader("Authorization") String authorization) {
        return feignClientService.testFeign(authorization)
            .switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.NOT_FOUND)))
            .map(response -> ResponseEntity.ok().body(response));
    }