From a94dd51cd3ab2926cee35c38825692d51498846e Mon Sep 17 00:00:00 2001 From: GiviMAD Date: Sat, 2 Mar 2024 00:08:48 -0800 Subject: [PATCH] [net] Expose Jetty EndPoint in http requests (#4092) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miguel Álvarez --- .../http/internal/WebClientFactoryImpl.java | 55 ++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/internal/WebClientFactoryImpl.java b/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/internal/WebClientFactoryImpl.java index 367bed2af..43b3efa87 100644 --- a/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/internal/WebClientFactoryImpl.java +++ b/bundles/org.openhab.core.io.net/src/main/java/org/openhab/core/io/net/http/internal/WebClientFactoryImpl.java @@ -24,11 +24,20 @@ import javax.net.ssl.TrustManager; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpDestination; +import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.client.HttpProxy; +import org.eclipse.jetty.client.api.Connection; +import org.eclipse.jetty.client.http.HttpChannelOverHTTP; +import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; +import org.eclipse.jetty.client.http.HttpConnectionOverHTTP; +import org.eclipse.jetty.client.http.HttpReceiverOverHTTP; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.http2.client.HTTP2Client; +import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.util.Promise; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.websocket.client.WebSocketClient; @@ -235,7 +244,7 @@ public class WebClientFactoryImpl implements HttpClientFactory, WebSocketFactory try { logger.debug("creating http client for consumer {}", consumerName); - HttpClient httpClient = new HttpClient( + HttpClient httpClient = new HttpClient(new CustomHttpClientTransportOverHTTP(), sslContextFactory != null ? sslContextFactory : createSslContextFactory()); // If proxy is set as property (standard Java property), provide the proxy information to Jetty HTTP @@ -413,4 +422,48 @@ public class WebClientFactoryImpl implements HttpClientFactory, WebSocketFactory "unexpected checked exception during initialization of the Jetty HTTP/2 client", e); } } + + /** + * Extends the default {@link HttpClientTransportOverHTTP) but exposes the underling {@link EndPoint} of each + * request/response. + * It mimics the way it's done in higher Jetty Http client versions. + */ + private static class CustomHttpClientTransportOverHTTP extends HttpClientTransportOverHTTP { + @Override + @NonNullByDefault({}) + protected HttpConnectionOverHTTP newHttpConnection(EndPoint endPoint, HttpDestination destination, + Promise promise) { + return new HttpConnectionOverHTTP(endPoint, destination, promise) { + @Override + protected HttpChannelOverHTTP newHttpChannel() { + return new HttpChannelOverHTTP(this) { + @Override + protected HttpReceiverOverHTTP newHttpReceiver() { + return new CustomHttpReceiverOverHTTP(this); + } + }; + } + }; + } + + private static class CustomHttpReceiverOverHTTP extends HttpReceiverOverHTTP { + private final HttpChannelOverHTTP channel; + + public CustomHttpReceiverOverHTTP(HttpChannelOverHTTP channel) { + super(channel); + this.channel = channel; + } + + @Override + public boolean headerComplete() { + HttpExchange exchange = getHttpExchange(); + if (exchange != null) { + // Store the EndPoint is case of upgrades + exchange.getRequest().getConversation().setAttribute(EndPoint.class.getName(), + channel.getHttpConnection().getEndPoint()); + } + return super.headerComplete(); + } + } + } }