we use Twitter's Finagle client, which uses Netty as its HTTP client. We see for one of our web service calls that Netty is unable to determine the HTTP version of the response, resulting in
2017-01-13 11:28:13,825 [finagle/netty3-1] WARN com.twitter.finagle.netty3.channel.ChannelStatsHandler ChannelStatsHandler caught an exception
java.lang.IllegalArgumentException: invalid version format: <!DOCTYPE
Netty's org.jboss.netty.handler.codec.http.HttpVersion
class is trying to determine the HTTP version (HTTP/1.1, HTTP/1.0) based on the string <!DOCTYPE
. That is obviously not going to work. The match fails resulting in the IllegalArgumentException above.
I don't receive a response in my application at all because of this. Netty throws an exception and that's it.
My question is why Netty could be using <!DOCTYPE
as input to the HTTP version match in class HttpVersion.
When I use CURL to call the service for which this problem occurs I get a proper response with a proper HTTP version. Below are the HTTP headers that curl returns. I also get a proper body, that does NOT start with <!DOCTYPE
. It is a well-formed SOAP response that starts with <SOAP-ENVELOPE..
.
HTTP/1.1 200 OK
Date: Fri, 13 Jan 2017 12:25:14 GMT
Server: Apache-Coyote/1.1
Content-Type: text/xml;charset=utf-8
Connection: close
Transfer-Encoding: chunked
My guess is that the failing call occurs because some itermediate system returns a 'broken' response, that I have been unable to trigger with CURL. So my second question would be if it is possible at all for a system to return a response without Http version and if I am thinking in the right direction here.
We were using https without setting the withTls option on the Finagle client.
The solution for us was to create the Finagle client using the com.twitter.finagle.Http.withTls(String hostName)
option and, in our particular case, to also set Java's SSL context to TLS version 1.2:
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLSv1.2");
SSLContext.setDefault(sslContext );
} catch (NoSuchAlgorithmException e) {
log.error("Failure getting ssl context", e);
}
After these changes the problem disappeared.