1

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.

loc.dang
  • 374
  • 3
  • 19
  • The InvoiceStore still gets 'Authorization' when i call its API but it doesn't seem to send that data to the ProductStore. – loc.dang Dec 23 '21 at 20:12

2 Answers2

2

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 ).

sajad
  • 113
  • 5
  • Oh sorry, I was missing this in the process of turning my code into a simple question to ask. I think I did something wrong in using `feign reactive`. When I enabled anonymous access at `localhost:8083/invoice/test` it worked. You must manually configure `feign reactive` to pass the `authorization header` instead of using the built-in configuration. I managed to do that but it didn't bring any good results for my project. Now I think the problem is with my consul configuration. Thank you for help. – loc.dang Dec 28 '21 at 05:32
  • I found 1 question about not transmitting authorization here [How to consume basic-authentication protected Restful web service via REACTIVE feign client](https://stackoverflow.com/questions/60609411/how-to-consume-basic-authentication-protected-restful-web-service-via-reactive-f) – loc.dang Dec 28 '21 at 05:42
0

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));
    }
loc.dang
  • 374
  • 3
  • 19