Connection endpoints to provide TLS details and protocol version

This commit is contained in:
Oleg Kalnichevski 2024-01-14 16:47:35 +01:00
parent 9d225a6517
commit 9833c35728
11 changed files with 171 additions and 0 deletions

View File

@ -0,0 +1,64 @@
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.hc.client5.http;
import javax.net.ssl.SSLSession;
import org.apache.hc.core5.annotation.Internal;
import org.apache.hc.core5.http.ProtocolVersion;
/**
* @since 5.4
*/
public final class EndpointInfo {
private final ProtocolVersion protocol;
private final SSLSession sslSession;
@Internal
public EndpointInfo(final ProtocolVersion protocol, final SSLSession sslSession) {
this.protocol = protocol;
this.sslSession = sslSession;
}
public ProtocolVersion getProtocol() {
return protocol;
}
public SSLSession getSslSession() {
return sslSession;
}
@Override
public String toString() {
return "EndpointInfo{" +
"protocol=" + protocol +
", sslSession=" + sslSession +
'}';
}
}

View File

@ -27,6 +27,7 @@
package org.apache.hc.client5.http.async;
import org.apache.hc.client5.http.EndpointInfo;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.annotation.Internal;
@ -133,6 +134,13 @@ public interface AsyncExecRuntime {
}
}
/**
* Returns information about the underlying endpoint when connected or {@code null} otherwise.
*/
default EndpointInfo getEndpointInfo() {
return null;
}
/**
* Validates the connection making sure it can be used to execute requests.
*

View File

@ -29,6 +29,7 @@ package org.apache.hc.client5.http.classic;
import java.io.IOException;
import org.apache.hc.client5.http.EndpointInfo;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.annotation.Internal;
@ -121,6 +122,13 @@ public interface ExecRuntime {
*/
void upgradeTls(HttpClientContext context) throws IOException;
/**
* Returns information about the underlying endpoint when connected or {@code null} otherwise.
*/
default EndpointInfo getEndpointInfo() {
return null;
}
/**
* Executes HTTP request using the given context.
*

View File

@ -30,6 +30,7 @@ package org.apache.hc.client5.http.impl.async;
import java.io.InterruptedIOException;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.hc.client5.http.EndpointInfo;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.async.AsyncExecRuntime;
import org.apache.hc.client5.http.config.RequestConfig;
@ -48,6 +49,8 @@ import org.apache.hc.core5.http.nio.command.RequestExecutionCommand;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.reactor.Command;
import org.apache.hc.core5.reactor.IOSession;
import org.apache.hc.core5.reactor.ssl.TlsDetails;
import org.apache.hc.core5.reactor.ssl.TransportSecurityLayer;
import org.apache.hc.core5.util.Identifiable;
import org.apache.hc.core5.util.TimeValue;
import org.apache.hc.core5.util.Timeout;
@ -233,6 +236,17 @@ class InternalH2AsyncExecRuntime implements AsyncExecRuntime {
throw new UnsupportedOperationException();
}
public EndpointInfo getEndpointInfo() {
final Endpoint endpoint = sessionRef.get();
if (endpoint != null && endpoint.session.isOpen()) {
if (endpoint.session instanceof TransportSecurityLayer) {
final TlsDetails tlsDetails = ((TransportSecurityLayer) endpoint.session).getTlsDetails();
return new EndpointInfo(HttpVersion.HTTP_2, tlsDetails != null ? tlsDetails.getSSLSession() : null);
}
}
return null;
}
@Override
public Cancellable execute(
final String id,

View File

@ -30,6 +30,7 @@ package org.apache.hc.client5.http.impl.async;
import java.io.InterruptedIOException;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.hc.client5.http.EndpointInfo;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.async.AsyncExecRuntime;
import org.apache.hc.client5.http.config.RequestConfig;
@ -266,6 +267,11 @@ class InternalHttpAsyncExecRuntime implements AsyncExecRuntime {
});
}
public EndpointInfo getEndpointInfo() {
final AsyncConnectionEndpoint endpoint = endpointRef.get();
return endpoint != null ? endpoint.getInfo() : null;
}
@Override
public Cancellable execute(
final String id, final AsyncClientExchangeHandler exchangeHandler, final HttpClientContext context) {

View File

@ -32,6 +32,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.hc.client5.http.EndpointInfo;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.classic.ExecRuntime;
import org.apache.hc.client5.http.config.RequestConfig;
@ -193,6 +194,12 @@ class InternalExecRuntime implements ExecRuntime, Cancellable {
manager.upgrade(endpoint, context);
}
@Override
public EndpointInfo getEndpointInfo() {
final ConnectionEndpoint endpoint = endpointRef.get();
return endpoint != null ? endpoint.getInfo() : null;
}
@Override
public ClassicHttpResponse execute(
final String id,

View File

@ -38,6 +38,7 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.hc.client5.http.DnsResolver;
import org.apache.hc.client5.http.EndpointInfo;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.config.ConnectionConfig;
@ -684,6 +685,18 @@ public class BasicHttpClientConnectionManager implements HttpClientConnectionMan
return requestExecutor.execute(request, getValidatedConnection(), context);
}
/**
* @since 5.4
*/
@Override
public EndpointInfo getInfo() {
final ManagedHttpClientConnection connection = this.connRef.get();
if (connection != null && connection.isOpen()) {
return new EndpointInfo(connection.getProtocolVersion(), connection.getSSLSession());
}
return null;
}
}
/**

View File

@ -36,6 +36,7 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.hc.client5.http.DnsResolver;
import org.apache.hc.client5.http.EndpointInfo;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.config.ConnectionConfig;
@ -773,5 +774,21 @@ public class PoolingHttpClientConnectionManager
return requestExecutor.execute(request, connection, context);
}
/**
* @since 5.4
*/
@Override
public EndpointInfo getInfo() {
final PoolEntry<HttpRoute, ManagedHttpClientConnection> poolEntry = poolEntryRef.get();
if (poolEntry != null) {
final ManagedHttpClientConnection connection = poolEntry.getConnection();
if (connection != null && connection.isOpen()) {
return new EndpointInfo(connection.getProtocolVersion(), connection.getSSLSession());
}
}
return null;
}
}
}

View File

@ -37,6 +37,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.hc.client5.http.DnsResolver;
import org.apache.hc.client5.http.EndpointInfo;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.config.ConnectionConfig;
@ -752,6 +753,19 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
Command.Priority.NORMAL);
}
@Override
public EndpointInfo getInfo() {
final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry = poolEntryRef.get();
if (poolEntry != null) {
final ManagedAsyncClientConnection connection = poolEntry.getConnection();
if (connection != null && connection.isOpen()) {
final TlsDetails tlsDetails = connection.getTlsDetails();
return new EndpointInfo(connection.getProtocolVersion(), tlsDetails != null ? tlsDetails.getSSLSession() : null);
}
}
return null;
}
}
/**

View File

@ -29,6 +29,7 @@ package org.apache.hc.client5.http.io;
import java.io.IOException;
import org.apache.hc.client5.http.EndpointInfo;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.Internal;
import org.apache.hc.core5.annotation.ThreadingBehavior;
@ -97,6 +98,15 @@ public abstract class ConnectionEndpoint implements ModalCloseable {
*/
public abstract void setSocketTimeout(Timeout timeout);
/**
* Returns information about the endpoint or {@code null} when not connected.
*
* @since 5.4
*/
public EndpointInfo getInfo() {
return null;
}
/**
* @since 5.4
*/

View File

@ -30,6 +30,7 @@ package org.apache.hc.client5.http.nio;
import java.io.IOException;
import java.util.concurrent.Future;
import org.apache.hc.client5.http.EndpointInfo;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.concurrent.BasicFuture;
@ -201,4 +202,13 @@ public abstract class AsyncConnectionEndpoint implements ModalCloseable {
return execute(id, requestProducer, responseConsumer, null, null, callback);
}
/**
* Returns information about the endpoint or {@code null} when not connected.
*
* @since 5.4
*/
public EndpointInfo getInfo() {
return null;
}
}