feign icon indicating copy to clipboard operation
feign copied to clipboard

Can't set Content-type for Request Header when use Spring annotations

Open sdlzhd opened this issue 4 years ago • 9 comments

I'm using Feign and Spring annotations, I have a request that expects to accept "text/plain".

@PostMapping(value = "/demo", consumes = "application/json", produces="text/plain")
public String demo(@RequestBody List<Long> ids);

But, the produces value not working. The request still has a header: Accept=application/json

sdlzhd avatar Jun 10 '20 07:06 sdlzhd

May be I got it wrong but your request produces (send using) text/plain and consumes (wait for result) app/json. Looks like "Accept=application/json" is ok here.

finnetrolle avatar Jun 10 '20 21:06 finnetrolle

@sdlzhd are you using feign-spring4 or feign support from springboot?

velo avatar Jun 10 '20 21:06 velo

I am using feign + feign-spring4 in the client app. In the server side, use spring boot.

I found the cause of the problem.

As you see the method declaration, the request template is Accept = "application/json", Content-Type="application/json".

My expected result is Accept = "text/plain", Content-Type="application/json" in client.

In the server side, the Controller:

@PostMapping(value = "/demo")
public String demo(@RequestBody List<Long> ids);

The server will accept a Content-Type = "application/json" request and return a Content-Type='text/plain' reponse.

The key to this problem is that when parsing @RequestBody, the wrong header is set. I think for the client, @RequestBody should be parsed as Content-Type="application/json", not Accept.

For the client, the best resolution order is:

  1. @RequestBody => Content-Type
  2. produces => Accept
  3. consumes => Content-Type

This will be easily consistent with Spring Boot.

sdlzhd avatar Jun 11 '20 05:06 sdlzhd

Any reply?

sdlzhd avatar Jun 23 '20 01:06 sdlzhd

I just ran into this issue on my own project, I believe the lines below seem to assume if you use the RequestBody annotation it should be handled the same as the produces declaration in the RequestMapping. https://github.com/OpenFeign/feign/blob/ae514aaf790c87804b245013044bd212d3786b92/spring4/src/main/java/feign/spring/SpringContract.java#L94-L96 I was able to ignore adding the RequestBody annotation on my contract interface and that seemed to work around this issue and still serialize a single request parameter as a json object in the request body and respect the produces field of my RequestMapping annotation. I didn't test if this work around is viable on a multiple parameter method call.

plnordquist avatar Sep 10 '20 20:09 plnordquist

We'll need to look into this more, but if anyone here is interested in taking this up, please do.

kdavisk6 avatar Dec 29 '20 17:12 kdavisk6

I think that when use @RequestBody , the server side should accept the Content-Type = "application/json" request. Here are some of my points:

  • when parsing @RequestBody ,it should use handleConsumesAnnotation(data, "application/json"); instead of handleProducesAnnotation(data, "application/json");
  • when parsing @ResponseBody ,it should use handleProducesAnnotation(data, "application/json"); instead of handleConsumesAnnotation(data, "application/json");

zwyStyle avatar Jun 22 '21 14:06 zwyStyle

If it hasn't been solved, I want to try it

lushaorong avatar Jul 01 '22 01:07 lushaorong

I can't say if was fixed or not, feel free to take a look

velo avatar Jul 01 '22 01:07 velo