feign icon indicating copy to clipboard operation
feign copied to clipboard

GET request with empty body has Content-Length header with 0

Open cdwijayarathna opened this issue 2 years ago • 3 comments

I am using the following code to make a request to an endpoint fronted with an ALB.

Feign.builder()
        .logger(Slf4jLogger(MyApi::class.java))
        .logLevel(feign.Logger.Level.FULL)
        .encoder(JacksonEncoder(objectMapper))
        .decoder(JacksonDecoder(objectMapper))
        .requestInterceptor { template -> template.header("X-Api-Key", apiKey) }
        .client(ApacheHttp5Client())
        .target(Target.HardCodedTarget(MyApi::class.java, apiUrl))

I am using the client to send GET requests to my endpoint /api/service/account/xxxx with an empty request body. In the receiving end, I am noticing that there is a header Content-Length with value 0, which makes the request non-compliant with rfc7230. I am using feign 12.3 and httpclient5 5.2.1. How can I get rid of this unwanted header?

cdwijayarathna avatar Jun 16 '23 02:06 cdwijayarathna

I have tested this case as I have code from another task #2064

I run queries for java11, Apache HC 5 and its async variant. I have run it with Jackson encodings and without it.

All requests do not have the Content-Length header:

# Apache HC5
DEBUG feign.Logger - [Http2Server#get] ---> GET https://api.github.com/ HTTP/1.1
DEBUG feign.Logger - [Http2Server#get] Accept: */*
DEBUG feign.Logger - [Http2Server#get] User-Agent: http2-test
DEBUG feign.Logger - [Http2Server#get] X-Api-Key: qwerty
DEBUG feign.Logger - [Http2Server#get] ---> END HTTP (0-byte body)
...
# Apache HC5, acync
DEBUG feign.Logger - [AsyncHttp2Server#get] ---> GET https://api.github.com/ HTTP/1.1
DEBUG feign.Logger - [AsyncHttp2Server#get] Accept: */*
DEBUG feign.Logger - [AsyncHttp2Server#get] User-Agent: http2-test
DEBUG feign.Logger - [AsyncHttp2Server#get] X-Api-Key: qwerty
DEBUG feign.Logger - [AsyncHttp2Server#get] ---> END HTTP (0-byte body)
...
# java11
DEBUG feign.Logger - [Http2Server#get] ---> GET https://api.github.com/ HTTP/1.1
DEBUG feign.Logger - [Http2Server#get] Accept: */*
DEBUG feign.Logger - [Http2Server#get] User-Agent: http2-test
DEBUG feign.Logger - [Http2Server#get] X-Api-Key: qwerty
...
# Apache HC5, json
DEBUG feign.Logger - [JsonHttp2Server#contributors] ---> GET https://api.github.com/repos/OpenFeign/feign/contributors HTTP/1.1
DEBUG feign.Logger - [JsonHttp2Server#contributors] Accept: */*
DEBUG feign.Logger - [JsonHttp2Server#contributors] User-Agent: http2-test
DEBUG feign.Logger - [JsonHttp2Server#contributors] X-Api-Key: qwerty
DEBUG feign.Logger - [JsonHttp2Server#contributors] ---> END HTTP (0-byte body)
...
# Apache HC5, async json
DEBUG feign.Logger - [JsonAsyncHttp2Server#contributors] ---> GET https://api.github.com/repos/OpenFeign/feign/contributors HTTP/1.1
DEBUG feign.Logger - [JsonAsyncHttp2Server#contributors] Accept: */*
DEBUG feign.Logger - [JsonAsyncHttp2Server#contributors] User-Agent: http2-test
DEBUG feign.Logger - [JsonAsyncHttp2Server#contributors] X-Api-Key: qwerty
DEBUG feign.Logger - [JsonAsyncHttp2Server#contributors] ---> END HTTP (0-byte body)
...
# java11, json
DEBUG feign.Logger - [JsonHttp2Server#contributors] ---> GET https://api.github.com/repos/OpenFeign/feign/contributors HTTP/1.1
DEBUG feign.Logger - [JsonHttp2Server#contributors] Accept: */*
DEBUG feign.Logger - [JsonHttp2Server#contributors] User-Agent: http2-test
DEBUG feign.Logger - [JsonHttp2Server#contributors] X-Api-Key: qwerty
DEBUG feign.Logger - [JsonHttp2Server#contributors] ---> END HTTP (0-byte body)
...

Could you re-check this case? Maybe there are other annotations in MyApi or additional interceptors.

vitalijr2 avatar Jun 22 '23 09:06 vitalijr2

Hi @radio-rogal ,

Thanks for checking this, I spent a lot of time going back and forth with this and could not figure out where the exact issue was. I did my testing in Java 17 and 19. As per my current observations, it works when I use OkHttpClient instead of ApacheHttpClient and ApacheHttp5Client. So I went ahead with using OkHttpClient. I also noticed that the issue does not happen when I send the request directly using ApacheHttpClient without Feign.

cdwijayarathna avatar Jun 22 '23 10:06 cdwijayarathna

Hello @vitalijr2,

There is indeed other headers that are added to the request. If you try to ping a netcat, you will be able to see them:

public class Dummy {

	public static void main(String[] args) {
		var logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Main.class);
		logger.setLevel(Level.TRACE);

		var objectMapper = new ObjectMapper();

		var client = Feign.builder()
			.logger(new Slf4jLogger(logger))
			.logLevel(feign.Logger.Level.FULL)
			.encoder(new JacksonEncoder(objectMapper))
			.decoder(new JacksonDecoder(objectMapper))
			.requestInterceptor((template) -> template.header("X-Api-Key", "abc"))
			.client(new ApacheHttpClient())
			.target(HelloClient.class, "http://localhost:8888");

		client.ping();
	}

	public static interface HelloClient {

		@RequestLine("GET /ping")
		Pong ping();

	}

}

Produce:

14:51:45.690 [main] DEBUG dummy.Dummy -- [HelloClient#ping] ---> GET http://localhost:8888/ping HTTP/1.1
14:51:45.692 [main] DEBUG dummy.Dummy -- [HelloClient#ping] X-Api-Key: abc
14:51:45.693 [main] DEBUG dummy.Dummy -- [HelloClient#ping] ---> END HTTP (0-byte body)

And on the netcat:

$ nc -lkvn 8888
Connection received on 127.0.0.1 53643
GET /ping HTTP/1.1
X-Api-Key: abc
Accept: */*
Content-Length: 0
Host: localhost:8888
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.14 (Java/21.0.2)
Accept-Encoding: gzip,deflate

And you can clearly see Content-Length: 0.

Caceresenzo avatar Apr 25 '24 12:04 Caceresenzo