[
https://issues.apache.org/jira/browse/HTTPCLIENT-1522?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14324923#comment-14324923
]
Ivan Shcheklein commented on HTTPCLIENT-1522:
---------------------------------------------
This is not a bug, but it can be really useful to make it easier to retry after
the SNI problem. Let's face it - we need http client to work with real world,
not with some rfc-perfect illusion :)
The easiest way I came up with is the following:
{code:java}
public class CustomSSLSocketFactory extends SSLConnectionSocketFactory {
private final SocketConfig socketConfig;
private final String ENABLE_SNI = "__enable_sni__";
/*
* Implement any constructor you need for your particular application -
* SSLConnectionSocketFactory has many variants
*/
public CustomSSLSocketFactory(final SocketConfig sc, final SSLContext
sslContext, final HostnameVerifier verifier) {
super(sslContext, verifier);
this.socketConfig = sc;
}
/*
* Socket initialisation code is from
DefaultHttpClientConnectionOperator::connect
* Unfortunately we need this to create a new socket on a retry.
*/
private Socket createSocketCustom(final HttpContext context) throws
IOException {
Socket sock = super.createSocket(context);
sock.setSoTimeout(socketConfig.getSoTimeout());
sock.setReuseAddress(socketConfig.isSoReuseAddress());
sock.setTcpNoDelay(socketConfig.isTcpNoDelay());
sock.setKeepAlive(socketConfig.isSoKeepAlive());
final int linger = socketConfig.getSoLinger();
if (linger >= 0) {
sock.setSoLinger(true, linger);
}
return sock;
}
private Socket connectSocketSni(
final int connectTimeout,
final Socket socket,
final HttpHost host,
final InetSocketAddress remoteAddress,
final InetSocketAddress localAddress,
final HttpContext context,
final boolean enableSni) throws IOException {
try {
return super.connectSocket(connectTimeout, socket, host,
remoteAddress, localAddress, context);
} catch (SSLProtocolException e) {
if (enableSni && e.getMessage() != null &&
e.getMessage().equals("handshake alert: unrecognized_name")) {
TimesLoggers.httpworker.warn("Server received saw wrong SNI
host, retrying without SNI, host: " + host);
context.setAttribute(ENABLE_SNI, false);
// We need to create a new socket to retry (the first one is
closed after IOException)
// Is there a clean way to do this?
return connectSocketSni(connectTimeout,
createSocketCustom(context), host, remoteAddress, localAddress, context, false);
} else {
throw e;
}
}
}
@Override
public Socket connectSocket(
final int connectTimeout,
final Socket socket,
final HttpHost host,
final InetSocketAddress remoteAddress,
final InetSocketAddress localAddress,
final HttpContext context) throws IOException {
context.setAttribute(ENABLE_SNI, true);
return this.connectSocketSni(connectTimeout, socket, host,
remoteAddress, localAddress, context, true);
}
@Override
public Socket createLayeredSocket(
final Socket socket,
final String target,
final int port,
final HttpContext context) throws IOException {
Boolean enableSniValue = (Boolean) context.getAttribute(ENABLE_SNI);
boolean enableSni = enableSniValue == null || enableSniValue;
return super.createLayeredSocket(socket, enableSni ? target : "", port,
context);
}
}
{code}
The main problem with it is that we need to create a new socket on to retry
request without SNI and sockets are created and initialised in the
DefaultHttpClientConnectionOperator::connect. There is no way to call the
default, SocketConfig-aware factory to get an unconnected socket.
Probably it's not a bug, but it looks like a problem in socket creation
architecture. Probably it should be located in one place to be easily accessed
by descendants.
> SNI support
> -----------
>
> Key: HTTPCLIENT-1522
> URL: https://issues.apache.org/jira/browse/HTTPCLIENT-1522
> Project: HttpComponents HttpClient
> Issue Type: Bug
> Components: HttpClient
> Affects Versions: 4.3.4
> Reporter: Igor
>
> Running HttpRequest to https://touchpoint.tealeaveshealth.com/consume
> causes an error
> {code}
> javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name
> {code}
> to see how to fix, you can open
> *http://stackoverflow.com/questions/7615645/ssl-handshake-alert-unrecognized-name-error-since-upgrade-to-java-1-7-0*
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]