From 48e0f25b1cba6dd686e5570ebdcc0d8c5ad1997f Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 21 Oct 2025 21:50:16 +0200 Subject: [PATCH 01/36] HttpClient 5.6-alpha1 release --- httpclient5-cache/pom.xml | 2 +- httpclient5-fluent/pom.xml | 2 +- httpclient5-observation/pom.xml | 4 ++-- httpclient5-testing/pom.xml | 4 ++-- httpclient5/pom.xml | 4 ++-- pom.xml | 6 +++--- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/httpclient5-cache/pom.xml b/httpclient5-cache/pom.xml index e1d30f756f..bc26795d53 100644 --- a/httpclient5-cache/pom.xml +++ b/httpclient5-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha1-SNAPSHOT + 5.6-alpha1 httpclient5-cache Apache HttpClient Cache diff --git a/httpclient5-fluent/pom.xml b/httpclient5-fluent/pom.xml index 85b5b6cc6f..d2642b78b7 100644 --- a/httpclient5-fluent/pom.xml +++ b/httpclient5-fluent/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha1-SNAPSHOT + 5.6-alpha1 httpclient5-fluent Apache HttpClient Fluent diff --git a/httpclient5-observation/pom.xml b/httpclient5-observation/pom.xml index 6cb5260aaa..36dc07bf34 100644 --- a/httpclient5-observation/pom.xml +++ b/httpclient5-observation/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha1-SNAPSHOT + 5.6-alpha1 httpclient5-observation @@ -148,4 +148,4 @@ - + \ No newline at end of file diff --git a/httpclient5-testing/pom.xml b/httpclient5-testing/pom.xml index ffc73b9385..e1a5d377b0 100644 --- a/httpclient5-testing/pom.xml +++ b/httpclient5-testing/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha1-SNAPSHOT + 5.6-alpha1 httpclient5-testing Apache HttpClient Integration Tests @@ -159,4 +159,4 @@ - + \ No newline at end of file diff --git a/httpclient5/pom.xml b/httpclient5/pom.xml index 4003210b9d..3dbba9987b 100644 --- a/httpclient5/pom.xml +++ b/httpclient5/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha1-SNAPSHOT + 5.6-alpha1 httpclient5 Apache HttpClient @@ -206,4 +206,4 @@ - + \ No newline at end of file diff --git a/pom.xml b/pom.xml index cc21e55cc1..4b66dec620 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ org.apache.httpcomponents.client5 httpclient5-parent Apache HttpComponents Client Parent - 5.6-alpha1-SNAPSHOT + 5.6-alpha1 Apache HttpComponents Client is a library of components for building client side HTTP services https://hc.apache.org/httpcomponents-client-5.5.x/${project.version}/ 1999 @@ -48,7 +48,7 @@ scm:git:https://gitbox.apache.org/repos/asf/httpcomponents-client.git scm:git:https://gitbox.apache.org/repos/asf/httpcomponents-client.git https://github.com/apache/httpcomponents-client/tree/${project.scm.tag} - 5.6-alpha1-SNAPSHOT + 5.6-alpha1 @@ -533,4 +533,4 @@ - + \ No newline at end of file From 77f52f0e3e49952731f10ad250549e5c85198de4 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 26 Oct 2025 10:13:25 +0100 Subject: [PATCH 02/36] Upgraded HttpClient version to 5.6-alpha2-SNAPSHOT --- httpclient5-cache/pom.xml | 2 +- httpclient5-fluent/pom.xml | 2 +- httpclient5-observation/pom.xml | 2 +- httpclient5-testing/pom.xml | 2 +- httpclient5/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/httpclient5-cache/pom.xml b/httpclient5-cache/pom.xml index bc26795d53..d42bbcd757 100644 --- a/httpclient5-cache/pom.xml +++ b/httpclient5-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha1 + 5.6-alpha2-SNAPSHOT httpclient5-cache Apache HttpClient Cache diff --git a/httpclient5-fluent/pom.xml b/httpclient5-fluent/pom.xml index d2642b78b7..af08a07fde 100644 --- a/httpclient5-fluent/pom.xml +++ b/httpclient5-fluent/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha1 + 5.6-alpha2-SNAPSHOT httpclient5-fluent Apache HttpClient Fluent diff --git a/httpclient5-observation/pom.xml b/httpclient5-observation/pom.xml index 36dc07bf34..c54c368729 100644 --- a/httpclient5-observation/pom.xml +++ b/httpclient5-observation/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha1 + 5.6-alpha2-SNAPSHOT httpclient5-observation diff --git a/httpclient5-testing/pom.xml b/httpclient5-testing/pom.xml index e1a5d377b0..7a5bb72bf3 100644 --- a/httpclient5-testing/pom.xml +++ b/httpclient5-testing/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha1 + 5.6-alpha2-SNAPSHOT httpclient5-testing Apache HttpClient Integration Tests diff --git a/httpclient5/pom.xml b/httpclient5/pom.xml index 3dbba9987b..bbcf4d4733 100644 --- a/httpclient5/pom.xml +++ b/httpclient5/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha1 + 5.6-alpha2-SNAPSHOT httpclient5 Apache HttpClient diff --git a/pom.xml b/pom.xml index 4b66dec620..dab00409cc 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ org.apache.httpcomponents.client5 httpclient5-parent Apache HttpComponents Client Parent - 5.6-alpha1 + 5.6-alpha2-SNAPSHOT Apache HttpComponents Client is a library of components for building client side HTTP services https://hc.apache.org/httpcomponents-client-5.5.x/${project.version}/ 1999 @@ -48,7 +48,7 @@ scm:git:https://gitbox.apache.org/repos/asf/httpcomponents-client.git scm:git:https://gitbox.apache.org/repos/asf/httpcomponents-client.git https://github.com/apache/httpcomponents-client/tree/${project.scm.tag} - 5.6-alpha1 + 5.6-alpha2-SNAPSHOT From e52e46668ff3463745c0e8c1973212ed01289ece Mon Sep 17 00:00:00 2001 From: Ryan Schmitt Date: Sun, 26 Oct 2025 02:34:45 -0700 Subject: [PATCH 03/36] TestTlsHandshakeTimeout: Disable assertions on Java 8 (cherry picked from commit 8767978952506c6792d117aab19fdedb68110bd7) --- .../testing/sync/TestTlsHandshakeTimeout.java | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestTlsHandshakeTimeout.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestTlsHandshakeTimeout.java index b763a71f50..ca93b2c63a 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestTlsHandshakeTimeout.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestTlsHandshakeTimeout.java @@ -47,7 +47,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import javax.net.ssl.SSLException; import java.time.Duration; import java.time.temporal.ChronoUnit; @@ -55,7 +54,6 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.apache.hc.core5.util.ReflectionUtils.determineJRELevel; -import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeFalse; @@ -97,23 +95,20 @@ void testTimeout(final boolean sendServerHello) throws Exception { @SuppressWarnings("deprecation") private static void assertTimeout(final ClassicHttpRequest request, final HttpClient client) { - final long startTime = System.nanoTime(); - final Exception ex = assertThrows(Exception.class, () -> client.execute(request)); - final Duration actualTime = Duration.of(System.nanoTime() - startTime, ChronoUnit.NANOS); + // There is a bug in Java 11, and some releases of Java 8: after the + // handshake times out, the SSLSocket implementation performs a + // blocking read on the socket to wait for close_notify or alert. This + // operation blocks until the read times out, which means that TLS + // handshakes take twice as long to time out on Java 11. Without a + // workaround, the only option is to skip the timeout assertions on + // older versions of Java. + assumeFalse(determineJRELevel() <= 11, "TLS handshake timeouts are buggy on Java 11 and earlier"); - if (determineJRELevel() == 8) { - assertInstanceOf(SSLException.class, ex); - } else { - assertInstanceOf(ConnectTimeoutException.class, ex); - } + final long startTime = System.nanoTime(); + final ConnectTimeoutException ex = assertThrows(ConnectTimeoutException.class, () -> client.execute(request)); assertTrue(ex.getMessage().contains("Read timed out"), ex.getMessage()); - // There is a bug in Java 11: after the handshake times out, the SSLSocket implementation performs a blocking - // read on the socket to wait for close_notify or alert. This operation blocks until the read times out, - // which means that TLS handshakes take twice as long to time out on Java 11. Without a workaround, the only - // option is to skip the timeout duration assertions on Java 11. - assumeFalse(determineJRELevel() == 11, "TLS handshake timeouts are buggy on Java 11"); - + final Duration actualTime = Duration.of(System.nanoTime() - startTime, ChronoUnit.NANOS); assertTrue(actualTime.toMillis() > EXPECTED_TIMEOUT.toMillis() / 2, format("Handshake attempt timed out too soon (only %,d out of %,d ms)", actualTime.toMillis(), From d2fadd2f0ecb2905ea869be8cf1b984b9562714a Mon Sep 17 00:00:00 2001 From: Ryan Schmitt Date: Sun, 26 Oct 2025 13:02:31 -0700 Subject: [PATCH 04/36] Tag TLS handshake timeout tests with `slow` These tests don't run reliably on the GitHub CI fleet. I am marking them with `@Tag("slow")`, which will cause them to run only when the `slow-tests` Maven profile is enabled. We can do the same with any other timing-sensitive tests that fail spuriously when running on shared build fleets. (cherry picked from commit 929f5216ea594c36d2a7d0a4d059d1b78a3a70c3) --- .../hc/client5/testing/async/TestAsyncTlsHandshakeTimeout.java | 2 ++ .../apache/hc/client5/testing/sync/TestTlsHandshakeTimeout.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncTlsHandshakeTimeout.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncTlsHandshakeTimeout.java index ee05837874..aca39d38d0 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncTlsHandshakeTimeout.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncTlsHandshakeTimeout.java @@ -38,6 +38,7 @@ import org.apache.hc.client5.testing.tls.TlsHandshakeTimeoutServer; import org.apache.hc.core5.reactor.IOReactorConfig; import org.apache.hc.core5.util.TimeValue; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Timeout; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -57,6 +58,7 @@ public class TestAsyncTlsHandshakeTimeout { private static final Duration EXPECTED_TIMEOUT = Duration.ofMillis(500); + @Tag("slow") @Timeout(5) @ParameterizedTest @ValueSource(strings = { "false", "true" }) diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestTlsHandshakeTimeout.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestTlsHandshakeTimeout.java index ca93b2c63a..a11378e31a 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestTlsHandshakeTimeout.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestTlsHandshakeTimeout.java @@ -43,6 +43,7 @@ import org.apache.hc.client5.testing.tls.TlsHandshakeTimeoutServer; import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.io.SocketConfig; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Timeout; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -61,6 +62,7 @@ public class TestTlsHandshakeTimeout { private static final Duration EXPECTED_TIMEOUT = Duration.ofMillis(500); + @Tag("slow") @Timeout(5) @ParameterizedTest @ValueSource(strings = { "false", "true" }) From 1f4dea7e75b5e6171fb9becdf9920f2e8c41de8a Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 7 Dec 2025 17:59:24 +0100 Subject: [PATCH 05/36] Fixed Micrometer and OpenTelemetry dependency declaration --- httpclient5-observation/pom.xml | 31 +++++++++---------------------- pom.xml | 21 +++++++++------------ 2 files changed, 18 insertions(+), 34 deletions(-) diff --git a/httpclient5-observation/pom.xml b/httpclient5-observation/pom.xml index c54c368729..29cfe761aa 100644 --- a/httpclient5-observation/pom.xml +++ b/httpclient5-observation/pom.xml @@ -36,18 +36,6 @@ Optional Micrometer / OpenTelemetry support for HttpClient jar - - - - io.opentelemetry - opentelemetry-bom - 1.49.0 - pom - import - - - - org.apache.httpcomponents.client5.observation @@ -87,17 +75,23 @@ io.micrometer micrometer-registry-prometheus + test - io.opentelemetry - opentelemetry-sdk - runtime + io.micrometer + micrometer-tracing + test io.micrometer micrometer-tracing-bridge-otel test + + io.opentelemetry + opentelemetry-sdk + test + io.opentelemetry opentelemetry-sdk-testing @@ -113,13 +107,6 @@ commons-compress test - - - io.micrometer - micrometer-tracing - ${micrometer.tracing.version} - test - org.junit.jupiter junit-jupiter-api diff --git a/pom.xml b/pom.xml index dab00409cc..7595fa090d 100644 --- a/pom.xml +++ b/pom.xml @@ -82,7 +82,7 @@ 1.5.7-4 1.15.2 1.5.2 - 1.52.0 + 1.49.0 1.26.2 @@ -219,37 +219,34 @@ io.micrometer micrometer-core ${micrometer.version} - true io.micrometer micrometer-observation ${micrometer.version} - true io.micrometer micrometer-registry-prometheus ${micrometer.version} - true io.micrometer - micrometer-tracing-bridge-otel + micrometer-tracing ${micrometer.tracing.version} - true + test - io.opentelemetry - opentelemetry-sdk - ${otel.version} - true + io.micrometer + micrometer-tracing-bridge-otel + ${micrometer.tracing.version} io.opentelemetry - opentelemetry-sdk-testing + opentelemetry-bom ${otel.version} - test + pom + import com.aayushatharva.brotli4j From 2c7fe0fc04669fc0cc856519a8cd324f81c030d6 Mon Sep 17 00:00:00 2001 From: Arturo Bernal Date: Fri, 12 Dec 2025 09:07:10 +0100 Subject: [PATCH 06/36] Add OFFLOCK pool concurrency policy backed by RouteSegmentedConnPool (#765) Wire PoolingHttpClientConnectionManager to use RouteSegmentedConnPool when OFFLOCK is selected. --- .../http/impl/io/PoolingHttpClientConnectionManager.java | 9 +++++++++ .../impl/nio/PoolingAsyncClientConnectionManager.java | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java index ecd134f86b..3604268db7 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java @@ -79,6 +79,7 @@ import org.apache.hc.core5.pool.PoolEntry; import org.apache.hc.core5.pool.PoolReusePolicy; import org.apache.hc.core5.pool.PoolStats; +import org.apache.hc.core5.pool.RouteSegmentedConnPool; import org.apache.hc.core5.pool.StrictConnPool; import org.apache.hc.core5.util.Args; import org.apache.hc.core5.util.Deadline; @@ -272,6 +273,14 @@ public void closeExpired() { }; break; + case OFFLOCK: + this.pool = new RouteSegmentedConnPool<>( + DEFAULT_MAX_CONNECTIONS_PER_ROUTE, + DEFAULT_MAX_TOTAL_CONNECTIONS, + timeToLive, + poolReusePolicy, + new DefaultDisposalCallback<>()); + break; default: throw new IllegalArgumentException("Unexpected PoolConcurrencyPolicy value: " + poolConcurrencyPolicy); } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java index abae03ffd1..6078a92352 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java @@ -86,6 +86,7 @@ import org.apache.hc.core5.pool.PoolEntry; import org.apache.hc.core5.pool.PoolReusePolicy; import org.apache.hc.core5.pool.PoolStats; +import org.apache.hc.core5.pool.RouteSegmentedConnPool; import org.apache.hc.core5.pool.StrictConnPool; import org.apache.hc.core5.reactor.Command; import org.apache.hc.core5.reactor.ConnectionInitiator; @@ -208,6 +209,14 @@ public void closeExpired() { }; break; + case OFFLOCK: + managedConnPool = new RouteSegmentedConnPool<>( + DEFAULT_MAX_CONNECTIONS_PER_ROUTE, + DEFAULT_MAX_TOTAL_CONNECTIONS, + timeToLive, + poolReusePolicy, + new DefaultDisposalCallback<>()); + break; default: throw new IllegalArgumentException("Unexpected PoolConcurrencyPolicy value: " + poolConcurrencyPolicy); } From 81b79711c186678253702de34c5126302364a449 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 14 Dec 2025 16:08:36 +0100 Subject: [PATCH 07/36] Upgraded HttpCore to version 5.4 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7595fa090d..da92bda039 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ 1.8 1.8 - 5.4-alpha1 + 5.4 2.25.0 1.20.0 2.5.2 From 77fa61aae9fe492eb81e321073441646856775e1 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 15 Dec 2025 10:23:19 +0100 Subject: [PATCH 08/36] Limit the length of content codec list that can be processed automatically --- .../http/impl/ContentCodingSupport.java | 10 ++++++ .../async/ContentCompressionAsyncExec.java | 16 ++++++++-- .../impl/async/HttpAsyncClientBuilder.java | 2 +- .../impl/classic/ContentCompressionExec.java | 19 ++++++++++-- .../InflatingAsyncEntityConsumerTest.java | 2 +- .../InflatingBrotliDataConsumerTest.java | 2 +- .../TestContentCompressionAsyncExec.java | 2 +- .../classic/TestContentCompressionExec.java | 31 +++++++++++++++++++ 8 files changed, 75 insertions(+), 9 deletions(-) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ContentCodingSupport.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ContentCodingSupport.java index 441c0d3295..5d794b9f33 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ContentCodingSupport.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/ContentCodingSupport.java @@ -28,12 +28,14 @@ package org.apache.hc.client5.http.impl; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; import org.apache.hc.core5.annotation.Internal; import org.apache.hc.core5.http.EntityDetails; +import org.apache.hc.core5.http.ProtocolException; import org.apache.hc.core5.http.message.MessageSupport; import org.apache.hc.core5.http.message.ParserCursor; @@ -43,6 +45,8 @@ @Internal public final class ContentCodingSupport { + public static final int MAX_CODEC_LIST_LEN = 5; + private ContentCodingSupport() { } @@ -62,4 +66,10 @@ public static List parseContentCodecs(final EntityDetails entityDetails) return codecs; } + public static void validate(final Collection codecList, final int maxCodecListLen) throws ProtocolException { + if (maxCodecListLen > 0 && codecList.size() > maxCodecListLen) { + throw new ProtocolException("Codec list exceeds maximum of " + maxCodecListLen + " elements"); + } + } + } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/ContentCompressionAsyncExec.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/ContentCompressionAsyncExec.java index d8c9a6aa4b..04d5ed7962 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/ContentCompressionAsyncExec.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/ContentCompressionAsyncExec.java @@ -67,23 +67,29 @@ public final class ContentCompressionAsyncExec implements AsyncExecChainHandler private final Lookup> decoders; private final List acceptTokens; + private final int maxCodecListLen; public ContentCompressionAsyncExec( final LinkedHashMap> decoderMap, - final boolean ignoreUnknown) { - + final int maxCodecListLen) { Args.notEmpty(decoderMap, "Decoder map"); final RegistryBuilder> rb = RegistryBuilder.create(); decoderMap.forEach(rb::register); this.decoders = rb.build(); this.acceptTokens = new ArrayList<>(decoderMap.keySet()); + this.maxCodecListLen = maxCodecListLen; + } + + public ContentCompressionAsyncExec( + final LinkedHashMap> decoderMap) { + this(decoderMap, ContentCodingSupport.MAX_CODEC_LIST_LEN); } /** * Default: DEFLATE + GZIP (plus x-gzip alias). */ - public ContentCompressionAsyncExec() { + public ContentCompressionAsyncExec(final int maxCodecListLen) { final LinkedHashMap> map = new LinkedHashMap<>(); map.put(ContentCoding.DEFLATE.token(), d -> new InflatingAsyncDataConsumer(d, null)); map.put(ContentCoding.GZIP.token(), InflatingGzipDataConsumer::new); @@ -109,8 +115,12 @@ public ContentCompressionAsyncExec() { this.decoders = rb.build(); this.acceptTokens = tokens; + this.maxCodecListLen = maxCodecListLen; } + public ContentCompressionAsyncExec() { + this(ContentCodingSupport.MAX_CODEC_LIST_LEN); + } @Override public void execute( diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java index b2f55bba79..d2968a5bfc 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java @@ -1100,7 +1100,7 @@ public CloseableHttpAsyncClient build() { if (!contentCompressionDisabled) { if (contentDecoderMap != null && !contentDecoderMap.isEmpty()) { execChainDefinition.addFirst( - new ContentCompressionAsyncExec(contentDecoderMap, true), + new ContentCompressionAsyncExec(contentDecoderMap), ChainElement.COMPRESS.name()); } else { execChainDefinition.addFirst( diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ContentCompressionExec.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ContentCompressionExec.java index f4da426ecb..fc7ed56c0b 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ContentCompressionExec.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ContentCompressionExec.java @@ -72,16 +72,25 @@ public final class ContentCompressionExec implements ExecChainHandler { private final Header acceptEncoding; private final Lookup> decoderRegistry; + private final int maxCodecListLen; public ContentCompressionExec( final List acceptEncoding, - final Lookup> decoderRegistry) { + final Lookup> decoderRegistry, + final int maxCodecListLen) { this.acceptEncoding = MessageSupport.headerOfTokens(HttpHeaders.ACCEPT_ENCODING, Args.notEmpty(acceptEncoding, "Encoding list")); this.decoderRegistry = Args.notNull(decoderRegistry, "Decoder register"); + this.maxCodecListLen = maxCodecListLen; } - public ContentCompressionExec() { + public ContentCompressionExec( + final List acceptEncoding, + final Lookup> decoderRegistry) { + this(acceptEncoding, decoderRegistry, ContentCodingSupport.MAX_CODEC_LIST_LEN); + } + + public ContentCompressionExec(final int maxCodecListLen) { final Map> decoderMap = new EnumMap<>(ContentCoding.class); for (final ContentCoding c : ContentCoding.values()) { final UnaryOperator d = ContentCodecRegistry.decoder(c); @@ -103,6 +112,11 @@ public ContentCompressionExec() { } this.acceptEncoding = MessageSupport.headerOfTokens(HttpHeaders.ACCEPT_ENCODING, acceptList); this.decoderRegistry = builder.build(); + this.maxCodecListLen = maxCodecListLen; + } + + public ContentCompressionExec() { + this(ContentCodingSupport.MAX_CODEC_LIST_LEN); } @Override @@ -128,6 +142,7 @@ public ClassicHttpResponse execute( // check for zero length entity. if (requestConfig.isContentCompressionEnabled() && entity != null && entity.getContentLength() != 0) { final List codecs = ContentCodingSupport.parseContentCodecs(entity); + ContentCodingSupport.validate(codecs, maxCodecListLen); if (!codecs.isEmpty()) { for (int i = codecs.size() - 1; i >= 0; i--) { final String codec = codecs.get(i); diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/async/methods/InflatingAsyncEntityConsumerTest.java b/httpclient5/src/test/java/org/apache/hc/client5/http/async/methods/InflatingAsyncEntityConsumerTest.java index fca30dc825..308bfe4cfe 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/async/methods/InflatingAsyncEntityConsumerTest.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/async/methods/InflatingAsyncEntityConsumerTest.java @@ -204,7 +204,7 @@ public Set getTrailerNames() { void unknownEncodingMapFlag() throws Exception { final LinkedHashMap> map = new LinkedHashMap<>(); map.put("deflate", d -> new InflatingAsyncDataConsumer(d, null)); - final ContentCompressionAsyncExec exec = new ContentCompressionAsyncExec(map, false); + final ContentCompressionAsyncExec exec = new ContentCompressionAsyncExec(map); assertNotNull(exec); } } diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/async/methods/InflatingBrotliDataConsumerTest.java b/httpclient5/src/test/java/org/apache/hc/client5/http/async/methods/InflatingBrotliDataConsumerTest.java index 8446d28307..230e0936ec 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/async/methods/InflatingBrotliDataConsumerTest.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/async/methods/InflatingBrotliDataConsumerTest.java @@ -195,7 +195,7 @@ public Set getTrailerNames() { void registerInExec() { final LinkedHashMap> map = new LinkedHashMap<>(); map.put("br", InflatingBrotliDataConsumer::new); - final ContentCompressionAsyncExec exec = new ContentCompressionAsyncExec(map, false); + final ContentCompressionAsyncExec exec = new ContentCompressionAsyncExec(map); assertNotNull(exec); } } diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/TestContentCompressionAsyncExec.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/TestContentCompressionAsyncExec.java index a02ddb45d4..8cf3a181d7 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/TestContentCompressionAsyncExec.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/TestContentCompressionAsyncExec.java @@ -163,7 +163,7 @@ public AsyncDataConsumer apply(final AsyncDataConsumer d) { return new InflatingAsyncDataConsumer(d, null); } }); - impl = new ContentCompressionAsyncExec(map, /*ignoreUnknown*/ false); + impl = new ContentCompressionAsyncExec(map); final HttpRequest request = new BasicHttpRequest(Method.GET, "/"); final AsyncExecCallback cb = executeAndCapture(request); diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestContentCompressionExec.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestContentCompressionExec.java index d9c5151d67..44711e82f7 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestContentCompressionExec.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestContentCompressionExec.java @@ -40,6 +40,7 @@ import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.Method; +import org.apache.hc.core5.http.ProtocolException; import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.http.message.BasicClassicHttpRequest; import org.apache.hc.core5.http.message.BasicClassicHttpResponse; @@ -236,4 +237,34 @@ void testContentEncodingRequestParameter() throws Exception { Assertions.assertFalse(entity instanceof GzipDecompressingEntity); } + @Test + void testContentEncodingExceedsCodecListLenMax() throws Exception { + impl = new ContentCompressionExec(5); + + final ClassicHttpRequest request = new BasicClassicHttpRequest(Method.GET, host, "/"); + final ClassicHttpResponse response1 = new BasicClassicHttpResponse(200, "OK"); + final HttpEntity original1 = EntityBuilder.create() + .setText("encoded stuff") + .setContentEncoding("gzip,gzip,gzip,gzip,gzip") + .build(); + response1.setEntity(original1); + + Mockito.when(execChain.proceed(request, scope)).thenReturn(response1); + + final HttpEntity entity = response1.getEntity(); + Assertions.assertNotNull(entity); + + final ClassicHttpResponse response2 = new BasicClassicHttpResponse(200, "OK"); + final HttpEntity original2 = EntityBuilder.create() + .setText("encoded stuff") + .setContentEncoding("gzip,gzip,gzip,gzip,gzip,gzip") + .build(); + response2.setEntity(original2); + + Mockito.when(execChain.proceed(request, scope)).thenReturn(response2); + + final ProtocolException exception = Assertions.assertThrows(ProtocolException.class, () -> impl.execute(request, scope, execChain)); + Assertions.assertEquals("Codec list exceeds maximum of 5 elements", exception.getMessage()); + } + } From 11ea8e52b7e970871bfbbb53e8c601b111ae2be6 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 14 Dec 2025 16:25:19 +0100 Subject: [PATCH 09/36] Updated release notes for HttpClient 5.6 release --- RELEASE_NOTES.txt | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 2f343a4822..8dc4d71a6d 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,10 +1,10 @@ -Release 5.6 ALPHA1 +Release 5.6 ------------------ -This is the first ALPHA release in the 5.6 release series. It adds several features -such as transport content decompression and content compression for the async transport, -support for Unix sockets, experimental support for SCRAM-SHA-256 authentication scheme, -and Micrometer/OTel observations & metrics. +This is the first GA release in the 5.6 release series. It adds several features such as +transport content decompression and content compression for the async transport, support +for Unix sockets, experimental support for SCRAM-SHA-256 authentication scheme, and +Micrometer/OTel observations & metrics. Commons Compress, Brotli codec, and ZStd codec are optional dependencies and get wired into the execution pipeline only if present on the classpath. @@ -28,6 +28,8 @@ Notable changes and features included in the 5.6 series: * Request Priority support (RFC 9218). Experimental. +* OFFLOCK connection pool concurrency policy. Experimental. + Compatibility notes: @@ -40,6 +42,31 @@ Compatibility notes: Change Log ------------------- +* Limit the length of the content codec list that can be processed automatically. + Contributed by Oleg Kalnichevski + +* Upgraded HttpCore to version 5.4 + Contributed by Oleg Kalnichevski + +* OFFLOCK connection pool concurrency policy backed by RouteSegmentedConnPool (#765). + Contributed by Arturo Bernal + + + +Release 5.6 ALPHA1 +------------------ + +This is the first ALPHA release in the 5.6 release series. It adds several features +such as transport content decompression and content compression for the async transport, +support for Unix sockets, experimental support for SCRAM-SHA-256 authentication scheme, +and Micrometer/OTel observations & metrics. + +Commons Compress, Brotli codec, and ZStd codec are optional dependencies and get +wired into the execution pipeline only if present on the classpath. + +Change Log +------------------- + * RequestConfig: Un-deprecate #setProxy. Contributed by Ryan Schmitt From 2ddb0c1fbd5d4f18ef000545669e6c2713bbd6d7 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 17 Dec 2025 10:06:20 +0100 Subject: [PATCH 10/36] Limit the length of content codec list that can be processed automatically (corrected) --- .../async/ContentCompressionAsyncExec.java | 1 + .../TestContentCompressionAsyncExec.java | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/ContentCompressionAsyncExec.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/ContentCompressionAsyncExec.java index 04d5ed7962..d685b39cd2 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/ContentCompressionAsyncExec.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/ContentCompressionAsyncExec.java @@ -149,6 +149,7 @@ public AsyncDataConsumer handleResponse(final HttpResponse rsp, } final List codecs = ContentCodingSupport.parseContentCodecs(details); + ContentCodingSupport.validate(codecs, maxCodecListLen); if (!codecs.isEmpty()) { AsyncDataConsumer downstream = cb.handleResponse(rsp, wrapEntityDetails(details)); for (int i = codecs.size() - 1; i >= 0; i--) { diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/TestContentCompressionAsyncExec.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/TestContentCompressionAsyncExec.java index 8cf3a181d7..09b2abfefd 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/TestContentCompressionAsyncExec.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/TestContentCompressionAsyncExec.java @@ -57,6 +57,7 @@ import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.Method; +import org.apache.hc.core5.http.ProtocolException; import org.apache.hc.core5.http.message.BasicHttpRequest; import org.apache.hc.core5.http.message.BasicHttpResponse; import org.apache.hc.core5.http.nio.AsyncDataConsumer; @@ -185,4 +186,32 @@ void testCompressionDisabledViaRequestConfig() throws Exception { assertFalse(request.containsHeader(HttpHeaders.ACCEPT_ENCODING)); } + + @Test + void testContentEncodingExceedsCodecListLenMax() throws Exception { + final HttpRequest request = new BasicHttpRequest(Method.GET, "/"); + final AsyncExecCallback cb = executeAndCapture(request); + + final HttpResponse rsp1 = new BasicHttpResponse(200, "OK"); + final EntityDetails details1 = mock(EntityDetails.class); + when(details1.getContentEncoding()).thenReturn("gzip,gzip,gzip,gzip,gzip"); + + final AsyncDataConsumer downstream1 = new StringAsyncEntityConsumer(); + when(originalCb.handleResponse(same(rsp1), same(details1))).thenReturn(downstream1); + + final AsyncDataConsumer wrapped = cb.handleResponse(rsp1, details1); + + assertNotNull(wrapped); + + final HttpResponse rsp2 = new BasicHttpResponse(200, "OK"); + final EntityDetails details2 = mock(EntityDetails.class); + when(details2.getContentEncoding()).thenReturn("gzip,gzip,gzip,gzip,gzip,gzip"); + + final AsyncDataConsumer downstream2 = new StringAsyncEntityConsumer(); + when(originalCb.handleResponse(same(rsp2), same(details2))).thenReturn(downstream2); + + final ProtocolException exception = assertThrows(ProtocolException.class, () -> cb.handleResponse(rsp2, details2)); + assertEquals("Codec list exceeds maximum of 5 elements", exception.getMessage()); + } + } \ No newline at end of file From 60e96590804e456b0eb99166d685bff5a7796644 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 17 Dec 2025 10:37:00 +0100 Subject: [PATCH 11/36] HttpClient 5.6 release --- httpclient5-cache/pom.xml | 2 +- httpclient5-fluent/pom.xml | 2 +- httpclient5-observation/pom.xml | 2 +- httpclient5-testing/pom.xml | 2 +- httpclient5/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/httpclient5-cache/pom.xml b/httpclient5-cache/pom.xml index d42bbcd757..1fa8d6c36e 100644 --- a/httpclient5-cache/pom.xml +++ b/httpclient5-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha2-SNAPSHOT + 5.6 httpclient5-cache Apache HttpClient Cache diff --git a/httpclient5-fluent/pom.xml b/httpclient5-fluent/pom.xml index af08a07fde..f510009e39 100644 --- a/httpclient5-fluent/pom.xml +++ b/httpclient5-fluent/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha2-SNAPSHOT + 5.6 httpclient5-fluent Apache HttpClient Fluent diff --git a/httpclient5-observation/pom.xml b/httpclient5-observation/pom.xml index 29cfe761aa..ebb52f36fc 100644 --- a/httpclient5-observation/pom.xml +++ b/httpclient5-observation/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha2-SNAPSHOT + 5.6 httpclient5-observation diff --git a/httpclient5-testing/pom.xml b/httpclient5-testing/pom.xml index 7a5bb72bf3..e8b096bc41 100644 --- a/httpclient5-testing/pom.xml +++ b/httpclient5-testing/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha2-SNAPSHOT + 5.6 httpclient5-testing Apache HttpClient Integration Tests diff --git a/httpclient5/pom.xml b/httpclient5/pom.xml index bbcf4d4733..1656afa1db 100644 --- a/httpclient5/pom.xml +++ b/httpclient5/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6-alpha2-SNAPSHOT + 5.6 httpclient5 Apache HttpClient diff --git a/pom.xml b/pom.xml index da92bda039..67bbbd749f 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ org.apache.httpcomponents.client5 httpclient5-parent Apache HttpComponents Client Parent - 5.6-alpha2-SNAPSHOT + 5.6 Apache HttpComponents Client is a library of components for building client side HTTP services https://hc.apache.org/httpcomponents-client-5.5.x/${project.version}/ 1999 @@ -48,7 +48,7 @@ scm:git:https://gitbox.apache.org/repos/asf/httpcomponents-client.git scm:git:https://gitbox.apache.org/repos/asf/httpcomponents-client.git https://github.com/apache/httpcomponents-client/tree/${project.scm.tag} - 5.6-alpha2-SNAPSHOT + 5.6 From f04367f0af87991304801eaea037753bce2e9648 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 20 Dec 2025 12:18:01 +0100 Subject: [PATCH 12/36] Upgraded HttpClient version to 5.6.1-SNAPSHOT --- httpclient5-cache/pom.xml | 2 +- httpclient5-fluent/pom.xml | 2 +- httpclient5-observation/pom.xml | 2 +- httpclient5-testing/pom.xml | 2 +- httpclient5/pom.xml | 2 +- pom.xml | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/httpclient5-cache/pom.xml b/httpclient5-cache/pom.xml index 1fa8d6c36e..ffec1e1bf6 100644 --- a/httpclient5-cache/pom.xml +++ b/httpclient5-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6 + 5.6.1-SNAPSHOT httpclient5-cache Apache HttpClient Cache diff --git a/httpclient5-fluent/pom.xml b/httpclient5-fluent/pom.xml index f510009e39..264a0eca56 100644 --- a/httpclient5-fluent/pom.xml +++ b/httpclient5-fluent/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6 + 5.6.1-SNAPSHOT httpclient5-fluent Apache HttpClient Fluent diff --git a/httpclient5-observation/pom.xml b/httpclient5-observation/pom.xml index ebb52f36fc..52d78dd638 100644 --- a/httpclient5-observation/pom.xml +++ b/httpclient5-observation/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6 + 5.6.1-SNAPSHOT httpclient5-observation diff --git a/httpclient5-testing/pom.xml b/httpclient5-testing/pom.xml index e8b096bc41..0158ea90f0 100644 --- a/httpclient5-testing/pom.xml +++ b/httpclient5-testing/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6 + 5.6.1-SNAPSHOT httpclient5-testing Apache HttpClient Integration Tests diff --git a/httpclient5/pom.xml b/httpclient5/pom.xml index 1656afa1db..94ec434a6d 100644 --- a/httpclient5/pom.xml +++ b/httpclient5/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6 + 5.6.1-SNAPSHOT httpclient5 Apache HttpClient diff --git a/pom.xml b/pom.xml index 67bbbd749f..d1e83adb35 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ org.apache.httpcomponents.client5 httpclient5-parent Apache HttpComponents Client Parent - 5.6 + 5.6.1-SNAPSHOT Apache HttpComponents Client is a library of components for building client side HTTP services https://hc.apache.org/httpcomponents-client-5.5.x/${project.version}/ 1999 @@ -48,7 +48,7 @@ scm:git:https://gitbox.apache.org/repos/asf/httpcomponents-client.git scm:git:https://gitbox.apache.org/repos/asf/httpcomponents-client.git https://github.com/apache/httpcomponents-client/tree/${project.scm.tag} - 5.6 + 5.6.1-SNAPSHOT From 0056ecd582502fa66b17df10882cac45fb21a32d Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 20 Dec 2025 14:45:44 +0100 Subject: [PATCH 13/36] Disable japicmp report for observation module --- httpclient5-observation/pom.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/httpclient5-observation/pom.xml b/httpclient5-observation/pom.xml index 52d78dd638..7d6a743bee 100644 --- a/httpclient5-observation/pom.xml +++ b/httpclient5-observation/pom.xml @@ -135,4 +135,16 @@ + + + + com.github.siom79.japicmp + japicmp-maven-plugin + + true + + + + + \ No newline at end of file From abf74893d38ea2fa04fd0fe21ba7271303671224 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 20 Dec 2025 15:02:17 +0100 Subject: [PATCH 14/36] Upgraded HttpClient API level to 5.6 --- pom.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index d1e83adb35..2141ebdc3b 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 3.1.10 1.21.3 2.10.1 - 5.3 + 5.6 javax.net.ssl.SSLEngine,javax.net.ssl.SSLParameters,java.nio.ByteBuffer,java.nio.CharBuffer,jdk.net.ExtendedSocketOptions,jdk.net.Sockets 1.27.1 1.5.7-4 @@ -283,9 +283,9 @@ maven-javadoc-plugin - https://hc.apache.org/httpcomponents-core-5.3.x/current/httpcore5/apidocs/ - https://hc.apache.org/httpcomponents-core-5.3.x/current/httpcore5-h2/apidocs/ - https://hc.apache.org/httpcomponents-client-5.5.x/current/httpclient5/apidocs/ + https://hc.apache.org/httpcomponents-core-5.4.x/current/httpcore5/apidocs/ + https://hc.apache.org/httpcomponents-core-5.4.x/current/httpcore5-h2/apidocs/ + https://hc.apache.org/httpcomponents-client-5.6.x/current/httpclient5/apidocs/ @@ -453,8 +453,8 @@ true true - https://hc.apache.org/httpcomponents-core-5.3.x/current/httpcore5/apidocs/ - https://hc.apache.org/httpcomponents-core-5.0.x/httpcore5-h2/apidocs/ + https://hc.apache.org/httpcomponents-core-5.4.x/current/httpcore5/apidocs/ + https://hc.apache.org/httpcomponents-core-5.4.x/current/httpcore5-h2/apidocs/ ${project.url}/httpclient5/apidocs/ From ce821420fbff6a45b2ba4ed75add7e8e4cb2dbbf Mon Sep 17 00:00:00 2001 From: Arturo Bernal Date: Thu, 25 Dec 2025 19:11:38 +0000 Subject: [PATCH 15/36] Fix NPE in connection evictor setup (#774) Builders computed evictor sleep time from maxIdleTime even when only evictExpiredConnections() was enabled, causing an NPE. (cherry picked from commit bbc3ac34a30457dc42bb28281f578c991f3ebd45) --- .../http/impl/async/HttpAsyncClientBuilder.java | 7 ++++--- .../http/impl/classic/HttpClientBuilder.java | 7 ++++--- .../impl/classic/TestHttpAsyncClientBuilder.java | 13 +++++++++++++ .../http/impl/classic/TestHttpClientBuilder.java | 10 ++++++++++ 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java index d2968a5bfc..bdcc390635 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java @@ -866,7 +866,7 @@ public final HttpAsyncClientBuilder evictExpiredConnections() { */ public final HttpAsyncClientBuilder evictIdleConnections(final TimeValue maxIdleTime) { this.evictIdleConnections = true; - this.maxIdleTime = maxIdleTime; + this.maxIdleTime = Args.notNull(maxIdleTime, "Max idle time"); return this; } @@ -1146,10 +1146,11 @@ public CloseableHttpAsyncClient build() { } if (evictExpiredConnections || evictIdleConnections) { if (connManagerCopy instanceof ConnPoolControl) { - TimeValue sleepTime = maxIdleTime.divide(10, TimeUnit.NANOSECONDS); + final TimeValue maxIdleTimeCopy = evictIdleConnections ? maxIdleTime : null; + TimeValue sleepTime = maxIdleTimeCopy != null ? maxIdleTimeCopy.divide(10, TimeUnit.NANOSECONDS) : ONE_SECOND; sleepTime = sleepTime.compareTo(ONE_SECOND) < 0 ? ONE_SECOND : sleepTime; final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor((ConnPoolControl) connManagerCopy, - sleepTime, maxIdleTime); + sleepTime, maxIdleTimeCopy); closeablesCopy.add(connectionEvictor::shutdown); connectionEvictor.start(); } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java index 0f8c811284..3c9f837cb7 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java @@ -780,7 +780,7 @@ public final HttpClientBuilder evictExpiredConnections() { */ public final HttpClientBuilder evictIdleConnections(final TimeValue maxIdleTime) { this.evictIdleConnections = true; - this.maxIdleTime = maxIdleTime; + this.maxIdleTime = Args.notNull(maxIdleTime, "Max idle time"); return this; } @@ -1115,10 +1115,11 @@ public CloseableHttpClient build() { } if (evictExpiredConnections || evictIdleConnections) { if (connManagerCopy instanceof ConnPoolControl) { - TimeValue sleepTime = maxIdleTime.divide(10, TimeUnit.NANOSECONDS); + final TimeValue maxIdleTimeCopy = evictIdleConnections ? maxIdleTime : null; + TimeValue sleepTime = maxIdleTimeCopy != null ? maxIdleTimeCopy.divide(10, TimeUnit.NANOSECONDS) : ONE_SECOND; sleepTime = sleepTime.compareTo(ONE_SECOND) < 0 ? ONE_SECOND : sleepTime; final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor((ConnPoolControl) connManagerCopy, - sleepTime, maxIdleTime); + sleepTime, maxIdleTimeCopy); closeablesCopy.add(() -> { connectionEvictor.shutdown(); try { diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestHttpAsyncClientBuilder.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestHttpAsyncClientBuilder.java index ac15ce15d6..ad66bbc8d6 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestHttpAsyncClientBuilder.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestHttpAsyncClientBuilder.java @@ -31,10 +31,13 @@ import org.apache.hc.client5.http.async.AsyncExecCallback; import org.apache.hc.client5.http.async.AsyncExecChain; import org.apache.hc.client5.http.async.AsyncExecChainHandler; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; import org.apache.hc.client5.http.impl.async.HttpAsyncClients; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.nio.AsyncEntityProducer; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; class TestHttpAsyncClientBuilder { @@ -82,4 +85,14 @@ public void execute(final HttpRequest request, final AsyncEntityProducer entityP chain.proceed(request, entityProducer, scope, asyncExecCallback); } } + + + @Test + void testEvictExpiredConnectionsDoesNotRequireMaxIdleTime() throws Exception { + try (final CloseableHttpAsyncClient client = HttpAsyncClientBuilder.create() + .evictExpiredConnections() + .build()) { + Assertions.assertNotNull(client); + } + } } diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestHttpClientBuilder.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestHttpClientBuilder.java index 2cec4699e2..f4ccd698f1 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestHttpClientBuilder.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestHttpClientBuilder.java @@ -33,6 +33,7 @@ import org.apache.hc.core5.http.ClassicHttpRequest; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.HttpException; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; class TestHttpClientBuilder { @@ -66,4 +67,13 @@ public ClassicHttpResponse execute( return chain.proceed(request, scope); } } + + @Test + void testEvictExpiredConnectionsDoesNotRequireMaxIdleTime() throws Exception { + try (final CloseableHttpClient client = HttpClientBuilder.create() + .evictExpiredConnections() + .build()) { + Assertions.assertNotNull(client); + } + } } \ No newline at end of file From 69bbb59507e3467fc179532aea3597be09b511eb Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 2 Jan 2026 16:11:58 +0100 Subject: [PATCH 16/36] Removed jxr and surefire reports and cleaned up japicmp and javadoc config --- pom.xml | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/pom.xml b/pom.xml index 2141ebdc3b..be056bb966 100644 --- a/pom.xml +++ b/pom.xml @@ -341,11 +341,6 @@ jar - - - ${project.build.directory}/${project.artifactId}-${project.version}.${project.packaging} - - true true @@ -360,6 +355,9 @@ @org.apache.hc.core5.annotation.Internal true + true + false + false @@ -484,7 +482,6 @@ javadoc - aggregate @@ -508,11 +505,6 @@ jar - - - ${project.build.directory}/${project.artifactId}-${project.version}.${project.packaging} - - @org.apache.hc.core5.annotation.Internal @@ -521,12 +513,6 @@ - - maven-jxr-plugin - - - maven-surefire-report-plugin - From 21393be75f43e8d8646cc0365a74c0700010432c Mon Sep 17 00:00:00 2001 From: Arturo Bernal Date: Fri, 2 Jan 2026 18:11:31 +0000 Subject: [PATCH 17/36] HTTPCLIENT-2411: Use standard HTTP-date format for synthesized Date header (#775) Add regression test for cache conformance Date formatting (cherry picked from commit d07ff4d2fbc094582b342bcc7edb9d69f18fb30f) --- .../http/impl/cache/ResponseCacheConformance.java | 3 ++- .../impl/cache/TestResponseCacheConformance.java | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ResponseCacheConformance.java b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ResponseCacheConformance.java index 87ef6857e3..37a368fbff 100644 --- a/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ResponseCacheConformance.java +++ b/httpclient5-cache/src/main/java/org/apache/hc/client5/http/impl/cache/ResponseCacheConformance.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.time.Instant; +import org.apache.hc.client5.http.utils.DateUtils; import org.apache.hc.core5.annotation.Contract; import org.apache.hc.core5.annotation.ThreadingBehavior; import org.apache.hc.core5.http.EntityDetails; @@ -71,7 +72,7 @@ public void process(final HttpResponse response, } } if (!response.containsHeader(HttpHeaders.DATE)) { - response.addHeader(new BasicHeader(HttpHeaders.DATE, Instant.now())); + response.addHeader(new BasicHeader(HttpHeaders.DATE, DateUtils.formatStandardDate(Instant.now()))); } } diff --git a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestResponseCacheConformance.java b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestResponseCacheConformance.java index df347b7b8a..1983376265 100644 --- a/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestResponseCacheConformance.java +++ b/httpclient5-cache/src/test/java/org/apache/hc/client5/http/impl/cache/TestResponseCacheConformance.java @@ -31,9 +31,11 @@ import java.time.Instant; import org.apache.hc.client5.http.utils.DateUtils; +import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.support.BasicResponseBuilder; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -87,4 +89,14 @@ void shouldStripContentTypeFromOrigin304ResponseToStrongValidation() throws Exce "Content-Type", "text/html;charset=utf-8"); } + @Test + void shouldAddStandardDateHeaderIfMissing() throws Exception { + final HttpResponse response = BasicResponseBuilder.create(HttpStatus.SC_OK) + .build(); + assertFalse(response.containsHeader(HttpHeaders.DATE)); + impl.process(response, null, null); + Assertions.assertTrue(response.containsHeader(HttpHeaders.DATE)); + Assertions.assertNotNull(DateUtils.parseStandardDate(response, HttpHeaders.DATE)); + } + } From dcf3ba8c25dda0b9e28ac1debfea59cbfb63d7de Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 3 Jan 2026 11:24:58 +0100 Subject: [PATCH 18/36] Updated composition of the project web content --- pom.xml | 3 ++- src/site/site.xml | 36 +++++++++++++++--------------------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/pom.xml b/pom.xml index be056bb966..6897aaed94 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ 4.0.0 org.apache.httpcomponents.client5 httpclient5-parent - Apache HttpComponents Client Parent + Apache HttpComponents Client 5.6.1-SNAPSHOT Apache HttpComponents Client is a library of components for building client side HTTP services https://hc.apache.org/httpcomponents-client-5.5.x/${project.version}/ @@ -509,6 +509,7 @@ @org.apache.hc.core5.annotation.Internal + true true diff --git a/src/site/site.xml b/src/site/site.xml index 0b8d8c87a6..65ce9f5fbb 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -18,33 +18,24 @@ specific language governing permissions and limitations under the License. --> - - - + - org.apache.httpcomponents - maven-site-skin - 1.1 - - + Apache - http://www.apache.org/images/asf_logo_wide.gif - http://www.apache.org/ + https://www.apache.org/images/asf_logo.gif + https://www.apache.org/ HttpComponents - http://hc.apache.org/images/logos/httpcomponents.png - http://hc.apache.org/ + https://hc.apache.org/images/logos/httpcomponents.png + https://hc.apache.org/ @@ -53,7 +44,7 @@ under the License. - + @@ -66,15 +57,15 @@ under the License. - + - + - + @@ -84,5 +75,8 @@ under the License.
All other marks mentioned may be trademarks or registered trademarks of their respective owners.
+ + true + From d2db5b157bacb0ce5d49872b241329ef249bcf68 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 13 Jan 2026 11:37:24 +0100 Subject: [PATCH 19/36] Upgraded japicmp to version 0.25.4; use published artifact for site report --- pom.xml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 6897aaed94..500413c26e 100644 --- a/pom.xml +++ b/pom.xml @@ -332,6 +332,7 @@ com.github.siom79.japicmp japicmp-maven-plugin + 0.25.4 @@ -354,7 +355,6 @@ @org.apache.hc.core5.annotation.Internal - true true false false @@ -497,6 +497,14 @@ + + + ${project.groupId} + ${project.artifactId} + ${project.version} + jar + + ${project.groupId} @@ -510,7 +518,6 @@ @org.apache.hc.core5.annotation.Internal true - true From fb3f6307d1f550d605053ce6376db3fdc3eb8067 Mon Sep 17 00:00:00 2001 From: Ryan Schmitt Date: Wed, 14 Jan 2026 15:47:10 -0800 Subject: [PATCH 20/36] Add LoggingIOSessionTest --- .../http/impl/async/LoggingIOSession.java | 2 +- .../http/impl/async/LoggingIOSessionTest.java | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/LoggingIOSessionTest.java diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/LoggingIOSession.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/LoggingIOSession.java index 4e4a5ab9e7..4dd973ab04 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/LoggingIOSession.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/LoggingIOSession.java @@ -262,7 +262,7 @@ public void disconnected(final IOSession protocolSession) { } - private void logData(final ByteBuffer data, final String prefix) { + void logData(final ByteBuffer data, final String prefix) { final byte[] line = new byte[16]; final StringBuilder buf = new StringBuilder(); while (data.hasRemaining()) { diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/LoggingIOSessionTest.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/LoggingIOSessionTest.java new file mode 100644 index 0000000000..c2ccea3058 --- /dev/null +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/LoggingIOSessionTest.java @@ -0,0 +1,75 @@ +/* + * ==================================================================== + * 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 + * . + * + */ +package org.apache.hc.client5.http.impl.async; + +import org.apache.hc.core5.reactor.IOSession; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; + +import java.nio.ByteBuffer; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +class LoggingIOSessionTest { + IOSession delegate = mock(IOSession.class); + Logger log = mock(Logger.class); + Logger wireLog = mock(Logger.class); + LoggingIOSession session = new LoggingIOSession(delegate, log, wireLog); + + @Test + void allBytes() { + when(delegate.toString()).thenReturn("IOSession"); + final byte[] bs = new byte[256]; + for (int i = 0; i < bs.length; i++) { + bs[i] = (byte) i; + } + final ByteBuffer buf = ByteBuffer.wrap(bs); + + session.logData(buf, "<< "); + + verify(wireLog).debug("IOSession << ......... .. 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f"); + verify(wireLog).debug("IOSession << ............ 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f"); + verify(wireLog).debug("IOSession << !\"#$%&'()*+,-./ 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f"); + verify(wireLog).debug("IOSession << 0123456789:;<=>? 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f"); + verify(wireLog).debug("IOSession << @ABCDEFGHIJKLMNO 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f"); + verify(wireLog).debug("IOSession << PQRSTUVWXYZ[\\]^_ 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f"); + verify(wireLog).debug("IOSession << `abcdefghijklmno 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f"); + verify(wireLog).debug("IOSession << pqrstuvwxyz{|}~\u007F 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f"); + verify(wireLog).debug("IOSession << ................ 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f"); + verify(wireLog).debug("IOSession << ................ 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f"); + verify(wireLog).debug("IOSession << ................ a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af"); + verify(wireLog).debug("IOSession << ................ b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf"); + verify(wireLog).debug("IOSession << ................ c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf"); + verify(wireLog).debug("IOSession << ................ d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df"); + verify(wireLog).debug("IOSession << ................ e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef"); + verify(wireLog).debug("IOSession << ................ f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff"); + verifyNoMoreInteractions(wireLog); + } +} From 6a1150d5bc1c4ffec3e8ee4c869602054fdec087 Mon Sep 17 00:00:00 2001 From: Ryan Schmitt Date: Wed, 14 Jan 2026 15:51:44 -0800 Subject: [PATCH 21/36] LoggingIOSession: Fix off-by-one error --- .../org/apache/hc/client5/http/impl/async/LoggingIOSession.java | 2 +- .../apache/hc/client5/http/impl/async/LoggingIOSessionTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/LoggingIOSession.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/LoggingIOSession.java index 4dd973ab04..8edba851b0 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/LoggingIOSession.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/LoggingIOSession.java @@ -273,7 +273,7 @@ void logData(final ByteBuffer data, final String prefix) { for (int i = 0; i < chunk; i++) { final char ch = (char) line[i]; - if (ch > Chars.SP && ch <= Chars.DEL) { + if (ch > Chars.SP && ch < Chars.DEL) { buf.append(ch); } else if (Character.isWhitespace(ch)) { buf.append(' '); diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/LoggingIOSessionTest.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/LoggingIOSessionTest.java index c2ccea3058..3c06ff9a49 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/LoggingIOSessionTest.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/LoggingIOSessionTest.java @@ -61,7 +61,7 @@ void allBytes() { verify(wireLog).debug("IOSession << @ABCDEFGHIJKLMNO 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f"); verify(wireLog).debug("IOSession << PQRSTUVWXYZ[\\]^_ 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f"); verify(wireLog).debug("IOSession << `abcdefghijklmno 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f"); - verify(wireLog).debug("IOSession << pqrstuvwxyz{|}~\u007F 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f"); + verify(wireLog).debug("IOSession << pqrstuvwxyz{|}~. 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f"); verify(wireLog).debug("IOSession << ................ 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f"); verify(wireLog).debug("IOSession << ................ 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f"); verify(wireLog).debug("IOSession << ................ a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af"); From b6e827e5bdf169a5acca304ec6171b3072bb3d48 Mon Sep 17 00:00:00 2001 From: Ryan Schmitt Date: Wed, 14 Jan 2026 16:20:57 -0800 Subject: [PATCH 22/36] Improve socket timeout tests This change simplifies the socket timeout tests in order to improve their reliability. Instead of asserting that the actual socket timeout was in a certain range, we take more of a pass-fail approach: if a `SocketTimeoutException` is thrown at all, then the configured timeout values must have been applied correctly within the client. This should greatly reduce or eliminate spurious test failures. --- .../testing/async/TestAsyncSocketTimeout.java | 54 ++++++++---------- .../testing/sync/TestSocketTimeout.java | 55 +++++++------------ 2 files changed, 44 insertions(+), 65 deletions(-) diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncSocketTimeout.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncSocketTimeout.java index ec5de2ff9b..ee17bb9cf1 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncSocketTimeout.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncSocketTimeout.java @@ -42,18 +42,15 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Timeout; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; +import org.junit.jupiter.params.provider.CsvSource; import java.net.SocketTimeoutException; import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import static java.lang.String.format; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.apache.hc.core5.util.ReflectionUtils.determineJRELevel; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeTrue; @@ -65,22 +62,14 @@ protected AbstractTestSocketTimeout(final URIScheme scheme, final ClientProtocol @Timeout(5) @ParameterizedTest - @ValueSource(strings = { - "150,0,150,false", - "0,150,150,false", - "150,0,150,true", - "0,150,150,true", + @CsvSource({ + "10,0", + "0,10", // ResponseTimeout overrides socket timeout - "2000,150,150,false", - "2000,150,150,true" + "10000,10", }) - void testReadTimeouts(final String param) throws Throwable { + void testReadTimeouts(final int connConfigTimeout, final int responseTimeout) throws Throwable { checkAssumptions(); - final String[] params = param.split(","); - final int connConfigTimeout = Integer.parseInt(params[0]); - final long responseTimeout = Integer.parseInt(params[1]); - final long expectedDelayMs = Long.parseLong(params[2]); - final boolean drip = Boolean.parseBoolean(params[3]); configureServer(bootstrap -> bootstrap .register("/random/*", AsyncRandomHandler::new)); final HttpHost target = startServer(); @@ -92,26 +81,29 @@ void testReadTimeouts(final String param) throws Throwable { .setSocketTimeout(connConfigTimeout, MILLISECONDS) .build()); } + + for (final boolean drip : new boolean[]{ false, true }) { + final SimpleHttpRequest request = getRequest(responseTimeout, drip, + target); + + final Throwable cause = assertThrows(ExecutionException.class, () -> client.execute(request, null).get()) + .getCause(); + assertInstanceOf(SocketTimeoutException.class, cause); + } + + closeClient(client); + } + + private SimpleHttpRequest getRequest(final int responseTimeout, final boolean drip, final HttpHost target) + throws Exception { final SimpleHttpRequest request = SimpleHttpRequest.create(Method.GET, target, - "/random/10240?delay=500&drip=" + (drip ? 1 : 0)); + "/random/10240?delay=2500&drip=" + (drip ? 1 : 0)); if (responseTimeout > 0) { request.setConfig(RequestConfig.custom() .setUnixDomainSocket(getUnixDomainSocket()) .setResponseTimeout(responseTimeout, MILLISECONDS).build()); } - - final long startTime = System.nanoTime(); - final Throwable cause = assertThrows(ExecutionException.class, () -> client.execute(request, null).get()) - .getCause(); - final long actualDelayMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime); - - assertInstanceOf(SocketTimeoutException.class, cause); - assertTrue(actualDelayMs > expectedDelayMs / 2, - format("Socket read timed out too soon (only %,d out of %,d ms)", actualDelayMs, expectedDelayMs)); - assertTrue(actualDelayMs < expectedDelayMs * 2, - format("Socket read timed out too late (%,d out of %,d ms)", actualDelayMs, expectedDelayMs)); - - closeClient(client); + return request; } void checkAssumptions() { diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSocketTimeout.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSocketTimeout.java index 49486c6b4d..56bd63008e 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSocketTimeout.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSocketTimeout.java @@ -41,16 +41,13 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Timeout; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; +import org.junit.jupiter.params.provider.CsvSource; import java.net.SocketTimeoutException; import java.net.URI; -import java.util.concurrent.TimeUnit; -import static java.lang.String.format; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; abstract class AbstractTestSocketTimeout extends AbstractIntegrationTestBase { protected AbstractTestSocketTimeout(final URIScheme scheme, final ClientProtocolLevel clientProtocolLevel, @@ -60,27 +57,16 @@ protected AbstractTestSocketTimeout(final URIScheme scheme, final ClientProtocol @Timeout(5) @ParameterizedTest - @ValueSource(strings = { - "150,0,0,150,false", - "0,150,0,150,false", - "150,0,0,150,true", - "0,150,0,150,true", + @CsvSource({ + "10,0,0", + "0,10,0", // ConnectionConfig overrides SocketConfig - "50,150,0,150,false", - "1000,150,0,150,false", - "50,150,0,150,true", - "1000,150,0,150,true", + "10000,10,0", // ResponseTimeout overrides socket timeout - "2000,2000,150,150,false", - "2000,2000,150,150,true" + "10000,10000,10", }) - void testReadTimeouts(final String param) throws Exception { - final String[] params = param.split(","); - final int socketConfigTimeout = Integer.parseInt(params[0]); - final int connConfigTimeout = Integer.parseInt(params[1]); - final long responseTimeout = Integer.parseInt(params[2]); - final long expectedDelayMs = Long.parseLong(params[3]); - final boolean drip = Boolean.parseBoolean(params[4]); + void testReadTimeouts(final int socketConfigTimeout, final int connConfigTimeout, final int responseTimeout) + throws Exception { configureServer(bootstrap -> bootstrap .register("/random/*", new RandomHandler())); final HttpHost target = startServer(); @@ -97,23 +83,24 @@ void testReadTimeouts(final String param) throws Exception { .setSocketTimeout(connConfigTimeout, MILLISECONDS) .build()); } - final HttpGet request = new HttpGet(new URI("/random/10240?delay=1000&drip=" + (drip ? 1 : 0))); + + for (final boolean drip : new boolean[]{ false, true }) { + final HttpGet request = getRequest(responseTimeout, drip); + + assertThrows(SocketTimeoutException.class, () -> + client.execute(target, request, new BasicHttpClientResponseHandler())); + } + } + + private HttpGet getRequest(final int responseTimeout, final boolean drip) throws Exception { + final HttpGet request = new HttpGet(new URI("/random/10240?delay=2500&drip=" + (drip ? 1 : 0))); if (responseTimeout > 0) { request.setConfig(RequestConfig.custom() .setUnixDomainSocket(getUnixDomainSocket()) .setResponseTimeout(responseTimeout, MILLISECONDS) .build()); } - - final long startTime = System.nanoTime(); - assertThrows(SocketTimeoutException.class, () -> - client.execute(target, request, new BasicHttpClientResponseHandler())); - final long actualDelayMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime); - - assertTrue(actualDelayMs > expectedDelayMs / 2, - format("Socket read timed out too soon (only %,d out of %,d ms)", actualDelayMs, expectedDelayMs)); - assertTrue(actualDelayMs < expectedDelayMs * 3, - format("Socket read timed out too late (%,d out of %,d ms)", actualDelayMs, expectedDelayMs)); + return request; } } @@ -128,7 +115,7 @@ public Http() { @Nested class Https extends AbstractTestSocketTimeout { public Https() { - super(URIScheme.HTTP, ClientProtocolLevel.STANDARD, false); + super(URIScheme.HTTPS, ClientProtocolLevel.STANDARD, false); } } From 8fdd72edd8c5d081484b85dfdaa5aa7ba6e34708 Mon Sep 17 00:00:00 2001 From: Ryan Schmitt Date: Wed, 14 Jan 2026 17:24:45 -0800 Subject: [PATCH 23/36] DefaultManagedHttpClientConnection: Restore original socket timeout This change fixes a bug in the synchronous client where socket timeouts were not being set correctly on reused connections, and the client was instead setting it to either the TLS handshake timeout or the `responseTimeout` from the `RequestConfig` of the previous request. The fix works by changing `DefaultManagedHttpClientConnection` to store the `socketTimeout` set on the socket at the time `bind` is called, and always restore that value when the `activate` method is called. Note that this requires the caller to call `setSoTimeout` on the socket _before_ binding the connection to it, hence the adjustments to some of the code in `DefaultHttpClientConnectionOperator`. --- .../testing/async/TestAsyncSocketTimeout.java | 32 ++++++++----------- .../testing/sync/TestSocketTimeout.java | 16 +++++++--- .../DefaultHttpClientConnectionOperator.java | 4 +-- .../DefaultManagedHttpClientConnection.java | 1 - 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncSocketTimeout.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncSocketTimeout.java index ee17bb9cf1..aae0ecb1b6 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncSocketTimeout.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncSocketTimeout.java @@ -38,7 +38,6 @@ import org.apache.hc.core5.http.Method; import org.apache.hc.core5.http.URIScheme; import org.apache.hc.core5.io.CloseMode; -import org.apache.hc.core5.util.VersionInfo; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Timeout; import org.junit.jupiter.params.ParameterizedTest; @@ -51,7 +50,6 @@ import static org.apache.hc.core5.util.ReflectionUtils.determineJRELevel; import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assumptions.assumeFalse; import static org.junit.jupiter.api.Assumptions.assumeTrue; abstract class AbstractTestSocketTimeout extends AbstractIntegrationTestBase { @@ -83,21 +81,26 @@ void testReadTimeouts(final int connConfigTimeout, final int responseTimeout) th } for (final boolean drip : new boolean[]{ false, true }) { - final SimpleHttpRequest request = getRequest(responseTimeout, drip, - target); - - final Throwable cause = assertThrows(ExecutionException.class, () -> client.execute(request, null).get()) - .getCause(); - assertInstanceOf(SocketTimeoutException.class, cause); + for (final boolean reuseConnection : new boolean[]{ false, true }) { + if (reuseConnection) { + client.execute(getRequest(2500, 0, false, target), null).get(); + } + final SimpleHttpRequest request = getRequest(responseTimeout, 2500, drip, target); + + final Throwable cause = assertThrows(ExecutionException.class, + () -> client.execute(request, null).get()).getCause(); + assertInstanceOf(SocketTimeoutException.class, cause, + String.format("drip=%s, reuseConnection=%s", drip, reuseConnection)); + } } closeClient(client); } - private SimpleHttpRequest getRequest(final int responseTimeout, final boolean drip, final HttpHost target) - throws Exception { + private SimpleHttpRequest getRequest(final int responseTimeout, final int delay, final boolean drip, + final HttpHost target) throws Exception { final SimpleHttpRequest request = SimpleHttpRequest.create(Method.GET, target, - "/random/10240?delay=2500&drip=" + (drip ? 1 : 0)); + "/random/10240?delay=" + delay + "&drip=" + (drip ? 1 : 0)); if (responseTimeout > 0) { request.setConfig(RequestConfig.custom() .setUnixDomainSocket(getUnixDomainSocket()) @@ -138,13 +141,6 @@ public Uds() { @Override void checkAssumptions() { assumeTrue(determineJRELevel() >= 16, "Async UDS requires Java 16+"); - final String[] components = VersionInfo - .loadVersionInfo("org.apache.hc.core5", getClass().getClassLoader()) - .getRelease() - .split("[-.]"); - final int majorVersion = Integer.parseInt(components[0]); - final int minorVersion = Integer.parseInt(components[1]); - assumeFalse(majorVersion <= 5 && minorVersion <= 3, "Async UDS requires HttpCore 5.4+"); } } } diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSocketTimeout.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSocketTimeout.java index 56bd63008e..bb8caa2aac 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSocketTimeout.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSocketTimeout.java @@ -85,15 +85,21 @@ void testReadTimeouts(final int socketConfigTimeout, final int connConfigTimeout } for (final boolean drip : new boolean[]{ false, true }) { - final HttpGet request = getRequest(responseTimeout, drip); + for (final boolean reuseConnection : new boolean[]{ false, true }) { + if (reuseConnection) { + client.execute(target, getRequest(5000, 0, false), new BasicHttpClientResponseHandler()); + } + final HttpGet request = getRequest(responseTimeout, 2500, drip); - assertThrows(SocketTimeoutException.class, () -> - client.execute(target, request, new BasicHttpClientResponseHandler())); + assertThrows(SocketTimeoutException.class, () -> + client.execute(target, request, new BasicHttpClientResponseHandler()), + String.format("drip=%s, reuseConnection=%s", drip, reuseConnection)); + } } } - private HttpGet getRequest(final int responseTimeout, final boolean drip) throws Exception { - final HttpGet request = new HttpGet(new URI("/random/10240?delay=2500&drip=" + (drip ? 1 : 0))); + private HttpGet getRequest(final int responseTimeout, final int delay, final boolean drip) throws Exception { + final HttpGet request = new HttpGet(new URI("/random/10240?delay=" + delay + "&drip=" + (drip ? 1 : 0))); if (responseTimeout > 0) { request.setConfig(RequestConfig.custom() .setUnixDomainSocket(getUnixDomainSocket()) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultHttpClientConnectionOperator.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultHttpClientConnectionOperator.java index d1e31cddd9..e0986ce9ec 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultHttpClientConnectionOperator.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultHttpClientConnectionOperator.java @@ -261,8 +261,8 @@ private void upgradeToTls(final ManagedHttpClientConnection conn, final HttpHost socket.setSoTimeout(handshakeTimeout.toMillisecondsIntBound()); } final SSLSocket sslSocket = tlsSocketStrategy.upgrade(socket, tlsName.getHostName(), tlsName.getPort(), attachment, context); - conn.bind(sslSocket, socket); socket.setSoTimeout(soTimeout); + conn.bind(sslSocket, socket); onAfterTlsHandshake(context, endpointHost); if (LOG.isDebugEnabled()) { LOG.debug("{} {} upgraded to TLS", ConnPoolSupport.getId(conn), tlsName); @@ -287,8 +287,8 @@ private void connectToUnixDomainSocket( conn.bind(newSocket); final Socket socket = unixDomainSocketFactory.connectSocket(newSocket, unixDomainSocket, connectTimeout); - conn.bind(socket); configureSocket(socket, socketConfig, false); + conn.bind(socket); onAfterSocketConnect(context, endpointHost); if (LOG.isDebugEnabled()) { LOG.debug("{} {} connected to {}", ConnPoolSupport.getId(conn), endpointHost, unixDomainSocket); diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultManagedHttpClientConnection.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultManagedHttpClientConnection.java index f5fb1f69f4..1a9f27bbad 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultManagedHttpClientConnection.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultManagedHttpClientConnection.java @@ -166,7 +166,6 @@ public void setSocketTimeout(final Timeout timeout) { LOG.debug("{} set socket timeout to {}", this.id, timeout); } super.setSocketTimeout(timeout); - socketTimeout = timeout; } @Override From 74396badff91bf19141dfee8181a8d7786c2f066 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 17 Jan 2026 15:09:24 +0100 Subject: [PATCH 24/36] Bug fix: corrected sleep time calculation in IdleConnectionEvictor; use 1 minute sleep time by default --- .../http/impl/IdleConnectionEvictor.java | 17 +++++++++++++++-- .../http/impl/async/HttpAsyncClientBuilder.java | 8 +------- .../http/impl/classic/HttpClientBuilder.java | 8 +------- .../http/impl/TestIdleConnectionEvictor.java | 8 ++++++++ 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/IdleConnectionEvictor.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/IdleConnectionEvictor.java index 18ad48759c..6a46106054 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/IdleConnectionEvictor.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/IdleConnectionEvictor.java @@ -28,6 +28,7 @@ package org.apache.hc.client5.http.impl; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; import org.apache.hc.core5.annotation.Contract; import org.apache.hc.core5.annotation.ThreadingBehavior; @@ -46,6 +47,9 @@ @Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL) public final class IdleConnectionEvictor { + private static final TimeValue ONE_SECOND = TimeValue.ofSeconds(1L); + private static final TimeValue ONE_MINUTE = TimeValue.ofMinutes(1L); + private final ThreadFactory threadFactory; private final Thread thread; @@ -53,7 +57,7 @@ public IdleConnectionEvictor(final ConnPoolControl connectionManager, final T final TimeValue sleepTime, final TimeValue maxIdleTime) { Args.notNull(connectionManager, "Connection manager"); this.threadFactory = threadFactory != null ? threadFactory : new DefaultThreadFactory("idle-connection-evictor", true); - final TimeValue localSleepTime = sleepTime != null ? sleepTime : TimeValue.ofSeconds(5); + final TimeValue localSleepTime = sleepTime != null ? sleepTime : calculateSleepTime(maxIdleTime); this.thread = this.threadFactory.newThread(() -> { try { while (!Thread.currentThread().isInterrupted()) { @@ -76,7 +80,7 @@ public IdleConnectionEvictor(final ConnPoolControl connectionManager, final T } public IdleConnectionEvictor(final ConnPoolControl connectionManager, final TimeValue maxIdleTime) { - this(connectionManager, null, maxIdleTime, maxIdleTime); + this(connectionManager, null, null, maxIdleTime); } public void start() { @@ -95,4 +99,13 @@ public void awaitTermination(final Timeout timeout) throws InterruptedException thread.join(timeout != null ? timeout.toMilliseconds() : Long.MAX_VALUE); } + static TimeValue calculateSleepTime(final TimeValue maxIdleTime) { + if (maxIdleTime == null) { + return ONE_MINUTE; + } else { + final TimeValue sleepTime = maxIdleTime.divide(10, TimeUnit.NANOSECONDS); + return sleepTime.compareTo(ONE_SECOND) < 0 ? ONE_SECOND : sleepTime; + } + } + } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java index bdcc390635..4627dfdead 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java @@ -37,7 +37,6 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.UnaryOperator; @@ -163,8 +162,6 @@ */ public class HttpAsyncClientBuilder { - private static final TimeValue ONE_SECOND = TimeValue.ofSeconds(1L); - private static class RequestInterceptorEntry { enum Position { FIRST, LAST } @@ -1146,11 +1143,8 @@ public CloseableHttpAsyncClient build() { } if (evictExpiredConnections || evictIdleConnections) { if (connManagerCopy instanceof ConnPoolControl) { - final TimeValue maxIdleTimeCopy = evictIdleConnections ? maxIdleTime : null; - TimeValue sleepTime = maxIdleTimeCopy != null ? maxIdleTimeCopy.divide(10, TimeUnit.NANOSECONDS) : ONE_SECOND; - sleepTime = sleepTime.compareTo(ONE_SECOND) < 0 ? ONE_SECOND : sleepTime; final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor((ConnPoolControl) connManagerCopy, - sleepTime, maxIdleTimeCopy); + null, evictIdleConnections ? maxIdleTime : null); closeablesCopy.add(connectionEvictor::shutdown); connectionEvictor.start(); } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java index 3c9f837cb7..d20d5c1ecb 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java @@ -37,7 +37,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.UnaryOperator; @@ -147,8 +146,6 @@ */ public class HttpClientBuilder { - private static final TimeValue ONE_SECOND = TimeValue.ofSeconds(1L); - private static class RequestInterceptorEntry { enum Position { FIRST, LAST } @@ -1115,11 +1112,8 @@ public CloseableHttpClient build() { } if (evictExpiredConnections || evictIdleConnections) { if (connManagerCopy instanceof ConnPoolControl) { - final TimeValue maxIdleTimeCopy = evictIdleConnections ? maxIdleTime : null; - TimeValue sleepTime = maxIdleTimeCopy != null ? maxIdleTimeCopy.divide(10, TimeUnit.NANOSECONDS) : ONE_SECOND; - sleepTime = sleepTime.compareTo(ONE_SECOND) < 0 ? ONE_SECOND : sleepTime; final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor((ConnPoolControl) connManagerCopy, - sleepTime, maxIdleTimeCopy); + null, evictIdleConnections ? maxIdleTime : null); closeablesCopy.add(() -> { connectionEvictor.shutdown(); try { diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestIdleConnectionEvictor.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestIdleConnectionEvictor.java index 95665e0b97..79e0092718 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestIdleConnectionEvictor.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestIdleConnectionEvictor.java @@ -78,4 +78,12 @@ void testEvictExpiredOnly() throws Exception { Assertions.assertFalse(connectionEvictor.isRunning()); } + @Test + void testCalculateSleepTime() throws Exception { + Assertions.assertEquals(TimeValue.ofMinutes(1), IdleConnectionEvictor.calculateSleepTime(null)); + Assertions.assertEquals(TimeValue.ofSeconds(3), IdleConnectionEvictor.calculateSleepTime(TimeValue.ofSeconds(30))); + Assertions.assertEquals(TimeValue.ofSeconds(1), IdleConnectionEvictor.calculateSleepTime(TimeValue.ofSeconds(10))); + Assertions.assertEquals(TimeValue.ofSeconds(1), IdleConnectionEvictor.calculateSleepTime(TimeValue.ofMilliseconds(125))); + } + } From 1e01a487e283c04cbcd60515951c2d8b6e1f2670 Mon Sep 17 00:00:00 2001 From: Arturo Bernal Date: Wed, 11 Feb 2026 06:07:09 +0000 Subject: [PATCH 25/36] HTTPCLIENT-2415: Normalize CookieOrigin path for cookie matching (#803) Strip query / fragment from CookieOrigin path per RFC 6265. Add regression tests for request-targets containing '?', '#'. (cherry picked from commit 9189d11abf60ecfae84f1d324629b4f47ead4e62) --- .../http/protocol/RequestAddCookies.java | 30 ++- .../client5/http/cookie/TestCookieOrigin.java | 5 + .../cookie/TestBasicCookieAttribHandlers.java | 1 - .../http/protocol/TestRequestAddCookies.java | 184 ++++++++++++++++++ 4 files changed, 214 insertions(+), 6 deletions(-) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/protocol/RequestAddCookies.java b/httpclient5/src/main/java/org/apache/hc/client5/http/protocol/RequestAddCookies.java index cf50c999ca..cd6cdac1cd 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/protocol/RequestAddCookies.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/protocol/RequestAddCookies.java @@ -76,6 +76,28 @@ public class RequestAddCookies implements HttpRequestInterceptor { private static final Logger LOG = LoggerFactory.getLogger(RequestAddCookies.class); + private static String normalizeRequestPath(final String rawPath) { + if (TextUtils.isBlank(rawPath)) { + return "/"; + } + int end = rawPath.length(); + + final int queryIndex = rawPath.indexOf('?'); + if (queryIndex >= 0) { + end = queryIndex; + } + final int fragmentIndex = rawPath.indexOf('#'); + if (fragmentIndex >= 0 && fragmentIndex < end) { + end = fragmentIndex; + } + if (end == 0) { + return "/"; + } + if (end == rawPath.length()) { + return rawPath; + } + return rawPath.substring(0, end); + } public RequestAddCookies() { super(); } @@ -100,7 +122,6 @@ public void process(final HttpRequest request, final EntityDetails entity, final return; } - final HttpClientContext clientContext = HttpClientContext.cast(context); final String exchangeId = clientContext.getExchangeId(); @@ -141,10 +162,9 @@ public void process(final HttpRequest request, final EntityDetails entity, final } final URIAuthority authority = request.getAuthority(); - String path = request.getPath(); - if (TextUtils.isEmpty(path)) { - path = "/"; - } + + final String path = normalizeRequestPath(request.getPath()); + String hostName = authority != null ? authority.getHostName() : null; if (hostName == null) { hostName = route.getTargetHost().getHostName(); diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/cookie/TestCookieOrigin.java b/httpclient5/src/test/java/org/apache/hc/client5/http/cookie/TestCookieOrigin.java index 542aec8583..965f1fdfe7 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/cookie/TestCookieOrigin.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/cookie/TestCookieOrigin.java @@ -76,6 +76,11 @@ void testEmptyPath() { Assertions.assertEquals("/", origin.getPath()); Assertions.assertFalse(origin.isSecure()); } + @Test + void testNormalizePathRejectsNull() { + Assertions.assertThrows(NullPointerException.class, () -> + new CookieOrigin("somehost", 80, null, false)); + } } diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/cookie/TestBasicCookieAttribHandlers.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/cookie/TestBasicCookieAttribHandlers.java index d44a0cd657..2a9cc7d20e 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/cookie/TestBasicCookieAttribHandlers.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/cookie/TestBasicCookieAttribHandlers.java @@ -399,5 +399,4 @@ void testBasicHttpOnlyParse() throws Exception { h.parse(cookie, "anyone"); Assertions.assertTrue(cookie.isHttpOnly()); } - } diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/protocol/TestRequestAddCookies.java b/httpclient5/src/test/java/org/apache/hc/client5/http/protocol/TestRequestAddCookies.java index 21ffea0545..f59631082c 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/protocol/TestRequestAddCookies.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/protocol/TestRequestAddCookies.java @@ -126,6 +126,62 @@ void testAddCookies() throws Exception { Assertions.assertFalse(cookieOrigin.isSecure()); } + @Test + void testAddCookiesWithQueryParams() throws Exception { + final BasicCookieStore store = new BasicCookieStore(); + final BasicClientCookie cookie = new BasicClientCookie("name", "value"); + cookie.setDomain("localhost.local"); + cookie.setPath("/stuff"); + store.addCookie(cookie); + + final HttpRequest request = new BasicHttpRequest("GET", "/stuff?foo=bar"); + final HttpRoute route = new HttpRoute(this.target, null, false); + + final HttpClientContext context = HttpClientContext.create(); + context.setRoute(route); + context.setCookieStore(store); + context.setCookieSpecRegistry(this.cookieSpecRegistry); + + final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE; + interceptor.process(request, null, context); + + final Header[] headers = request.getHeaders("Cookie"); + Assertions.assertNotNull(headers); + Assertions.assertEquals(1, headers.length); + Assertions.assertEquals("name=value", headers[0].getValue()); + + final CookieOrigin cookieOrigin = context.getCookieOrigin(); + Assertions.assertEquals("/stuff", cookieOrigin.getPath()); + } + + @Test + void testAddCookiesWithFragment() throws Exception { + final BasicCookieStore store = new BasicCookieStore(); + final BasicClientCookie cookie = new BasicClientCookie("name", "value"); + cookie.setDomain("localhost.local"); + cookie.setPath("/stuff"); + store.addCookie(cookie); + + final HttpRequest request = new BasicHttpRequest("GET", "/stuff#section"); + final HttpRoute route = new HttpRoute(this.target, null, false); + + final HttpClientContext context = HttpClientContext.create(); + context.setRoute(route); + context.setCookieStore(store); + context.setCookieSpecRegistry(this.cookieSpecRegistry); + + final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE; + interceptor.process(request, null, context); + + final Header[] headers = request.getHeaders("Cookie"); + Assertions.assertNotNull(headers); + Assertions.assertEquals(1, headers.length); + Assertions.assertEquals("name=value", headers[0].getValue()); + + final CookieOrigin cookieOrigin = context.getCookieOrigin(); + Assertions.assertEquals("/stuff", cookieOrigin.getPath()); + } + @Test void testCookiesForConnectRequest() throws Exception { final HttpRequest request = new BasicHttpRequest("CONNECT", "www.somedomain.com"); @@ -432,5 +488,133 @@ void testSkipAddingCookiesWhenCookieHeaderPresent() throws Exception { Assertions.assertEquals(1, headers.length); Assertions.assertEquals("existingCookie=existingValue", headers[0].getValue()); } + @Test + void testAddCookiesWithRequestPathContainingQuery() throws Exception { + final HttpRequest request = new BasicHttpRequest("GET", "/stuff?foo=bar"); + + final HttpRoute route = new HttpRoute(this.target, null, false); + + final CookieStore store = new BasicCookieStore(); + final BasicClientCookie cookie = new BasicClientCookie("name", "value"); + cookie.setDomain("localhost.local"); + cookie.setPath("/stuff"); + store.addCookie(cookie); + + final HttpClientContext context = HttpClientContext.create(); + context.setRoute(route); + context.setCookieStore(store); + context.setCookieSpecRegistry(this.cookieSpecRegistry); + + final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE; + interceptor.process(request, null, context); + + final Header[] headers = request.getHeaders("Cookie"); + Assertions.assertNotNull(headers); + Assertions.assertEquals(1, headers.length); + Assertions.assertEquals("name=value", headers[0].getValue()); + + final CookieOrigin cookieOrigin = context.getCookieOrigin(); + Assertions.assertNotNull(cookieOrigin); + Assertions.assertEquals("/stuff", cookieOrigin.getPath()); + } + + @Test + void testAddCookiesWithRequestPathContainingFragment() throws Exception { + final HttpRequest request = new BasicHttpRequest("GET", "/stuff#frag"); + + final HttpRoute route = new HttpRoute(this.target, null, false); + + final CookieStore store = new BasicCookieStore(); + final BasicClientCookie cookie = new BasicClientCookie("name", "value"); + cookie.setDomain("localhost.local"); + cookie.setPath("/stuff"); + store.addCookie(cookie); + + final HttpClientContext context = HttpClientContext.create(); + context.setRoute(route); + context.setCookieStore(store); + context.setCookieSpecRegistry(this.cookieSpecRegistry); + + final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE; + interceptor.process(request, null, context); + + final Header[] headers = request.getHeaders("Cookie"); + Assertions.assertNotNull(headers); + Assertions.assertEquals(1, headers.length); + Assertions.assertEquals("name=value", headers[0].getValue()); + + final CookieOrigin cookieOrigin = context.getCookieOrigin(); + Assertions.assertNotNull(cookieOrigin); + Assertions.assertEquals("/stuff", cookieOrigin.getPath()); + } + + @Test + void testAddCookiesWithRootPathQuery() throws Exception { + // Should behave as path "/" (query ignored) + final HttpRequest request = new BasicHttpRequest("GET", "/?foo=bar"); + + final HttpRoute route = new HttpRoute(this.target, null, false); + + final HttpClientContext context = HttpClientContext.create(); + context.setRoute(route); + context.setCookieStore(this.cookieStore); // setup cookies are path "/" + context.setCookieSpecRegistry(this.cookieSpecRegistry); + + final HttpRequestInterceptor interceptor = RequestAddCookies.INSTANCE; + interceptor.process(request, null, context); + + final Header[] headers = request.getHeaders("Cookie"); + Assertions.assertNotNull(headers); + Assertions.assertEquals(1, headers.length); + Assertions.assertEquals("name1=value1; name2=value2", headers[0].getValue()); + + final CookieOrigin cookieOrigin = context.getCookieOrigin(); + Assertions.assertNotNull(cookieOrigin); + Assertions.assertEquals("/", cookieOrigin.getPath()); + } + + + @Test + void testCookieOriginPathNormalization() throws Exception { + final String[][] cases = new String[][]{ + {"", "/"}, + {" ", "/"}, + {"\t", "/"}, + {"?", "/"}, + {"#","/"}, + {"?foo", "/"}, + {"#frag", "/"}, + {"/", "/"}, + {"/?foo", "/"}, + {"/#frag", "/"}, + {"/stuff", "/stuff"}, + {"/stuff?foo", "/stuff"}, + {"/stuff#frag", "/stuff"}, + {"/stuff?foo#bar", "/stuff"}, + {"/stuff#bar?foo", "/stuff"}, + {"/stuff/", "/stuff/"}, + {"/stuff/?foo", "/stuff/"}, + }; + + for (final String[] c : cases) { + final String input = c[0]; + final String expected = c[1]; + + final HttpRequest request = new BasicHttpRequest("GET", input); + final HttpRoute route = new HttpRoute(this.target, null, false); + + final HttpClientContext context = HttpClientContext.create(); + context.setRoute(route); + context.setCookieStore(new BasicCookieStore()); + context.setCookieSpecRegistry(this.cookieSpecRegistry); + + RequestAddCookies.INSTANCE.process(request, null, context); + + final CookieOrigin origin = context.getCookieOrigin(); + Assertions.assertNotNull(origin, "input=" + input); + Assertions.assertEquals(expected, origin.getPath(), "input=" + input); + } + } + } From 9cc45f6c67864ec53f2284d16e77872851e25e87 Mon Sep 17 00:00:00 2001 From: Arturo Bernal Date: Sat, 14 Feb 2026 19:20:16 +0100 Subject: [PATCH 26/36] HTTPCLIENT-2414 - Fix Basic auth cache scoping across path prefixes (#802) Preserve AuthExchange pathPrefix on reset to avoid preemptive Authorization reuse outside the protection space. --- .../sync/TestClientAuthentication.java | 127 +++++++++++++- .../http/impl/async/AsyncProtocolExec.java | 6 +- .../http/impl/classic/ProtocolExec.java | 6 +- .../impl/async/TestAsyncProtocolExec.java | 159 ++++++++++++++++++ .../http/impl/classic/TestProtocolExec.java | 33 ++++ 5 files changed, 323 insertions(+), 8 deletions(-) create mode 100644 httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/TestAsyncProtocolExec.java diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java index 84eabde95e..da7767e3af 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java @@ -33,8 +33,10 @@ import java.security.SecureRandom; import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -59,6 +61,7 @@ import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.client5.testing.BasicTestAuthenticator; +import org.apache.hc.client5.testing.auth.AuthResult; import org.apache.hc.client5.testing.auth.Authenticator; import org.apache.hc.client5.testing.auth.BearerAuthenticationHandler; import org.apache.hc.client5.testing.classic.AuthenticatingDecorator; @@ -405,11 +408,11 @@ void testBasicAuthenticationCredentialsCachingByPathPrefix() throws Exception { } // There should be an auth strategy call for all successful message exchanges - Mockito.verify(authStrategy, Mockito.times(2)).select(Mockito.any(), Mockito.any(), Mockito.any()); + Mockito.verify(authStrategy, Mockito.times(3)).select(Mockito.any(), Mockito.any(), Mockito.any()); assertThat( responseQueue.stream().map(HttpResponse::getCode).collect(Collectors.toList()), - CoreMatchers.equalTo(Arrays.asList(200, 401, 200, 200, 401, 200))); + CoreMatchers.equalTo(Arrays.asList(200, 401, 200, 401, 200, 401, 200))); } @Test @@ -820,4 +823,124 @@ void testBearerTokenAuthentication() throws Exception { }); } + @Test + void testBasicAuthenticationCredentialsCachingDifferentPathPrefixesSameContext() throws Exception { + final List requests = new CopyOnWriteArrayList<>(); + final Authenticator authenticator = new BasicTestAuthenticator("test:test", "test realm") { + @Override + public AuthResult perform(final URIAuthority authority, + final String requestUri, + final String credentials) { + requests.add(new RequestSnapshot(requestUri, credentials != null)); + return super.perform(authority, requestUri, credentials); + } + }; + configureServerWithBasicAuth(authenticator, bootstrap -> bootstrap.register("*", new EchoHandler())); + final HttpHost target = startServer(); + + final List responseCodes = new CopyOnWriteArrayList<>(); + + configureClient(builder -> builder + .addResponseInterceptorLast((response, entity, context) -> responseCodes.add(response.getCode()))); + + final TestClient client = client(); + + final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create() + .add(target, "test", "test".toCharArray()) + .build(); + + final HttpClientContext context = HttpClientContext.create(); + context.setAuthCache(new BasicAuthCache()); + context.setCredentialsProvider(credentialsProvider); + + for (final String requestPath : new String[]{"/blah/a", "/blubb/b"}) { + final HttpGet httpGet = new HttpGet(requestPath); + client.execute(target, httpGet, context, response -> { + EntityUtils.consume(response.getEntity()); + return null; + }); + } + + Assertions.assertEquals(Arrays.asList(401, 200, 401, 200), responseCodes); + + assertHandshakePerPath(requests, "/blah/a"); + assertHandshakePerPath(requests, "/blubb/b"); + } + + private static void assertHandshakePerPath(final List requests, final String path) { + final List filtered = requests.stream() + .filter(r -> path.equals(r.path)) + .collect(Collectors.toList()); + + Assertions.assertEquals(2, filtered.size(), "Expected 2 requests for " + path + " (challenge + retry)"); + Assertions.assertFalse(filtered.get(0).hasAuthorization, "First request to " + path + " must not be preemptive"); + Assertions.assertTrue(filtered.get(1).hasAuthorization, "Second request to " + path + " must carry Authorization"); + } + + private static final class RequestSnapshot { + private final String path; + private final boolean hasAuthorization; + + private RequestSnapshot(final String path, final boolean hasAuthorization) { + this.path = path; + this.hasAuthorization = hasAuthorization; + } + } + + @Test + void testBasicAuthenticationCredentialsCachingPerPrefixAndReuseWithinPrefix() throws Exception { + final List requests = new CopyOnWriteArrayList<>(); + final Authenticator authenticator = new BasicTestAuthenticator("test:test", "test realm") { + @Override + public AuthResult perform(final URIAuthority authority, + final String requestUri, + final String credentials) { + requests.add(new RequestSnapshot(requestUri, credentials != null)); + return super.perform(authority, requestUri, credentials); + } + }; + configureServerWithBasicAuth(authenticator, bootstrap -> bootstrap.register("*", new EchoHandler())); + final HttpHost target = startServer(); + + final List responseCodes = new CopyOnWriteArrayList<>(); + configureClient(builder -> builder + .addResponseInterceptorLast((response, entity, context) -> responseCodes.add(response.getCode()))); + + final TestClient client = client(); + + final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create() + .add(target, "test", "test".toCharArray()) + .build(); + + final HttpClientContext context = HttpClientContext.create(); + context.setAuthCache(new BasicAuthCache()); + context.setCredentialsProvider(credentialsProvider); + + // First hit per prefix must challenge; subsequent hits under same prefix should be preemptive (200 only) + for (final String requestPath : new String[]{"/blah/a", "/blubb/b", "/blubb/c", "/blah/d"}) { + final HttpGet httpGet = new HttpGet(requestPath); + client.execute(target, httpGet, context, response -> { + EntityUtils.consume(response.getEntity()); + return null; + }); + } + + Assertions.assertEquals(Arrays.asList(401, 200, 401, 200, 200, 200), responseCodes); + + assertHandshakePerPath(requests, "/blah/a"); + assertHandshakePerPath(requests, "/blubb/b"); + assertPreemptivePerPath(requests, "/blubb/c"); + assertPreemptivePerPath(requests, "/blah/d"); + } + + private static void assertPreemptivePerPath(final List requests, final String path) { + final List filtered = requests.stream() + .filter(r -> path.equals(r.path)) + .collect(Collectors.toList()); + + Assertions.assertEquals(1, filtered.size(), "Expected 1 request for " + path + " (preemptive)"); + Assertions.assertTrue(filtered.get(0).hasAuthorization, "Request to " + path + " must carry Authorization"); + } + + } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AsyncProtocolExec.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AsyncProtocolExec.java index 1b35f8cb34..706793e98b 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AsyncProtocolExec.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AsyncProtocolExec.java @@ -159,9 +159,6 @@ public void execute( // that of the previous authentication exchange. targetAuthExchange.reset(); } - if (targetAuthExchange.getPathPrefix() == null) { - targetAuthExchange.setPathPrefix(pathPrefix); - } if (authCacheKeeper != null) { authCacheKeeper.loadPreemptively(target, pathPrefix, targetAuthExchange, clientContext); @@ -340,6 +337,9 @@ private boolean needAuthentication( targetNeedsAuth = authenticator.handleResponse(target, ChallengeType.TARGET, response, targetAuthStrategy, targetAuthExchange, context); + if (!targetAuthExchange.isConnectionBased() && targetAuthExchange.getPathPrefix() == null) { + targetAuthExchange.setPathPrefix(pathPrefix); + } if (authCacheKeeper != null) { authCacheKeeper.updateOnResponse(target, pathPrefix, targetAuthExchange, context); } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ProtocolExec.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ProtocolExec.java index b927dbc798..4514ddfe94 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ProtocolExec.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/ProtocolExec.java @@ -163,9 +163,6 @@ public ClassicHttpResponse execute( // that of the previous authentication exchange. targetAuthExchange.reset(); } - if (targetAuthExchange.getPathPrefix() == null) { - targetAuthExchange.setPathPrefix(pathPrefix); - } if (authCacheKeeper != null) { authCacheKeeper.loadPreemptively(target, pathPrefix, targetAuthExchange, context); @@ -301,6 +298,9 @@ private boolean needAuthentication( targetNeedsAuth = authenticator.handleResponse(target, ChallengeType.TARGET, response, targetAuthStrategy, targetAuthExchange, context); + if (!targetAuthExchange.isConnectionBased() && targetAuthExchange.getPathPrefix() == null) { + targetAuthExchange.setPathPrefix(pathPrefix); + } if (authCacheKeeper != null) { authCacheKeeper.updateOnResponse(target, pathPrefix, targetAuthExchange, context); } diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/TestAsyncProtocolExec.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/TestAsyncProtocolExec.java new file mode 100644 index 0000000000..d9f9939699 --- /dev/null +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/TestAsyncProtocolExec.java @@ -0,0 +1,159 @@ +/* + * ==================================================================== + * 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 + * . + * + */ +package org.apache.hc.client5.http.impl.async; + +import java.io.IOException; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.hc.client5.http.AuthenticationStrategy; +import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.async.AsyncExecCallback; +import org.apache.hc.client5.http.async.AsyncExecChain; +import org.apache.hc.client5.http.async.AsyncExecRuntime; +import org.apache.hc.client5.http.auth.AuthExchange; +import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.ChallengeType; +import org.apache.hc.client5.http.auth.StandardAuthScheme; +import org.apache.hc.client5.http.impl.auth.BasicScheme; +import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.core5.concurrent.CancellableDependency; +import org.apache.hc.core5.http.EntityDetails; +import org.apache.hc.core5.http.HttpHeaders; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.message.BasicHttpResponse; +import org.apache.hc.core5.http.nio.AsyncDataConsumer; +import org.apache.hc.core5.http.nio.AsyncEntityProducer; +import org.apache.hc.core5.http.support.BasicRequestBuilder; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +class TestAsyncProtocolExec { + + @Mock + private AuthenticationStrategy targetAuthStrategy; + @Mock + private AuthenticationStrategy proxyAuthStrategy; + @Mock + private AsyncExecChain chain; + @Mock + private AsyncExecRuntime execRuntime; + + private AsyncProtocolExec protocolExec; + private HttpHost target; + + @BeforeEach + void setup() { + MockitoAnnotations.openMocks(this); + protocolExec = new AsyncProtocolExec(targetAuthStrategy, proxyAuthStrategy, null, true); + target = new HttpHost("http", "foo", 80); + } + + @Test + void testAuthExchangePathPrefixRestoredAfterChallenge() throws Exception { + final HttpRoute route = new HttpRoute(target); + final HttpClientContext context = HttpClientContext.create(); + context.setCredentialsProvider(CredentialsProviderBuilder.create() + .add(new AuthScope(target), "user", "pass".toCharArray()) + .build()); + + Mockito.when(targetAuthStrategy.select( + Mockito.eq(ChallengeType.TARGET), + Mockito.any(), + Mockito.any())) + .thenReturn(Collections.singletonList(new BasicScheme())); + + Mockito.when(execRuntime.isEndpointConnected()).thenReturn(true); + + final AtomicInteger proceedCount = new AtomicInteger(0); + + Mockito.doAnswer(invocation -> { + final AsyncExecCallback cb = invocation.getArgument(3, AsyncExecCallback.class); + final int i = proceedCount.getAndIncrement(); + + if (i == 0) { + final HttpResponse resp1 = new BasicHttpResponse(401, "Huh?"); + resp1.setHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=test"); + cb.handleResponse(resp1, (EntityDetails) null); + cb.completed(); + } else { + final HttpResponse resp2 = new BasicHttpResponse(200, "OK"); + cb.handleResponse(resp2, (EntityDetails) null); + cb.completed(); + } + return null; + }).when(chain).proceed(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any()); + + final HttpRequest request = BasicRequestBuilder.get("http://foo/blah/a").build(); + + final CancellableDependency dependency = Mockito.mock(CancellableDependency.class); + final AsyncExecChain.Scope scope = new AsyncExecChain.Scope( + "test", + route, + request, + dependency, + context, + execRuntime, + null, + new AtomicInteger(1)); + + final AsyncExecCallback asyncCallback = new AsyncExecCallback() { + @Override + public AsyncDataConsumer handleResponse(final HttpResponse response, final EntityDetails entityDetails) + throws IOException { + return Mockito.mock(AsyncDataConsumer.class); + } + + @Override + public void handleInformationResponse(final HttpResponse response) { + } + + @Override + public void completed() { + } + + @Override + public void failed(final Exception cause) { + Assertions.fail(cause); + } + }; + + protocolExec.execute(request, (AsyncEntityProducer) null, scope, chain, asyncCallback); + + Assertions.assertEquals(2, proceedCount.get()); + + final AuthExchange authExchange = context.getAuthExchange(target); + Assertions.assertEquals("/blah/", authExchange.getPathPrefix()); + } +} diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestProtocolExec.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestProtocolExec.java index 9f92bec242..7bf32fea51 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestProtocolExec.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestProtocolExec.java @@ -276,4 +276,37 @@ void testExecEntityEnclosingRequest() throws Exception { Assertions.assertEquals(401, response.getCode()); } + @Test + void testAuthExchangePathPrefixRestoredAfterChallenge() throws Exception { + final HttpRoute route = new HttpRoute(target); + final ClassicHttpRequest request = new HttpGet("http://foo/blah/a"); + final HttpClientContext context = HttpClientContext.create(); + + context.setCredentialsProvider(CredentialsProviderBuilder.create() + .add(new AuthScope(target), "user", "pass".toCharArray()) + .build()); + + final ClassicHttpResponse response1 = new BasicClassicHttpResponse(401, "Huh?"); + response1.setHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=test"); + final ClassicHttpResponse response2 = new BasicClassicHttpResponse(200, "OK"); + + Mockito.when(chain.proceed(Mockito.same(request), Mockito.any())) + .thenReturn(response1, response2); + + Mockito.when(targetAuthStrategy.select( + Mockito.eq(ChallengeType.TARGET), + Mockito.any(), + Mockito.any())) + .thenReturn(Collections.singletonList(new BasicScheme())); + + Mockito.when(execRuntime.isConnectionReusable()).thenReturn(true); + + final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, execRuntime, context); + final ClassicHttpResponse finalResponse = protocolExec.execute(request, scope, chain); + + Assertions.assertEquals(200, finalResponse.getCode()); + + final AuthExchange authExchange = context.getAuthExchange(target); + Assertions.assertEquals("/blah/", authExchange.getPathPrefix()); + } } From 30386d309614309b18e7b23953ee42bded18d57b Mon Sep 17 00:00:00 2001 From: Arturo Bernal Date: Thu, 19 Mar 2026 16:57:17 +0100 Subject: [PATCH 27/36] HTTPCLIENT-2417 Honor TlsConfig attachment in async connect path Make PoolingAsyncClientConnectionManager.connect() use the provided TlsConfig for direct TLS connections. (cherry picked from commit df4347f34528dd4b10b2aef968086dd589d99428) --- .../impl/nio/PoolingAsyncClientConnectionManager.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java index 6078a92352..eda6d39144 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java @@ -487,6 +487,15 @@ public Future connect( if (LOG.isDebugEnabled()) { LOG.debug("{} connecting endpoint to {} ({})", ConnPoolSupport.getId(endpoint), firstHop, connectTimeout); } + final Object connectAttachment; + if (route.isTunnelled()) { + connectAttachment = null; + } else if (attachment instanceof TlsConfig) { + connectAttachment = attachment; + } else { + connectAttachment = resolveTlsConfig(route.getTargetHost()); + } + final Future connectFuture = connectionOperator.connect( connectionInitiator, firstHop, @@ -494,7 +503,7 @@ public Future connect( route.getTargetName(), route.getLocalSocketAddress(), connectTimeout, - route.isTunnelled() ? null : resolveTlsConfig(route.getTargetHost()), + connectAttachment, context, new FutureCallback() { From c69f38f764814b3d9a24c4f0d6c9576385e0083c Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Mon, 23 Mar 2026 09:16:31 +0100 Subject: [PATCH 28/36] Bug-fix: corrects message exchange cancellation logic in InternalHttpAsyncExecRuntime * Fixes the problem with message exchanges over an existing persistent connection being non-cancellable * Response timeout not be applied to H2 endpoints * Test coverage --- .../InternalTestHttpAsyncExecRuntime.java | 151 ++++++++++++ .../TestInternalHttpAsyncExecRuntime.java | 217 ++++++++++++++++++ .../async/TestAsyncServerBootstrap.java | 6 +- .../async/InternalHttpAsyncExecRuntime.java | 69 ++++-- 4 files changed, 421 insertions(+), 22 deletions(-) create mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/http/impl/async/InternalTestHttpAsyncExecRuntime.java create mode 100644 httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestInternalHttpAsyncExecRuntime.java diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/http/impl/async/InternalTestHttpAsyncExecRuntime.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/http/impl/async/InternalTestHttpAsyncExecRuntime.java new file mode 100644 index 0000000000..91e12d3e52 --- /dev/null +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/http/impl/async/InternalTestHttpAsyncExecRuntime.java @@ -0,0 +1,151 @@ +/* + * ==================================================================== + * 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 + * . + * + */ +package org.apache.hc.client5.http.impl.async; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.hc.client5.http.HttpRoute; +import org.apache.hc.client5.http.async.AsyncExecRuntime; +import org.apache.hc.client5.http.config.TlsConfig; +import org.apache.hc.client5.http.nio.AsyncClientConnectionManager; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.core5.concurrent.BasicFuture; +import org.apache.hc.core5.concurrent.Cancellable; +import org.apache.hc.core5.concurrent.FutureContribution; +import org.apache.hc.core5.http.EntityDetails; +import org.apache.hc.core5.http.Header; +import org.apache.hc.core5.http.HttpException; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler; +import org.apache.hc.core5.http.nio.CapacityChannel; +import org.apache.hc.core5.http.nio.DataStreamChannel; +import org.apache.hc.core5.http.nio.RequestChannel; +import org.apache.hc.core5.http.protocol.HttpContext; +import org.apache.hc.core5.reactor.ConnectionInitiator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class InternalTestHttpAsyncExecRuntime extends InternalHttpAsyncExecRuntime { + + private static final Logger LOG = LoggerFactory.getLogger(InternalTestHttpAsyncExecRuntime.class); + + private final AtomicBoolean cancelled; + + public InternalTestHttpAsyncExecRuntime(final AsyncClientConnectionManager manager, + final ConnectionInitiator connectionInitiator, + final TlsConfig tlsConfig) { + super(LOG, manager, connectionInitiator, null, tlsConfig); + this.cancelled = new AtomicBoolean(); + } + + public Future leaseAndConnect(final HttpHost target, final HttpClientContext context) { + final BasicFuture resultFuture = new BasicFuture<>(null); + acquireEndpoint("test", new HttpRoute(target), null, context, new FutureContribution(resultFuture) { + + @Override + public void completed(final AsyncExecRuntime runtime) { + if (!runtime.isEndpointConnected()) { + runtime.connectEndpoint(context, new FutureContribution(resultFuture) { + + @Override + public void completed(final AsyncExecRuntime runtime) { + resultFuture.completed(true); + } + + }); + } else { + resultFuture.completed(true); + } + } + + }); + return resultFuture; + } + + @Override + public Cancellable execute(final String id, final AsyncClientExchangeHandler exchangeHandler, final HttpClientContext context) { + return super.execute(id, new AsyncClientExchangeHandler() { + + public void cancel() { + if (cancelled.compareAndSet(false, true)) { + exchangeHandler.cancel(); + } + } + + public void failed(final Exception cause) { + exchangeHandler.failed(cause); + } + + public void produceRequest(final RequestChannel channel, final HttpContext context) throws HttpException, IOException { + exchangeHandler.produceRequest(channel, context); + } + + public void consumeResponse(final HttpResponse response, final EntityDetails entityDetails, final HttpContext context) throws HttpException, IOException { + exchangeHandler.consumeResponse(response, entityDetails, context); + } + + public void consumeInformation(final HttpResponse response, final HttpContext context) throws HttpException, IOException { + exchangeHandler.consumeInformation(response, context); + } + + public void updateCapacity(final CapacityChannel capacityChannel) throws IOException { + exchangeHandler.updateCapacity(capacityChannel); + } + + public void consume(final ByteBuffer src) throws IOException { + exchangeHandler.consume(src); + } + + public void streamEnd(final List trailers) throws HttpException, IOException { + exchangeHandler.streamEnd(trailers); + } + + public void releaseResources() { + exchangeHandler.releaseResources(); + } + + public int available() { + return exchangeHandler.available(); + } + + public void produce(final DataStreamChannel channel) throws IOException { + exchangeHandler.produce(channel); + } + + }, context); + } + + public boolean isAborted() { + return cancelled.get(); + } + +} diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestInternalHttpAsyncExecRuntime.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestInternalHttpAsyncExecRuntime.java new file mode 100644 index 0000000000..6155ed1944 --- /dev/null +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestInternalHttpAsyncExecRuntime.java @@ -0,0 +1,217 @@ +/* + * ==================================================================== + * 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 + * . + * + */ +package org.apache.hc.client5.testing.async; + +import java.net.InetSocketAddress; +import java.util.concurrent.CancellationException; +import java.util.concurrent.Future; +import java.util.function.Consumer; + +import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; +import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder; +import org.apache.hc.client5.http.async.methods.SimpleRequestProducer; +import org.apache.hc.client5.http.async.methods.SimpleResponseConsumer; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.config.TlsConfig; +import org.apache.hc.client5.http.impl.async.InternalTestHttpAsyncExecRuntime; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.client5.testing.extension.async.ClientProtocolLevel; +import org.apache.hc.client5.testing.extension.async.ServerProtocolLevel; +import org.apache.hc.client5.testing.extension.async.TestAsyncClient; +import org.apache.hc.client5.testing.extension.async.TestAsyncResources; +import org.apache.hc.client5.testing.extension.async.TestAsyncServer; +import org.apache.hc.client5.testing.extension.async.TestAsyncServerBootstrap; +import org.apache.hc.core5.concurrent.BasicFuture; +import org.apache.hc.core5.concurrent.Cancellable; +import org.apache.hc.core5.concurrent.FutureContribution; +import org.apache.hc.core5.http.HttpHeaders; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpRequest; +import org.apache.hc.core5.http.URIScheme; +import org.apache.hc.core5.http.nio.support.BasicClientExchangeHandler; +import org.apache.hc.core5.http.support.BasicRequestBuilder; +import org.apache.hc.core5.http2.HttpVersionPolicy; +import org.apache.hc.core5.pool.PoolStats; +import org.apache.hc.core5.reactor.ConnectionInitiator; +import org.apache.hc.core5.util.TimeValue; +import org.apache.hc.core5.util.Timeout; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class TestInternalHttpAsyncExecRuntime { + + public static final Timeout TIMEOUT = Timeout.ofMinutes(1); + + @RegisterExtension + private final TestAsyncResources testResources; + + public TestInternalHttpAsyncExecRuntime() { + this.testResources = new TestAsyncResources(URIScheme.HTTP, ClientProtocolLevel.STANDARD, ServerProtocolLevel.STANDARD, TIMEOUT); + } + + public void configureServer(final Consumer serverCustomizer) { + testResources.configureServer(serverCustomizer); + } + + public HttpHost startServer() throws Exception { + final TestAsyncServer server = testResources.server(); + final InetSocketAddress inetSocketAddress = server.start(); + return new HttpHost(testResources.scheme().id, "localhost", inetSocketAddress.getPort()); + } + + public TestAsyncClient startClient() throws Exception { + final TestAsyncClient client = testResources.client(); + client.start(); + return client; + } + + static final int REQ_NUM = 5; + + HttpRequest createRequest(final HttpHost target) { + return BasicRequestBuilder.get() + .setHttpHost(target) + .setPath("/random/20000") + .addHeader(HttpHeaders.HOST, target.toHostString()) + .build(); + } + + @Test + void testExecutionCancellation_http11HardCancellation_connectionMarkedNonReusable() throws Exception { + configureServer(bootstrap -> bootstrap.register("/random/*", AsyncRandomHandler::new)); + final HttpHost target = startServer(); + + final TestAsyncClient client = startClient(); + final ConnectionInitiator connectionInitiator = client.getImplementation(); + final PoolingAsyncClientConnectionManager connectionManager = client.getConnectionManager(); + for (int i = 0; i < REQ_NUM; i++) { + final HttpClientContext context = HttpClientContext.create(); + + final InternalTestHttpAsyncExecRuntime testRuntime = new InternalTestHttpAsyncExecRuntime( + connectionManager, + connectionInitiator, + TlsConfig.custom() + .setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_1) + .build()); + final Future connectFuture = testRuntime.leaseAndConnect(target, context); + Assertions.assertTrue(connectFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit())); + + final BasicFuture resultFuture = new BasicFuture<>(null); + final Cancellable cancellable = testRuntime.execute( + "test-" + i, + new BasicClientExchangeHandler<>( + SimpleRequestProducer.create(SimpleRequestBuilder.get() + .setHttpHost(target) + .setPath("/random/20000") + .addHeader(HttpHeaders.HOST, target.toHostString()) + .build()), + SimpleResponseConsumer.create(), + new FutureContribution(resultFuture) { + + @Override + public void completed(final SimpleHttpResponse result) { + resultFuture.completed(result); + } + + }), + context); + // sleep a bit + Thread.sleep(i % 10); + cancellable.cancel(); + + // The message exchange is expected to get aborted + try { + resultFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit()); + } catch (final CancellationException expected) { + } + Assertions.assertTrue(testRuntime.isAborted()); + testRuntime.discardEndpoint(); + } + } + + @Test + void testExecutionCancellation_http11NoHardCancellation_connectionAlive() throws Exception { + configureServer(bootstrap -> bootstrap.register("/random/*", AsyncRandomHandler::new)); + final HttpHost target = startServer(); + + final TestAsyncClient client = startClient(); + final ConnectionInitiator connectionInitiator = client.getImplementation(); + final PoolingAsyncClientConnectionManager connectionManager = client.getConnectionManager(); + for (int i = 0; i < REQ_NUM; i++) { + final HttpClientContext context = HttpClientContext.create(); + context.setRequestConfig(RequestConfig.custom() + .setHardCancellationEnabled(false) + .build()); + + final InternalTestHttpAsyncExecRuntime testRuntime = new InternalTestHttpAsyncExecRuntime( + connectionManager, + connectionInitiator, + TlsConfig.custom() + .setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_1) + .build()); + final Future connectFuture = testRuntime.leaseAndConnect(target, context); + Assertions.assertTrue(connectFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit())); + + final BasicFuture resultFuture = new BasicFuture<>(null); + final Cancellable cancellable = testRuntime.execute( + "test-" + i, + new BasicClientExchangeHandler<>( + SimpleRequestProducer.create(SimpleRequestBuilder.get() + .setHttpHost(target) + .setPath("/random/20000") + .addHeader(HttpHeaders.HOST, target.toHostString()) + .build()), + SimpleResponseConsumer.create(), + new FutureContribution(resultFuture) { + + @Override + public void completed(final SimpleHttpResponse result) { + resultFuture.completed(result); + } + + }), + context); + // sleep a bit + Thread.sleep(i % 10); + cancellable.cancel(); + + // The message exchange should not get aborted and is expected to successfully complete + final SimpleHttpResponse response = resultFuture.get(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit()); + Assertions.assertNotNull(response); + Assertions.assertFalse(testRuntime.isAborted()); + // The underlying connection is expected to stay valid + Assertions.assertTrue(testRuntime.isEndpointConnected()); + testRuntime.markConnectionReusable(null, TimeValue.ofMinutes(1)); + testRuntime.releaseEndpoint(); + + final PoolStats totalStats = connectionManager.getTotalStats(); + Assertions.assertTrue(totalStats.getAvailable() > 0); + } + } + +} diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/extension/async/TestAsyncServerBootstrap.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/extension/async/TestAsyncServerBootstrap.java index 3bb742a6dc..897b702f0e 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/extension/async/TestAsyncServerBootstrap.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/extension/async/TestAsyncServerBootstrap.java @@ -66,7 +66,7 @@ public HandlerEntry(final String uriPattern, final T handler) { } private final URIScheme scheme; - private final ServerProtocolLevel serverProtocolLevel; + private ServerProtocolLevel serverProtocolLevel; private final List>> handlerList; private Timeout timeout; @@ -79,6 +79,10 @@ public TestAsyncServerBootstrap(final URIScheme scheme, final ServerProtocolLeve this.handlerList = new ArrayList<>(); } + public void setServerProtocolLevel(final ServerProtocolLevel serverProtocolLevel) { + this.serverProtocolLevel = serverProtocolLevel; + } + public ServerProtocolLevel getProtocolLevel() { return serverProtocolLevel; } diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncExecRuntime.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncExecRuntime.java index 28d59abaf4..80461a9649 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncExecRuntime.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncExecRuntime.java @@ -28,6 +28,7 @@ package org.apache.hc.client5.http.impl.async; import java.io.InterruptedIOException; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import org.apache.hc.client5.http.EndpointInfo; @@ -42,7 +43,10 @@ import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.core5.concurrent.CallbackContribution; import org.apache.hc.core5.concurrent.Cancellable; +import org.apache.hc.core5.concurrent.ComplexCancellable; import org.apache.hc.core5.concurrent.FutureCallback; +import org.apache.hc.core5.http.HttpVersion; +import org.apache.hc.core5.http.ProtocolVersion; import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler; import org.apache.hc.core5.http.nio.AsyncPushConsumer; import org.apache.hc.core5.http.nio.HandlerFactory; @@ -282,36 +286,58 @@ public EndpointInfo getEndpointInfo() { return endpoint != null ? endpoint.getInfo() : null; } + private Cancellable doExecute( + final String id, + final AsyncConnectionEndpoint endpoint, + final AsyncClientExchangeHandler exchangeHandler, + final HttpClientContext context) { + if (log.isDebugEnabled()) { + log.debug("{} start execution {}", ConnPoolSupport.getId(endpoint), id); + } + final RequestConfig requestConfig = context.getRequestConfigOrDefault(); + final Timeout responseTimeout = requestConfig.getResponseTimeout(); + final EndpointInfo endpointInfo = endpoint.getInfo(); + final ProtocolVersion version = endpointInfo != null ? endpointInfo.getProtocol() : null; + final boolean isH2 = version != null && version.greaterEquals(HttpVersion.HTTP_2); + if (!isH2 && responseTimeout != null) { + endpoint.setSocketTimeout(responseTimeout); + } + endpoint.execute(id, exchangeHandler, pushHandlerFactory, context); + if (requestConfig.isHardCancellationEnabled()) { + return new Cancellable() { + + private final AtomicBoolean cancelled = new AtomicBoolean(); + + @Override + public boolean cancel() { + if (cancelled.compareAndSet(false, true)) { + exchangeHandler.cancel(); + return true; + } + return false; + } + + }; + } else { + return Operations.nonCancellable(); + } + } + @Override public Cancellable execute( final String id, final AsyncClientExchangeHandler exchangeHandler, final HttpClientContext context) { final AsyncConnectionEndpoint endpoint = ensureValid(); if (endpoint.isConnected()) { - if (log.isDebugEnabled()) { - log.debug("{} start execution {}", ConnPoolSupport.getId(endpoint), id); - } - final RequestConfig requestConfig = context.getRequestConfigOrDefault(); - final Timeout responseTimeout = requestConfig.getResponseTimeout(); - if (responseTimeout != null) { - endpoint.setSocketTimeout(responseTimeout); - } - endpoint.execute(id, exchangeHandler, pushHandlerFactory, context); - if (context.getRequestConfigOrDefault().isHardCancellationEnabled()) { - return () -> { - exchangeHandler.cancel(); - return true; - }; - } + return doExecute(id, endpoint, exchangeHandler, context); } else { - connectEndpoint(context, new FutureCallback() { + final ComplexCancellable complexCancellable = new ComplexCancellable(); + final Cancellable connectCancellable = connectEndpoint(context, new FutureCallback() { @Override public void completed(final AsyncExecRuntime runtime) { - if (log.isDebugEnabled()) { - log.debug("{} start execution {}", ConnPoolSupport.getId(endpoint), id); - } try { - endpoint.execute(id, exchangeHandler, pushHandlerFactory, context); + final Cancellable executeCancellable = doExecute(id, endpoint, exchangeHandler, context); + complexCancellable.setDependency(executeCancellable); } catch (final RuntimeException ex) { failed(ex); } @@ -328,8 +354,9 @@ public void cancelled() { } }); + complexCancellable.setDependency(connectCancellable); + return complexCancellable; } - return Operations.nonCancellable(); } @Override From 3de8ad5e99a52b2a9c2f595a4ce8c9b00649d515 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 27 Mar 2026 13:41:04 +0100 Subject: [PATCH 29/36] Fixed DefaultClientTlsStrategy test failures on MacOS --- .../testing/sync/TestDefaultClientTlsStrategy.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestDefaultClientTlsStrategy.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestDefaultClientTlsStrategy.java index 6cc605094b..bf30e5d3e3 100644 --- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestDefaultClientTlsStrategy.java +++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestDefaultClientTlsStrategy.java @@ -30,7 +30,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.io.IOException; -import java.net.InetAddress; import java.net.Socket; import java.util.Objects; @@ -370,7 +369,7 @@ void testHostnameVerificationClient() throws Exception { final HttpHost target1 = new HttpHost("https", "localhost", server.getLocalPort()); - try (final Socket socket = new Socket(InetAddress.getLocalHost(), server.getLocalPort())) { + try (final Socket socket = new Socket("localhost", server.getLocalPort())) { final TlsSocketStrategy tlsStrategy = new DefaultClientTlsStrategy( SSLTestContexts.createClientSSLContext(), HostnameVerificationPolicy.CLIENT, @@ -388,7 +387,7 @@ void testHostnameVerificationClient() throws Exception { final HttpHost target2 = new HttpHost("https", "some-other-host", server.getLocalPort()); - try (final Socket socket = new Socket(InetAddress.getLocalHost(), server.getLocalPort())) { + try (final Socket socket = new Socket("localhost", server.getLocalPort())) { final TlsSocketStrategy tlsStrategy = new DefaultClientTlsStrategy( SSLTestContexts.createClientSSLContext(), HostnameVerificationPolicy.CLIENT, @@ -403,7 +402,7 @@ void testHostnameVerificationClient() throws Exception { context)); } - try (final Socket socket = new Socket(InetAddress.getLocalHost(), server.getLocalPort())) { + try (final Socket socket = new Socket("localhost", server.getLocalPort())) { final TlsSocketStrategy tlsStrategy = new DefaultClientTlsStrategy( SSLTestContexts.createClientSSLContext(), HostnameVerificationPolicy.CLIENT, @@ -432,7 +431,7 @@ void testHostnameVerificationBuiltIn() throws Exception { final HttpHost target1 = new HttpHost("https", "localhost", server.getLocalPort()); - try (final Socket socket = new Socket(InetAddress.getLocalHost(), server.getLocalPort())) { + try (final Socket socket = new Socket("localhost", server.getLocalPort())) { final TlsSocketStrategy tlsStrategy = new DefaultClientTlsStrategy( SSLTestContexts.createClientSSLContext(), HostnameVerificationPolicy.BUILTIN, @@ -450,7 +449,7 @@ void testHostnameVerificationBuiltIn() throws Exception { final HttpHost target2 = new HttpHost("https", "some-other-host", server.getLocalPort()); - try (final Socket socket = new Socket(InetAddress.getLocalHost(), server.getLocalPort())) { + try (final Socket socket = new Socket("localhost", server.getLocalPort())) { final TlsSocketStrategy tlsStrategy = new DefaultClientTlsStrategy( SSLTestContexts.createClientSSLContext(), HostnameVerificationPolicy.BUILTIN, From fa6b6d70af06195c0ffdaadd107e1673c7200114 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 12 Apr 2026 07:54:52 -0400 Subject: [PATCH 30/36] Add missing Javadoc for ConnectionConfig (#820) * Add missing Javadoc for ConnectionConfig * Adjust text after PR review. * Fix Javadoc typo --- .../client5/http/config/ConnectionConfig.java | 89 ++++++++++++++++++- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/config/ConnectionConfig.java b/httpclient5/src/main/java/org/apache/hc/client5/http/config/ConnectionConfig.java index 5c2f654985..d69949f1a4 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/config/ConnectionConfig.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/config/ConnectionConfig.java @@ -44,6 +44,16 @@ public class ConnectionConfig implements Cloneable { private static final Timeout DEFAULT_CONNECT_TIMEOUT = Timeout.ofMinutes(3); + /** + * The default connection configuration. + *
    + *
  • Timeout connectTimeout: 3 minutes
  • + *
  • Timeout socketTimeout: {@code null} (undefined)
  • + *
  • Timeout idleTimeout: {@code null} (undefined)
  • + *
  • TimeValue validateAfterInactivity: {@code null} (undefined)
  • + *
  • TimeValue timeToLive: {@code null} (undefined)
  • + *
+ */ public static final ConnectionConfig DEFAULT = new Builder().build(); private final Timeout connectTimeout; @@ -74,6 +84,10 @@ protected ConnectionConfig() { } /** + * Gets the default socket timeout value for I/O operations on connections created by this configuration. + * A timeout value of zero is interpreted as an infinite timeout. + * + * @return the default socket timeout value, defaults to null. * @see Builder#setSocketTimeout(Timeout) */ public Timeout getSocketTimeout() { @@ -81,6 +95,16 @@ public Timeout getSocketTimeout() { } /** + * Gets the timeout until the target endpoint acknowledges accepting the connection request. + *

+ * Note that isn't the same time as the new connection being fully established. An HTTPS connection cannot be considered fully established until the TLS + * handshake has been successfully completed. + *

+ *

+ * A timeout value of zero is interpreted as an infinite timeout. + *

+ * + * @return the timeout until the target endpoint acknowledges accepting the connection request, defaults to 3 minutes. * @see Builder#setConnectTimeout(Timeout) */ public Timeout getConnectTimeout() { @@ -88,6 +112,12 @@ public Timeout getConnectTimeout() { } /** + * Gets the maximum period of idleness for a connection. + *

+ * Implementations can use this value to discard connections that have been idle for too long. + *

+ * + * @return the maximum period of idleness for a connection, defaults to null. * @see Builder#setIdleTimeout(Timeout) */ public Timeout getIdleTimeout() { @@ -95,6 +125,9 @@ public Timeout getIdleTimeout() { } /** + * Gets the period of inactivity after which persistent connections must be re-validated. + * + * @return the period of inactivity after which persistent connections must be re-validated, defaults to null. * @see Builder#setValidateAfterInactivity(TimeValue) */ public TimeValue getValidateAfterInactivity() { @@ -102,6 +135,9 @@ public TimeValue getValidateAfterInactivity() { } /** + * Gets the total span of time connections can be kept alive or execute requests. + * + * @return the total span of time connections can be kept alive or execute requests, defaults to null. * @see Builder#setTimeToLive(TimeValue) (TimeValue) */ public TimeValue getTimeToLive() { @@ -126,10 +162,21 @@ public String toString() { return builder.toString(); } + /** + * Creates a new builder for {@link ConnectionConfig}. + * + * @return a new builder for {@link ConnectionConfig}. + */ public static ConnectionConfig.Builder custom() { return new Builder(); } + /** + * Creates a new builder for {@link ConnectionConfig} based on an existing instance. + * + * @param config the instance to copy. + * @return a new builder for {@link ConnectionConfig}. + */ public static ConnectionConfig.Builder copy(final ConnectionConfig config) { return new Builder() .setConnectTimeout(config.getConnectTimeout()) @@ -138,6 +185,9 @@ public static ConnectionConfig.Builder copy(final ConnectionConfig config) { .setTimeToLive(config.getTimeToLive()); } + /** + * Builder for {@link ConnectionConfig}. + */ public static class Builder { private Timeout socketTimeout; @@ -152,6 +202,10 @@ public static class Builder { } /** + * Sets the default socket timeout value for I/O operations on connections created by this configuration. + * + * @param soTimeout The default socket timeout value for I/O operations. + * @param timeUnit The time unit of the soTimeout parameter. * @return this instance. * @see #setSocketTimeout(Timeout) */ @@ -161,7 +215,7 @@ public Builder setSocketTimeout(final int soTimeout, final TimeUnit timeUnit) { } /** - * Determines the default socket timeout value for I/O operations on + * Sets the default socket timeout value for I/O operations on * connections created by this configuration. * A timeout value of zero is interpreted as an infinite timeout. *

@@ -174,6 +228,7 @@ public Builder setSocketTimeout(final int soTimeout, final TimeUnit timeUnit) { * Default: {@code null} (undefined) *

* + * @param soTimeout The default socket timeout value for I/O operations. * @return this instance. */ public Builder setSocketTimeout(final Timeout soTimeout) { @@ -182,7 +237,7 @@ public Builder setSocketTimeout(final Timeout soTimeout) { } /** - * Determines the timeout until a new connection is fully established. + * Sets the timeout until a new connection is fully established. *

* A timeout value of zero is interpreted as an infinite timeout. *

@@ -190,6 +245,7 @@ public Builder setSocketTimeout(final Timeout soTimeout) { * Default: 3 minutes *

* + * @param connectTimeout The timeout until a new connection is fully established. * @return this instance. */ public Builder setConnectTimeout(final Timeout connectTimeout) { @@ -198,6 +254,10 @@ public Builder setConnectTimeout(final Timeout connectTimeout) { } /** + * Sets the timeout until a new connection is fully established. + * + * @param connectTimeout The timeout until a new connection is fully established. + * @param timeUnit The time unit of the timeout parameter. * @return this instance. * @see #setConnectTimeout(Timeout) */ @@ -217,6 +277,7 @@ public Builder setConnectTimeout(final long connectTimeout, final TimeUnit timeU * Default: {@code null} (undefined) *

* + * @param idleTimeout The maximum period of idleness for a connection. * @return this instance. * * @since 5.6 @@ -227,6 +288,13 @@ public Builder setIdleTimeout(final Timeout idleTimeout) { } /** + * Sets the maximum period of idleness for a connection. + *

+ * Connections that are idle for longer than {@code idleTimeout} are no longer eligible for reuse. + *

+ * + * @param idleTimeout The maximum period of idleness for a connection. + * @param timeUnit * @return this instance. * @see #setIdleTimeout(Timeout) */ @@ -236,13 +304,14 @@ public Builder setIdleTimeout(final long idleTimeout, final TimeUnit timeUnit) { } /** - * Defines period of inactivity after which persistent connections must + * Sets the period of inactivity after which persistent connections must * be re-validated prior to being leased to the consumer. Negative values passed * to this method disable connection validation. *

* Default: {@code null} (undefined) *

* + * @param validateAfterInactivity The period of inactivity after which persistent connections must be re-validated. * @return this instance. */ public Builder setValidateAfterInactivity(final TimeValue validateAfterInactivity) { @@ -251,6 +320,10 @@ public Builder setValidateAfterInactivity(final TimeValue validateAfterInactivit } /** + * Sets the period of inactivity after which persistent connections must be re-validated prior to being leased to the consumer. + * + * @param validateAfterInactivity The period of inactivity after which persistent connections must be re-validated. + * @param timeUnit The time unit of the validateAfterInactivity parameter. * @return this instance. * @see #setValidateAfterInactivity(TimeValue) */ @@ -265,6 +338,7 @@ public Builder setValidateAfterInactivity(final long validateAfterInactivity, fi * Default: {@code null} (undefined) *

* + * @param timeToLive The total span of time connections can be kept alive or execute requests. * @return this instance. */ public Builder setTimeToLive(final TimeValue timeToLive) { @@ -273,6 +347,10 @@ public Builder setTimeToLive(final TimeValue timeToLive) { } /** + * Sets the total span of time connections can be kept alive or execute requests. + * + * @param timeToLive The total span of time connections can be kept alive or execute requests. + * @param timeUnit The time unit of the timeToLive parameter. * @return this instance. * @see #setTimeToLive(TimeValue) */ @@ -281,6 +359,11 @@ public Builder setTimeToLive(final long timeToLive, final TimeUnit timeUnit) { return this; } + /** + * Builds a new {@link ConnectionConfig} instance based on the values provided to the setters methods. + * + * @return a new {@link ConnectionConfig} instance. + */ public ConnectionConfig build() { return new ConnectionConfig( connectTimeout != null ? connectTimeout : DEFAULT_CONNECT_TIMEOUT, From 49549abca82842586cdce82e5f8a1bbd461a1ac7 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 12 Apr 2026 15:01:16 +0200 Subject: [PATCH 31/36] Auth challenge parsing code improvement --- .../http/impl/auth/AuthenticationHandler.java | 63 +++++++------------ 1 file changed, 22 insertions(+), 41 deletions(-) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/AuthenticationHandler.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/AuthenticationHandler.java index fc7e4a22dd..acf51dae24 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/AuthenticationHandler.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/AuthenticationHandler.java @@ -28,7 +28,6 @@ package org.apache.hc.client5.http.impl.auth; import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Locale; @@ -47,7 +46,6 @@ import org.apache.hc.core5.annotation.Contract; import org.apache.hc.core5.annotation.Internal; import org.apache.hc.core5.annotation.ThreadingBehavior; -import org.apache.hc.core5.http.FormattedHeader; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpHeaders; import org.apache.hc.core5.http.HttpHost; @@ -56,10 +54,9 @@ import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.ParseException; import org.apache.hc.core5.http.message.BasicHeader; -import org.apache.hc.core5.http.message.ParserCursor; +import org.apache.hc.core5.http.message.MessageSupport; import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.util.Asserts; -import org.apache.hc.core5.util.CharArrayBuffer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -169,43 +166,27 @@ public Map extractChallengeMap( final HttpResponse response, final HttpClientContext context) { final Map challengeMap = new HashMap<>(); - final Iterator
headerIterator = response.headerIterator( - challengeType == ChallengeType.PROXY ? HttpHeaders.PROXY_AUTHENTICATE : HttpHeaders.WWW_AUTHENTICATE); - while (headerIterator.hasNext()) { - final Header header = headerIterator.next(); - final CharArrayBuffer buffer; - final int pos; - if (header instanceof FormattedHeader) { - buffer = ((FormattedHeader) header).getBuffer(); - pos = ((FormattedHeader) header).getValuePos(); - } else { - final String s = header.getValue(); - if (s == null) { - continue; - } - buffer = new CharArrayBuffer(s.length()); - buffer.append(s); - pos = 0; - } - final ParserCursor cursor = new ParserCursor(pos, buffer.length()); - final List authChallenges; - try { - authChallenges = parser.parse(challengeType, buffer, cursor); - } catch (final ParseException ex) { - if (LOG.isWarnEnabled()) { - final HttpClientContext clientContext = HttpClientContext.cast(context); - final String exchangeId = clientContext.getExchangeId(); - LOG.warn("{} Malformed challenge: {}", exchangeId, header.getValue()); - } - continue; - } - for (final AuthChallenge authChallenge : authChallenges) { - final String schemeName = authChallenge.getSchemeName().toLowerCase(Locale.ROOT); - if (!challengeMap.containsKey(schemeName)) { - challengeMap.put(schemeName, authChallenge); - } - } - } + MessageSupport.parseHeaders( + response, + challengeType == ChallengeType.PROXY ? HttpHeaders.PROXY_AUTHENTICATE : HttpHeaders.WWW_AUTHENTICATE, + (buffer, cursor) -> { + try { + final List authChallenges = parser.parse(challengeType, buffer, cursor); + for (final AuthChallenge authChallenge : authChallenges) { + final String schemeName = authChallenge.getSchemeName().toLowerCase(Locale.ROOT); + if (!challengeMap.containsKey(schemeName)) { + challengeMap.put(schemeName, authChallenge); + } + } + } catch (final ParseException ex) { + if (LOG.isWarnEnabled()) { + final HttpClientContext clientContext = HttpClientContext.cast(context); + final String exchangeId = clientContext.getExchangeId(); + LOG.warn("{} Malformed challenge", exchangeId); + } + } + + }); return challengeMap; } From 1acf00b879d908a869508ceee2edb0fe65b69d73 Mon Sep 17 00:00:00 2001 From: Arturo Bernal Date: Wed, 15 Apr 2026 09:17:36 +0200 Subject: [PATCH 32/36] Fix SCRAM final response handling --- .../impl/DefaultAuthenticationStrategy.java | 1 - .../http/impl/auth/AuthenticationHandler.java | 27 ++ .../client5/http/impl/auth/ScramScheme.java | 115 +++++++- .../examples/ClientScramAuthentication.java | 81 ++++++ .../impl/auth/TestAuthenticationHandler.java | 46 ++++ .../http/impl/auth/TestScramScheme.java | 259 ++++++++++++++---- 6 files changed, 455 insertions(+), 74 deletions(-) create mode 100644 httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientScramAuthentication.java diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultAuthenticationStrategy.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultAuthenticationStrategy.java index ba480f3f03..d5f403a00e 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultAuthenticationStrategy.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/DefaultAuthenticationStrategy.java @@ -69,7 +69,6 @@ public class DefaultAuthenticationStrategy implements AuthenticationStrategy { private static final List DEFAULT_SCHEME_PRIORITY = Collections.unmodifiableList(Arrays.asList( StandardAuthScheme.BEARER, - StandardAuthScheme.SCRAM_SHA_256, StandardAuthScheme.DIGEST, StandardAuthScheme.BASIC)); diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/AuthenticationHandler.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/AuthenticationHandler.java index acf51dae24..1205a1367d 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/AuthenticationHandler.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/AuthenticationHandler.java @@ -27,6 +27,7 @@ package org.apache.hc.client5.http.impl.auth; +import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -52,8 +53,10 @@ import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.NameValuePair; import org.apache.hc.core5.http.ParseException; import org.apache.hc.core5.http.message.BasicHeader; +import org.apache.hc.core5.http.message.BasicHeaderValueParser; import org.apache.hc.core5.http.message.MessageSupport; import org.apache.hc.core5.http.protocol.HttpContext; import org.apache.hc.core5.util.Asserts; @@ -227,6 +230,30 @@ public boolean handleResponse( } final Map challengeMap = extractChallengeMap(challengeType, response, clientContext); + if (challengeMap.isEmpty() && !challenged && isChallengeExpected) { + final AuthScheme authScheme = authExchange.getAuthScheme(); + if (authScheme != null) { + MessageSupport.parseHeaders( + response, + challengeType == ChallengeType.PROXY ? "Proxy-Authentication-Info" : "Authentication-Info", + (buffer, cursor) -> { + final String schemeName = authScheme.getName(); + final List params = new ArrayList<>(); + while (!cursor.atEnd()) { + final NameValuePair param = BasicHeaderValueParser.INSTANCE.parseNameValuePair(buffer, cursor); + params.add(param); + if (!cursor.atEnd()) { + final char ch = buffer.charAt(cursor.getPos()); + if (ch == ',') { + cursor.updatePos(cursor.getPos() + 1); + } + } + } + final AuthChallenge authChallenge = new AuthChallenge(challengeType, schemeName, null, params); + challengeMap.put(schemeName.toLowerCase(Locale.ROOT), authChallenge); + }); + } + } if (challengeMap.isEmpty()) { if (LOG.isDebugEnabled()) { diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/ScramScheme.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/ScramScheme.java index 1c1224de53..3cf3978581 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/ScramScheme.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/ScramScheme.java @@ -80,6 +80,9 @@ public final class ScramScheme implements AuthScheme { private static final Logger LOG = LoggerFactory.getLogger(ScramScheme.class); + private static final int DEFAULT_WARN_MIN_ITERATIONS = 4096; + private static final int DEFAULT_MAX_ITERATIONS_ALLOWED = 100000; + // RFC 7804 / RFC 5802 fixed no-CB GS2 header and its base64 value for 'c=' private static final String GS2_HEADER = "n,,"; private static final String C_BIND_B64 = "biws"; // base64("n,,") @@ -100,6 +103,7 @@ private enum State { private final SecureRandom secureRandom; private final int warnMinIterations; private final int minIterationsRequired; + private final int maxIterationsAllowed; private State state = State.INIT; private boolean complete; @@ -128,7 +132,7 @@ private enum State { * @since 5.6 */ public ScramScheme() { - this(4096, 0, null); + this(DEFAULT_WARN_MIN_ITERATIONS, 0, DEFAULT_MAX_ITERATIONS_ALLOWED, null); } /** @@ -140,8 +144,26 @@ public ScramScheme() { * @since 5.6 */ public ScramScheme(final int warnMinIterations, final int minIterationsRequired, final SecureRandom rnd) { + this(warnMinIterations, minIterationsRequired, DEFAULT_MAX_ITERATIONS_ALLOWED, rnd); + } + + /** + * Constructor with custom iteration policy. + * + * @param warnMinIterations warn if iteration count is lower than this (0 disables warnings) + * @param minIterationsRequired fail if iteration count is lower than this (0 disables enforcement) + * @param maxIterationsAllowed fail if iteration count is greater than this (must be positive) + * @param rnd optional secure random source (null uses system default) + * @since 5.6 + */ + public ScramScheme( + final int warnMinIterations, + final int minIterationsRequired, + final int maxIterationsAllowed, + final SecureRandom rnd) { this.warnMinIterations = Math.max(0, warnMinIterations); this.minIterationsRequired = Math.max(0, minIterationsRequired); + this.maxIterationsAllowed = Args.positive(maxIterationsAllowed, "Max iterations allowed"); this.secureRandom = rnd != null ? rnd : new SecureRandom(); } @@ -206,9 +228,10 @@ public void processChallenge( Args.notNull(context, "HTTP context"); if (authChallenge == null) { - if (!challenged) { - // Final response with no Authentication-Info: nothing to do - return; + if (!challenged && this.state == State.CLIENT_FINAL_SENT) { + zeroAndClearExpectedV(); + this.state = State.FAILED; + throw new AuthenticationException("Missing SCRAM Authentication-Info"); } throw new MalformedChallengeException("Null SCRAM challenge"); } @@ -232,10 +255,32 @@ public void processChallenge( return; } + final String sid = params.get("sid"); + if (sid == null || sid.isEmpty()) { + zeroAndClearExpectedV(); + this.state = State.FAILED; + throw new MalformedChallengeException("SCRAM server-first missing sid"); + } + // server-first (data present) - final String decoded = b64ToString(data); + final String decoded; + try { + decoded = b64ToString(data); + } catch (final MalformedChallengeException ex) { + zeroAndClearExpectedV(); + this.state = State.FAILED; + throw ex; + } this.serverFirstRaw = decoded; - final Map attrs = parseAttrs(decoded); + + final Map attrs; + try { + attrs = parseAttrs(decoded); + } catch (final MalformedChallengeException ex) { + zeroAndClearExpectedV(); + this.state = State.FAILED; + throw ex; + } final String r = attrs.get("r"); final String s = attrs.get("s"); @@ -249,7 +294,6 @@ public void processChallenge( throw new AuthenticationException("SCRAM server nonce does not start with client nonce"); } - this.sid = params.get("sid"); try { this.salt = B64D.decode(s); if (this.salt.length == 0) { @@ -274,10 +318,16 @@ public void processChallenge( throw new AuthenticationException( "SCRAM iteration count below required minimum: " + this.iterations + " < " + this.minIterationsRequired); } + if (this.iterations > this.maxIterationsAllowed) { + this.state = State.FAILED; + throw new AuthenticationException( + "SCRAM iteration count above allowed maximum: " + this.iterations + " > " + this.maxIterationsAllowed); + } if (this.warnMinIterations > 0 && this.iterations < this.warnMinIterations && LOG.isWarnEnabled()) { LOG.warn("SCRAM iteration count ({}) lower than recommended ({})", this.iterations, warnMinIterations); } + this.sid = sid; this.serverNonce = r; this.state = State.SERVER_FIRST_RCVD; this.complete = false; @@ -285,14 +335,49 @@ public void processChallenge( return; } + if (this.state != State.CLIENT_FINAL_SENT) { + final State currentState = this.state; + zeroAndClearExpectedV(); + this.state = State.FAILED; + throw new AuthenticationException("SCRAM final response out of sequence: " + currentState); + } + + final String sid = params.get("sid"); + if (sid == null || sid.isEmpty()) { + zeroAndClearExpectedV(); + this.state = State.FAILED; + throw new MalformedChallengeException("SCRAM Authentication-Info missing sid"); + } + if (this.sid == null || !this.sid.equals(sid)) { + zeroAndClearExpectedV(); + this.state = State.FAILED; + throw new AuthenticationException("SCRAM sid mismatch"); + } + // --- final-response path (Authentication-Info on any status) --- // For Authentication-Info, RFC 7804 does NOT mandate a scheme token; do NOT enforce scheme name here. final String data = params.get("data"); if (data == null) { - return; + zeroAndClearExpectedV(); + this.state = State.FAILED; + throw new MalformedChallengeException("SCRAM Authentication-Info missing data"); + } + final String decoded; + try { + decoded = b64ToString(data); + } catch (final MalformedChallengeException ex) { + zeroAndClearExpectedV(); + this.state = State.FAILED; + throw ex; + } + final Map attrs; + try { + attrs = parseAttrs(decoded); + } catch (final MalformedChallengeException ex) { + zeroAndClearExpectedV(); + this.state = State.FAILED; + throw ex; } - final String decoded = b64ToString(data); - final Map attrs = parseAttrs(decoded); final String err = attrs.get("e"); if (err != null) { this.state = State.FAILED; @@ -303,7 +388,9 @@ public void processChallenge( } final String vB64 = attrs.get("v"); if (vB64 == null) { - return; + zeroAndClearExpectedV(); + this.state = State.FAILED; + throw new MalformedChallengeException("SCRAM Authentication-Info missing v"); } // compare 'v' in constant time; treat bad base64 for v as a signature mismatch (tests expect "signature") @@ -335,7 +422,7 @@ public void processChallenge( */ @Override public boolean isChallengeComplete() { - return this.complete || this.state == State.COMPLETE || this.state == State.FAILED; + return this.state == State.FAILED; } /** @@ -486,9 +573,7 @@ private String buildClientFinalAndExpectV() throws AuthenticationException { final StringBuilder sb = new StringBuilder(64); sb.append(StandardAuthScheme.SCRAM_SHA_256).append(' '); - if (this.sid != null) { - sb.append("sid=").append(quoteParam(this.sid)).append(", "); - } + sb.append("sid=").append(quoteParam(this.sid)).append(", "); sb.append("data=").append(quoteParam(data)); // quoted this.state = State.CLIENT_FINAL_SENT; diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientScramAuthentication.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientScramAuthentication.java new file mode 100644 index 0000000000..fb37e7c7b8 --- /dev/null +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientScramAuthentication.java @@ -0,0 +1,81 @@ +/* + * ==================================================================== + * 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 + * . + * + */ +package org.apache.hc.client5.http.examples; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.apache.hc.client5.http.auth.StandardAuthScheme; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.message.StatusLine; + +/** + * An example of how to explicitly enable {@code SCRAM-SHA-256} authentication. + * SCRAM-SHA-256 is not part of the default auth scheme preference list and + * must be opted into by placing it on the preferred auth schemes list of + * the {@link RequestConfig}. + * + * @since 5.7 + */ +public class ClientScramAuthentication { + + public static void main(final String[] args) throws Exception { + final List priority = Collections.unmodifiableList(Arrays.asList( + StandardAuthScheme.SCRAM_SHA_256, + StandardAuthScheme.BEARER)); + + final HttpHost target = new HttpHost("http", "httpbin.org", 80); + + try (final CloseableHttpClient httpclient = HttpClients.custom() + .setDefaultRequestConfig(RequestConfig.custom() + .setTargetPreferredAuthSchemes(priority) + .setProxyPreferredAuthSchemes(priority) + .build()) + .setDefaultCredentialsProvider(CredentialsProviderBuilder.create() + .add(target, "user", "passwd".toCharArray()) + .build()) + .build()) { + + final HttpGet httpget = new HttpGet("http://httpbin.org/basic-auth/user/passwd"); + + System.out.println("Executing request " + httpget.getMethod() + " " + httpget.getUri()); + httpclient.execute(httpget, response -> { + System.out.println("----------------------------------------"); + System.out.println(httpget + "->" + new StatusLine(response)); + EntityUtils.consume(response.getEntity()); + return null; + }); + } + } +} diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestAuthenticationHandler.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestAuthenticationHandler.java index 272342be51..48f5b82056 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestAuthenticationHandler.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestAuthenticationHandler.java @@ -29,6 +29,7 @@ import java.util.LinkedList; import java.util.Queue; +import org.apache.hc.client5.http.auth.AuthChallenge; import org.apache.hc.client5.http.auth.AuthExchange; import org.apache.hc.client5.http.auth.AuthScheme; import org.apache.hc.client5.http.auth.AuthSchemeFactory; @@ -48,6 +49,7 @@ import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpResponse; import org.apache.hc.core5.http.HttpStatus; +import org.apache.hc.core5.http.NameValuePair; import org.apache.hc.core5.http.config.Lookup; import org.apache.hc.core5.http.config.RegistryBuilder; import org.apache.hc.core5.http.message.BasicHeader; @@ -58,6 +60,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Answers; +import org.mockito.ArgumentCaptor; import org.mockito.Mockito; class TestAuthenticationHandler { @@ -481,4 +484,47 @@ void testAuthSuccessConnectionBased() throws Exception { Mockito.any(HttpContext.class)); } + private static String getParam(final AuthChallenge authChallenge, final String name) { + for (final NameValuePair param : authChallenge.getParams()) { + if (param.getName().equalsIgnoreCase(name)) { + return param.getValue(); + } + } + return null; + } + + @Test + void testAuthenticationInfoProcessedOnSuccessResponse() throws Exception { + final HttpHost host = new HttpHost("somehost", 80); + final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK, "OK"); + response.addHeader(new BasicHeader("Authentication-Info", "sid=\"sid-1\", data=\"dj1hYmM\"")); + + final AuthScheme authScheme = Mockito.mock(AuthScheme.class); + Mockito.when(authScheme.getName()).thenReturn(StandardAuthScheme.SCRAM_SHA_256); + Mockito.when(authScheme.isChallengeExpected()).thenReturn(Boolean.TRUE); + Mockito.when(authScheme.isChallengeComplete()).thenReturn(Boolean.FALSE); + + this.authExchange.select(authScheme); + this.authExchange.setState(AuthExchange.State.HANDSHAKE); + + final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy(); + + Assertions.assertFalse(this.httpAuthenticator.handleResponse( + host, ChallengeType.TARGET, response, authStrategy, this.authExchange, this.context)); + Assertions.assertEquals(AuthExchange.State.SUCCESS, this.authExchange.getState()); + + final ArgumentCaptor challengeCaptor = ArgumentCaptor.forClass(AuthChallenge.class); + Mockito.verify(authScheme).processChallenge( + Mockito.eq(host), + Mockito.eq(false), + challengeCaptor.capture(), + Mockito.same(this.context)); + + final AuthChallenge challenge = challengeCaptor.getValue(); + Assertions.assertNotNull(challenge); + Assertions.assertEquals(StandardAuthScheme.SCRAM_SHA_256, challenge.getSchemeName()); + Assertions.assertEquals("sid-1", getParam(challenge, "sid")); + Assertions.assertEquals("dj1hYmM", getParam(challenge, "data")); + } + } diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestScramScheme.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestScramScheme.java index ae383e529b..c2f15cb783 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestScramScheme.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestScramScheme.java @@ -24,7 +24,6 @@ * . * */ - package org.apache.hc.client5.http.impl.auth; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -63,7 +62,7 @@ final class TestScramScheme { private static final String REALM = "s1"; private static final String USER = "u"; private static final String PASS = "p"; - + private static final String SID = "sid-1"; static String b64(final byte[] b) { return Base64.getEncoder().withoutPadding().encodeToString(b); @@ -73,10 +72,6 @@ static byte[] b64d(final String s) { return Base64.getDecoder().decode(s); } - static String b64s(final String s) { - return b64(s.getBytes(StandardCharsets.UTF_8)); - } - static String deb64s(final String s) { return new String(b64d(s), StandardCharsets.UTF_8); } @@ -86,7 +81,9 @@ static Map parseCsvAttrs(final String s) { int i = 0; while (i < s.length()) { final int eq = s.indexOf('=', i); - if (eq < 0) break; + if (eq < 0) { + break; + } final String k = s.substring(i, eq); i = eq + 1; final StringBuilder v = new StringBuilder(); @@ -105,7 +102,6 @@ static Map parseCsvAttrs(final String s) { } static Map splitHeader(final String header) { - // "SCRAM-SHA-256 realm="...", data="..."" -> name/value map (lowercase keys) final int sp = header.indexOf(' '); final String params = header.substring(sp + 1); final Map map = new HashMap<>(); @@ -136,7 +132,6 @@ static byte[] hmac(final byte[] key, final String msg) throws GeneralSecurityExc return mac.doFinal(msg.getBytes(StandardCharsets.UTF_8)); } - @Test void strictScram_fullRoundtrip_completes() throws Exception { final ScramScheme scheme = new ScramScheme(); @@ -145,40 +140,36 @@ void strictScram_fullRoundtrip_completes() throws Exception { new UsernamePasswordCredentials(USER, PASS.toCharArray())); final HttpClientContext ctx = HttpClientContext.create(); - // 401 announce (no data) scheme.processChallenge(HOST, true, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), new BasicNameValuePair("realm", REALM)), ctx); assertTrue(scheme.isResponseReady(HOST, creds, ctx)); - // Authorization (client-first) final String authz1 = scheme.generateAuthResponse(HOST, null, ctx); final Map h1 = splitHeader(authz1); assertEquals(REALM, h1.get("realm")); final String clientFirst = deb64s(h1.get("data")); - assertTrue(clientFirst.startsWith("n,,"), "GS2 header missing"); + assertTrue(clientFirst.startsWith("n,,")); final String clientFirstBare = clientFirst.substring("n,,".length()); - final Map cf1 = parseCsvAttrs(clientFirstBare); - final String clientNonce = cf1.get("r"); + final String clientNonce = parseCsvAttrs(clientFirstBare).get("r"); assertNotNull(clientNonce); - // 401 server-first final String saltB64 = b64("salt-256".getBytes(StandardCharsets.UTF_8)); final int iters = 4096; final String serverFirst = "r=" + clientNonce + "XYZ,s=" + saltB64 + ",i=" + iters; scheme.processChallenge(HOST, true, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), - new BasicNameValuePair("sid", "sid-1"), + new BasicNameValuePair("sid", SID), new BasicNameValuePair("data", b64(serverFirst.getBytes(StandardCharsets.UTF_8)))), ctx); final String authz2 = scheme.generateAuthResponse(HOST, null, ctx); final Map h2 = splitHeader(authz2); - assertEquals("sid-1", h2.get("sid")); + assertEquals(SID, h2.get("sid")); final String clientFinal = deb64s(h2.get("data")); final Map cf2 = parseCsvAttrs(clientFinal); - assertEquals("biws", cf2.get("c")); // Base64("n,,") + assertEquals("biws", cf2.get("c")); final String clientFinalNoProof = "c=" + cf2.get("c") + ",r=" + cf2.get("r"); final String authMessage = clientFirstBare + "," + serverFirst + "," + clientFinalNoProof; @@ -188,10 +179,56 @@ void strictScram_fullRoundtrip_completes() throws Exception { scheme.processChallenge(HOST, false, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), new BasicNameValuePair("data", b64(("v=" + vB64).getBytes(StandardCharsets.UTF_8)))), ctx); - assertTrue(scheme.isChallengeComplete()); + assertFalse(scheme.isChallengeComplete()); + } + + @Test + void strictScram_lowIterations_warnsButSucceeds() throws Exception { + final ScramScheme scheme = new ScramScheme(4096, 0, 100000, null); + final BasicCredentialsProvider creds = new BasicCredentialsProvider(); + creds.setCredentials(new AuthScope(HOST, REALM, scheme.getName()), + new UsernamePasswordCredentials(USER, PASS.toCharArray())); + final HttpClientContext ctx = HttpClientContext.create(); + + scheme.processChallenge(HOST, true, + new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("realm", REALM)), + ctx); + assertTrue(scheme.isResponseReady(HOST, creds, ctx)); + + final String authz1 = scheme.generateAuthResponse(HOST, null, ctx); + final String clientFirstBare = deb64s(splitHeader(authz1).get("data")).substring("n,,".length()); + final String clientNonce = parseCsvAttrs(clientFirstBare).get("r"); + + final String saltB64 = b64("salt-low".getBytes(StandardCharsets.UTF_8)); + final String serverFirst = "r=" + clientNonce + "Z,s=" + saltB64 + ",i=1024"; + scheme.processChallenge(HOST, true, + new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), + new BasicNameValuePair("data", b64(serverFirst.getBytes(StandardCharsets.UTF_8)))), + ctx); + + final String authz2 = scheme.generateAuthResponse(HOST, null, ctx); + final String clientFinal = deb64s(splitHeader(authz2).get("data")); + final Map cf = parseCsvAttrs(clientFinal); + final String clientFinalNoProof = "c=" + cf.get("c") + ",r=" + cf.get("r"); + final String authMessage = clientFirstBare + "," + serverFirst + "," + clientFinalNoProof; + + final byte[] salted = pbkdf2(PASS.toCharArray(), b64d(saltB64), 1024, 32); + final byte[] serverKey = hmac(salted, "Server Key"); + final String vB64 = b64(hmac(serverKey, authMessage)); + + scheme.processChallenge(HOST, false, + new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), + new BasicNameValuePair("data", b64(("v=" + vB64).getBytes(StandardCharsets.UTF_8)))), + ctx); + + assertFalse(scheme.isChallengeComplete()); } @Test @@ -202,33 +239,56 @@ void strictScram_invalidServerNonce_rejectedAt401() throws Exception { new UsernamePasswordCredentials(USER, PASS.toCharArray())); final HttpClientContext ctx = HttpClientContext.create(); - // 401 announce scheme.processChallenge(HOST, true, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), new BasicNameValuePair("realm", REALM)), ctx); assertTrue(scheme.isResponseReady(HOST, creds, ctx)); - - // Send client-first so the client nonce is generated and state is correct. - // We don't need the header content here. scheme.generateAuthResponse(HOST, null, ctx); - // Bad server-first: nonce does NOT start with the client nonce final String badServerFirst = "r=NOTPREFIXED,s=" + b64("salt".getBytes(StandardCharsets.UTF_8)) + ",i=4096"; - final AuthenticationException ex = assertThrows(AuthenticationException.class, () -> scheme.processChallenge(HOST, true, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), new BasicNameValuePair("data", b64(badServerFirst.getBytes(StandardCharsets.UTF_8)))), ctx)); - assertTrue(ex.getMessage().toLowerCase(Locale.ROOT).contains("nonce")); + assertTrue(scheme.isChallengeComplete()); } + @Test + void strictScram_minIterations_enforced() throws Exception { + final ScramScheme scheme = new ScramScheme(4096, 4096, 100000, null); + final BasicCredentialsProvider creds = new BasicCredentialsProvider(); + creds.setCredentials(new AuthScope(HOST, REALM, scheme.getName()), + new UsernamePasswordCredentials(USER, PASS.toCharArray())); + final HttpClientContext ctx = HttpClientContext.create(); + + scheme.processChallenge(HOST, true, + new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("realm", REALM)), + ctx); + assertTrue(scheme.isResponseReady(HOST, creds, ctx)); + + final String authz1 = scheme.generateAuthResponse(HOST, null, ctx); + final String clientFirstBare = deb64s(splitHeader(authz1).get("data")).substring("n,,".length()); + final String clientNonce = parseCsvAttrs(clientFirstBare).get("r"); + + final String serverFirst = "r=" + clientNonce + "Z,s=" + b64("salt".getBytes(StandardCharsets.UTF_8)) + ",i=1024"; + final AuthenticationException ex = assertThrows(AuthenticationException.class, () -> + scheme.processChallenge(HOST, true, + new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), + new BasicNameValuePair("data", b64(serverFirst.getBytes(StandardCharsets.UTF_8)))), + ctx)); + assertTrue(ex.getMessage().toLowerCase(Locale.ROOT).contains("iteration")); + assertTrue(scheme.isChallengeComplete()); + } @Test - void strictScram_lowIterations_warnsButSucceeds() throws Exception { - final ScramScheme scheme = new ScramScheme(4096, 0, null); // warn only + void strictScram_maxIterations_enforced() throws Exception { + final ScramScheme scheme = new ScramScheme(4096, 0, 8192, null); final BasicCredentialsProvider creds = new BasicCredentialsProvider(); creds.setCredentials(new AuthScope(HOST, REALM, scheme.getName()), new UsernamePasswordCredentials(USER, PASS.toCharArray())); @@ -244,11 +304,67 @@ void strictScram_lowIterations_warnsButSucceeds() throws Exception { final String clientFirstBare = deb64s(splitHeader(authz1).get("data")).substring("n,,".length()); final String clientNonce = parseCsvAttrs(clientFirstBare).get("r"); - // server-first with i=1024 (below warn threshold) - final String saltB64 = b64("salt-low".getBytes(StandardCharsets.UTF_8)); - final String serverFirst = "r=" + clientNonce + "Z,s=" + saltB64 + ",i=1024"; + final String serverFirst = "r=" + clientNonce + "Z,s=" + b64("salt".getBytes(StandardCharsets.UTF_8)) + ",i=20000"; + final AuthenticationException ex = assertThrows(AuthenticationException.class, () -> + scheme.processChallenge(HOST, true, + new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), + new BasicNameValuePair("data", b64(serverFirst.getBytes(StandardCharsets.UTF_8)))), + ctx)); + assertTrue(ex.getMessage().toLowerCase(Locale.ROOT).contains("maximum")); + assertTrue(scheme.isChallengeComplete()); + } + + @Test + void strictScram_missingSidInServerFirst_isMalformed() throws Exception { + final ScramScheme scheme = new ScramScheme(); + final BasicCredentialsProvider creds = new BasicCredentialsProvider(); + creds.setCredentials(new AuthScope(HOST, REALM, scheme.getName()), + new UsernamePasswordCredentials(USER, PASS.toCharArray())); + final HttpClientContext ctx = HttpClientContext.create(); + + scheme.processChallenge(HOST, true, + new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("realm", REALM)), + ctx); + assertTrue(scheme.isResponseReady(HOST, creds, ctx)); + final String authz1 = scheme.generateAuthResponse(HOST, null, ctx); + final String clientFirstBare = deb64s(splitHeader(authz1).get("data")).substring("n,,".length()); + final String clientNonce = parseCsvAttrs(clientFirstBare).get("r"); + + final String serverFirst = "r=" + clientNonce + "Z,s=" + b64("salt".getBytes(StandardCharsets.UTF_8)) + ",i=4096"; + final MalformedChallengeException ex = assertThrows(MalformedChallengeException.class, () -> + scheme.processChallenge(HOST, true, + new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("data", b64(serverFirst.getBytes(StandardCharsets.UTF_8)))), + ctx)); + assertTrue(ex.getMessage().toLowerCase(Locale.ROOT).contains("sid")); + assertTrue(scheme.isChallengeComplete()); + } + + @Test + void strictScram_authInfo_missingSid_fails() throws Exception { + final ScramScheme scheme = new ScramScheme(); + final BasicCredentialsProvider creds = new BasicCredentialsProvider(); + creds.setCredentials(new AuthScope(HOST, REALM, scheme.getName()), + new UsernamePasswordCredentials(USER, PASS.toCharArray())); + final HttpClientContext ctx = HttpClientContext.create(); + scheme.processChallenge(HOST, true, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("realm", REALM)), + ctx); + assertTrue(scheme.isResponseReady(HOST, creds, ctx)); + + final String authz1 = scheme.generateAuthResponse(HOST, null, ctx); + final String clientFirstBare = deb64s(splitHeader(authz1).get("data")).substring("n,,".length()); + final String clientNonce = parseCsvAttrs(clientFirstBare).get("r"); + + final String saltB64 = b64("salt".getBytes(StandardCharsets.UTF_8)); + final String serverFirst = "r=" + clientNonce + "Z,s=" + saltB64 + ",i=4096"; + scheme.processChallenge(HOST, true, + new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), new BasicNameValuePair("data", b64(serverFirst.getBytes(StandardCharsets.UTF_8)))), ctx); @@ -257,23 +373,22 @@ void strictScram_lowIterations_warnsButSucceeds() throws Exception { final Map cf = parseCsvAttrs(clientFinal); final String clientFinalNoProof = "c=" + cf.get("c") + ",r=" + cf.get("r"); final String authMessage = clientFirstBare + "," + serverFirst + "," + clientFinalNoProof; - - final byte[] salted = pbkdf2(PASS.toCharArray(), b64d(saltB64), 1024, 32); + final byte[] salted = pbkdf2(PASS.toCharArray(), b64d(saltB64), 4096, 32); final byte[] serverKey = hmac(salted, "Server Key"); final String vB64 = b64(hmac(serverKey, authMessage)); - // 2xx with v -> success - scheme.processChallenge(HOST, false, - new AuthChallenge(ChallengeType.TARGET, scheme.getName(), - new BasicNameValuePair("data", b64(("v=" + vB64).getBytes(StandardCharsets.UTF_8)))), - ctx); - + final MalformedChallengeException ex = assertThrows(MalformedChallengeException.class, () -> + scheme.processChallenge(HOST, false, + new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("data", b64(("v=" + vB64).getBytes(StandardCharsets.UTF_8)))), + ctx)); + assertTrue(ex.getMessage().toLowerCase(Locale.ROOT).contains("sid")); assertTrue(scheme.isChallengeComplete()); } @Test - void strictScram_minIterations_enforced() throws Exception { - final ScramScheme scheme = new ScramScheme(4096, 4096, null); // hard min 4096 + void strictScram_authInfo_sidMismatch_fails() throws Exception { + final ScramScheme scheme = new ScramScheme(); final BasicCredentialsProvider creds = new BasicCredentialsProvider(); creds.setCredentials(new AuthScope(HOST, REALM, scheme.getName()), new UsernamePasswordCredentials(USER, PASS.toCharArray())); @@ -289,14 +404,31 @@ void strictScram_minIterations_enforced() throws Exception { final String clientFirstBare = deb64s(splitHeader(authz1).get("data")).substring("n,,".length()); final String clientNonce = parseCsvAttrs(clientFirstBare).get("r"); - // server-first with i=1024 (below hard min) -> fail immediately at processChallenge(401) - final String serverFirst = "r=" + clientNonce + "Z,s=" + b64("salt".getBytes(StandardCharsets.UTF_8)) + ",i=1024"; + final String saltB64 = b64("salt".getBytes(StandardCharsets.UTF_8)); + final String serverFirst = "r=" + clientNonce + "Z,s=" + saltB64 + ",i=4096"; + scheme.processChallenge(HOST, true, + new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), + new BasicNameValuePair("data", b64(serverFirst.getBytes(StandardCharsets.UTF_8)))), + ctx); + + final String authz2 = scheme.generateAuthResponse(HOST, null, ctx); + final String clientFinal = deb64s(splitHeader(authz2).get("data")); + final Map cf = parseCsvAttrs(clientFinal); + final String clientFinalNoProof = "c=" + cf.get("c") + ",r=" + cf.get("r"); + final String authMessage = clientFirstBare + "," + serverFirst + "," + clientFinalNoProof; + final byte[] salted = pbkdf2(PASS.toCharArray(), b64d(saltB64), 4096, 32); + final byte[] serverKey = hmac(salted, "Server Key"); + final String vB64 = b64(hmac(serverKey, authMessage)); + final AuthenticationException ex = assertThrows(AuthenticationException.class, () -> - scheme.processChallenge(HOST, true, + scheme.processChallenge(HOST, false, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), - new BasicNameValuePair("data", b64(serverFirst.getBytes(StandardCharsets.UTF_8)))), + new BasicNameValuePair("sid", "sid-other"), + new BasicNameValuePair("data", b64(("v=" + vB64).getBytes(StandardCharsets.UTF_8)))), ctx)); - assertTrue(ex.getMessage().toLowerCase(Locale.ROOT).contains("iteration")); + assertTrue(ex.getMessage().toLowerCase(Locale.ROOT).contains("sid")); + assertTrue(scheme.isChallengeComplete()); } @Test @@ -320,19 +452,20 @@ void strictScram_authInfo_mismatchV_fails() throws Exception { final String serverFirst = "r=" + clientNonce + "Z,s=" + b64("salt".getBytes(StandardCharsets.UTF_8)) + ",i=4096"; scheme.processChallenge(HOST, true, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), new BasicNameValuePair("data", b64(serverFirst.getBytes(StandardCharsets.UTF_8)))), ctx); - // client-final scheme.generateAuthResponse(HOST, null, ctx); - // 2xx with wrong v final MalformedChallengeException ex = assertThrows(MalformedChallengeException.class, () -> scheme.processChallenge(HOST, false, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), new BasicNameValuePair("data", b64("v=WRONG".getBytes(StandardCharsets.UTF_8)))), ctx)); assertTrue(ex.getMessage().toLowerCase(Locale.ROOT).contains("signature")); + assertTrue(scheme.isChallengeComplete()); } @Test @@ -356,18 +489,20 @@ void strictScram_authInfo_errorE_fails() throws Exception { final String serverFirst = "r=" + clientNonce + "Z,s=" + b64("salt".getBytes(StandardCharsets.UTF_8)) + ",i=4096"; scheme.processChallenge(HOST, true, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), new BasicNameValuePair("data", b64(serverFirst.getBytes(StandardCharsets.UTF_8)))), ctx); scheme.generateAuthResponse(HOST, null, ctx); - // 2xx with e= final AuthenticationException ex = assertThrows(AuthenticationException.class, () -> scheme.processChallenge(HOST, false, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), new BasicNameValuePair("data", b64("e=server-fail".getBytes(StandardCharsets.UTF_8)))), ctx)); assertTrue(ex.getMessage().contains("server error")); + assertTrue(scheme.isChallengeComplete()); } @Test @@ -378,9 +513,11 @@ void strictScram_badBase64In401Data_isMalformed() { final MalformedChallengeException ex = assertThrows(MalformedChallengeException.class, () -> scheme.processChallenge(HOST, true, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), new BasicNameValuePair("data", "%%%not-base64%%%")), ctx)); assertTrue(ex.getMessage().toLowerCase(Locale.ROOT).contains("base64")); + assertTrue(scheme.isChallengeComplete()); } @Test @@ -391,9 +528,11 @@ void strictScram_missingAttrsInServerFirst_isMalformed() { final MalformedChallengeException ex = assertThrows(MalformedChallengeException.class, () -> scheme.processChallenge(HOST, true, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), new BasicNameValuePair("data", b64("r=only".getBytes(StandardCharsets.UTF_8)))), ctx)); assertTrue(ex.getMessage().toLowerCase(Locale.ROOT).contains("missing")); + assertTrue(scheme.isChallengeComplete()); } @Test @@ -404,7 +543,6 @@ void testPreemptiveAuthentication() throws Exception { new UsernamePasswordCredentials(USER, PASS.toCharArray())); final HttpClientContext ctx = HttpClientContext.create(); - // Test that we can generate a response without receiving a challenge first assertTrue(scheme.isResponseReady(HOST, creds, ctx)); final String response = scheme.generateAuthResponse(HOST, null, ctx); assertNotNull(response); @@ -427,31 +565,38 @@ void testInvalidBase64InAuthInfo() throws Exception { new UsernamePasswordCredentials(USER, PASS.toCharArray())); final HttpClientContext ctx = HttpClientContext.create(); - // Go through the initial flow scheme.processChallenge(HOST, true, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), new BasicNameValuePair("realm", REALM)), ctx); + assertTrue(scheme.isResponseReady(HOST, creds, ctx)); + final String authz1 = scheme.generateAuthResponse(HOST, null, ctx); + final String clientFirstBare = deb64s(splitHeader(authz1).get("data")).substring("n,,".length()); + final String clientNonce = parseCsvAttrs(clientFirstBare).get("r"); + + final String serverFirst = "r=" + clientNonce + "Z,s=" + b64("salt".getBytes(StandardCharsets.UTF_8)) + ",i=4096"; + scheme.processChallenge(HOST, true, + new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), + new BasicNameValuePair("data", b64(serverFirst.getBytes(StandardCharsets.UTF_8)))), + ctx); scheme.generateAuthResponse(HOST, null, ctx); - // Test with invalid base64 in Authentication-Info final MalformedChallengeException ex = assertThrows(MalformedChallengeException.class, () -> scheme.processChallenge(HOST, false, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), + new BasicNameValuePair("sid", SID), new BasicNameValuePair("data", "invalid-base64")), ctx)); assertTrue(ex.getMessage().toLowerCase(Locale.ROOT).contains("base64")); + assertTrue(scheme.isChallengeComplete()); } @Test void testInvalidStateTransition() throws Exception { final ScramScheme scheme = new ScramScheme(); - final BasicCredentialsProvider creds = new BasicCredentialsProvider(); - creds.setCredentials(new AuthScope(HOST, REALM, scheme.getName()), - new UsernamePasswordCredentials(USER, PASS.toCharArray())); final HttpClientContext ctx = HttpClientContext.create(); - // Try to generate a response without proper state setup final AuthenticationException ex = assertThrows(AuthenticationException.class, () -> scheme.generateAuthResponse(HOST, null, ctx)); assertTrue(ex.getMessage().toLowerCase(Locale.ROOT).contains("sequence")); @@ -465,7 +610,6 @@ void testEmptyPassword() throws Exception { new UsernamePasswordCredentials(USER, "".toCharArray())); final HttpClientContext ctx = HttpClientContext.create(); - // This should work without throwing exceptions scheme.processChallenge(HOST, true, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), new BasicNameValuePair("realm", REALM)), @@ -483,7 +627,6 @@ void testSpecialCharacters() throws Exception { new UsernamePasswordCredentials(specialUser, specialPass.toCharArray())); final HttpClientContext ctx = HttpClientContext.create(); - // Test the full flow with special characters scheme.processChallenge(HOST, true, new AuthChallenge(ChallengeType.TARGET, scheme.getName(), new BasicNameValuePair("realm", REALM)), From 1b2bafe817552369466a925e0cb3592deb303a26 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 15 Apr 2026 10:42:30 +0200 Subject: [PATCH 33/36] Updated release notes for HttpClient 5.6.1 release --- RELEASE_NOTES.txt | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 8dc4d71a6d..b633bb3a7c 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,3 +1,50 @@ +Release 5.6.1 +------------------ + +This is a maintenance release disables experimental SCRAM auth scheme by default and +fixes SCRAM final response handling. The SCRAM auth scheme can be re-enabled by +choosing a custom auth scheme preference sequence that explicitly includes SCRAM auth. + + +Change Log +------------------- + +* Fix SCRAM final response handling. + Contributed by Arturo Bernal + +* Auth challenge parsing code improvement. + Contributed by Oleg Kalnichevski + +* Add missing Javadoc for ConnectionConfig (#820). + Contributed by Gary Gregory + +* Bug fix: Corrected async message exchange cancellation logic in + InternalHttpAsyncExecRuntime. + Contributed by Oleg Kalnichevski + +* HTTPCLIENT-2417: Honor TlsConfig attachment in async connect path. + Contributed by Arturo Bernal + +* HTTPCLIENT-2414: Fix Basic auth cache scoping across path prefixes (#802). + Contributed by Arturo Bernal + +* HTTPCLIENT-2415: Normalize CookieOrigin path for cookie matching (#803). + Contributed by Arturo Bernal + +* Bug fix: Corrected sleep time calculation in IdleConnectionEvictor; use 1 minute sleep + time by default. + Contributed by Oleg Kalnichevski + +* DefaultManagedHttpClientConnection: Restore original socket timeout. + Contributed by Ryan Schmitt + +* HTTPCLIENT-2411: Use standard HTTP-date format for synthesized Date header (#775). + Contributed by Arturo Bernal + +* Fix NPE in connection evictor setup (#774). + Contributed by Arturo Bernal + + Release 5.6 ------------------ From dba9b8e11d094395336089a06cf60ca3bb087fe8 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sun, 19 Apr 2026 10:28:34 +0200 Subject: [PATCH 34/36] Upgraded HttpClient version to 5.6.2-SNAPSHOT --- httpclient5-cache/pom.xml | 2 +- httpclient5-fluent/pom.xml | 2 +- httpclient5-observation/pom.xml | 2 +- httpclient5-testing/pom.xml | 2 +- httpclient5/pom.xml | 2 +- .../publicsuffix/list/effective_tld_names.dat | 3637 ++++++++++------- pom.xml | 4 +- 7 files changed, 2116 insertions(+), 1535 deletions(-) diff --git a/httpclient5-cache/pom.xml b/httpclient5-cache/pom.xml index ffec1e1bf6..82d101935d 100644 --- a/httpclient5-cache/pom.xml +++ b/httpclient5-cache/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6.1-SNAPSHOT + 5.6.2-SNAPSHOT httpclient5-cache Apache HttpClient Cache diff --git a/httpclient5-fluent/pom.xml b/httpclient5-fluent/pom.xml index 264a0eca56..353f152dbe 100644 --- a/httpclient5-fluent/pom.xml +++ b/httpclient5-fluent/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6.1-SNAPSHOT + 5.6.2-SNAPSHOT httpclient5-fluent Apache HttpClient Fluent diff --git a/httpclient5-observation/pom.xml b/httpclient5-observation/pom.xml index 7d6a743bee..16a2a962fd 100644 --- a/httpclient5-observation/pom.xml +++ b/httpclient5-observation/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6.1-SNAPSHOT + 5.6.2-SNAPSHOT httpclient5-observation diff --git a/httpclient5-testing/pom.xml b/httpclient5-testing/pom.xml index 0158ea90f0..e4d647714b 100644 --- a/httpclient5-testing/pom.xml +++ b/httpclient5-testing/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6.1-SNAPSHOT + 5.6.2-SNAPSHOT httpclient5-testing Apache HttpClient Integration Tests diff --git a/httpclient5/pom.xml b/httpclient5/pom.xml index 94ec434a6d..ba4ab52914 100644 --- a/httpclient5/pom.xml +++ b/httpclient5/pom.xml @@ -28,7 +28,7 @@ org.apache.httpcomponents.client5 httpclient5-parent - 5.6.1-SNAPSHOT + 5.6.2-SNAPSHOT httpclient5 Apache HttpClient diff --git a/httpclient5/src/main/resources/org/publicsuffix/list/effective_tld_names.dat b/httpclient5/src/main/resources/org/publicsuffix/list/effective_tld_names.dat index 0e75882bb0..29e6f4e01e 100644 --- a/httpclient5/src/main/resources/org/publicsuffix/list/effective_tld_names.dat +++ b/httpclient5/src/main/resources/org/publicsuffix/list/effective_tld_names.dat @@ -5,6 +5,9 @@ // Please pull this list from, and only from https://publicsuffix.org/list/public_suffix_list.dat, // rather than any other VCS sites. Pulling from any other URL is not guaranteed to be supported. +// VERSION: 2026-04-10_20-27-44_UTC +// COMMIT: 8f9e04f2be9098ada07aa3cf13592dfe78870985 + // Instructions on pulling and using this list can be found at https://publicsuffix.org/list/. // ===BEGIN ICANN DOMAINS=== @@ -14,23 +17,23 @@ ac com.ac edu.ac gov.ac -net.ac mil.ac +net.ac org.ac -// ad : https://en.wikipedia.org/wiki/.ad +// ad : https://www.iana.org/domains/root/db/ad.html +// Confirmed by Amadeu Abril i Abril (CORE) 2024-11-17 ad -nom.ad -// ae : https://tdra.gov.ae/en/aeda/ae-policies +// ae : https://www.iana.org/domains/root/db/ae.html ae +ac.ae co.ae +gov.ae +mil.ae net.ae org.ae sch.ae -ac.ae -gov.ae -mil.ae // aero : https://information.aero/registration/policies/dmp aero @@ -132,27 +135,27 @@ union.aero workinggroup.aero works.aero -// af : http://www.nic.af/help.jsp +// af : https://www.nic.af/domain-price af -gov.af com.af -org.af -net.af edu.af +gov.af +net.af +org.af // ag : http://www.nic.ag/prices.htm ag +co.ag com.ag -org.ag net.ag -co.ag nom.ag +org.ag // ai : http://nic.com.ai/ ai -off.ai com.ai net.ai +off.ai org.ai // al : http://www.ert.gov.al/ert_alb/faq_det.html?Id=31 @@ -165,6 +168,7 @@ net.al org.al // am : https://www.amnic.net/policy/en/Policy_EN.pdf +// Confirmed by ISOC AM 2024-11-18 am co.am com.am @@ -172,17 +176,20 @@ commune.am net.am org.am -// ao : https://en.wikipedia.org/wiki/.ao -// http://www.dns.ao/REGISTR.DOC +// ao : https://www.iana.org/domains/root/db/ao.html +// https://www.dns.ao/ao/ ao +co.ao ed.ao +edu.ao +gov.ao gv.ao +it.ao og.ao -co.ao +org.ao pb.ao -it.ao -// aq : https://en.wikipedia.org/wiki/.aq +// aq : https://www.iana.org/domains/root/db/aq.html aq // ar : https://nic.ar/es/nic-argentina/normativa @@ -199,51 +206,53 @@ musica.ar mutual.ar net.ar org.ar +seg.ar senasa.ar tur.ar -// arpa : https://en.wikipedia.org/wiki/.arpa +// arpa : https://www.iana.org/domains/root/db/arpa.html // Confirmed by registry 2008-06-18 arpa e164.arpa +home.arpa in-addr.arpa ip6.arpa iris.arpa uri.arpa urn.arpa -// as : https://en.wikipedia.org/wiki/.as +// as : https://www.iana.org/domains/root/db/as.html as gov.as -// asia : https://en.wikipedia.org/wiki/.asia +// asia : https://www.iana.org/domains/root/db/asia.html asia -// at : https://en.wikipedia.org/wiki/.at +// at : https://www.iana.org/domains/root/db/at.html // Confirmed by registry 2008-06-17 at ac.at +sth.ac.at co.at gv.at or.at -sth.ac.at -// au : https://en.wikipedia.org/wiki/.au -// http://www.auda.org.au/ +// au : https://www.iana.org/domains/root/db/au.html +// https://www.auda.org.au/ +// Confirmed by registry 2025-07-16 au // 2LDs +asn.au com.au -net.au -org.au edu.au gov.au -asn.au id.au +net.au +org.au // Historic 2LDs (closed to new registration, but sites still exist) -info.au conf.au oz.au -// CGDNs - http://www.cgdn.org.au/ +// CGDNs : https://www.auda.org.au/au-domain-names/the-different-au-domain-names/state-and-territory-domain-names/ act.au nsw.au nt.au @@ -263,9 +272,9 @@ sa.edu.au tas.edu.au vic.edu.au wa.edu.au -// act.gov.au Bug 984824 - Removed at request of Greg Tankard -// nsw.gov.au Bug 547985 - Removed at request of -// nt.gov.au Bug 940478 - Removed at request of Greg Connors +// act.gov.au - Bug 984824 - Removed at request of Greg Tankard +// nsw.gov.au - Bug 547985 - Removed at request of +// nt.gov.au - Bug 940478 - Removed at request of Greg Connors qld.gov.au sa.gov.au tas.gov.au @@ -273,31 +282,35 @@ vic.gov.au wa.gov.au // 4LDs // education.tas.edu.au - Removed at the request of the Department of Education Tasmania -schools.nsw.edu.au +// schools.nsw.edu.au - Removed at the request of the New South Wales Department of Education. -// aw : https://en.wikipedia.org/wiki/.aw +// aw : https://www.iana.org/domains/root/db/aw.html aw com.aw -// ax : https://en.wikipedia.org/wiki/.ax +// ax : https://www.iana.org/domains/root/db/ax.html ax -// az : https://en.wikipedia.org/wiki/.az +// az : https://www.iana.org/domains/root/db/az.html +// Confirmed via https://whois.az/?page_id=10 2024-12-11 az +biz.az +co.az com.az -net.az -int.az -gov.az -org.az edu.az +gov.az info.az -pp.az +int.az mil.az name.az +net.az +org.az +pp.az +// No longer available for registration, however domains exist as of 2024-12-11 +// see https://whois.az/?page_id=783 pro.az -biz.az -// ba : http://nic.ba/users_data/files/pravilnik_o_registraciji.pdf +// ba : https://www.iana.org/domains/root/db/ba.html ba com.ba edu.ba @@ -306,7 +319,7 @@ mil.ba net.ba org.ba -// bb : https://en.wikipedia.org/wiki/.bb +// bb : https://www.iana.org/domains/root/db/bb.html bb biz.bb co.bb @@ -319,21 +332,46 @@ org.bb store.bb tv.bb -// bd : https://en.wikipedia.org/wiki/.bd -*.bd - -// be : https://en.wikipedia.org/wiki/.be +// bd : https://www.iana.org/domains/root/db/bd.html +// Confirmed by registry +bd +ac.bd +ai.bd +co.bd +com.bd +edu.bd +gov.bd +id.bd +info.bd +it.bd +mil.bd +net.bd +org.bd +sch.bd +tv.bd + +// be : https://www.iana.org/domains/root/db/be.html // Confirmed by registry 2008-06-08 be ac.be -// bf : https://en.wikipedia.org/wiki/.bf +// bf : https://www.iana.org/domains/root/db/bf.html bf gov.bf -// bg : https://en.wikipedia.org/wiki/.bg +// bg : https://www.iana.org/domains/root/db/bg.html // https://www.register.bg/user/static/rules/en/index.html bg +0.bg +1.bg +2.bg +3.bg +4.bg +5.bg +6.bg +7.bg +8.bg +9.bg a.bg b.bg c.bg @@ -360,26 +398,16 @@ w.bg x.bg y.bg z.bg -0.bg -1.bg -2.bg -3.bg -4.bg -5.bg -6.bg -7.bg -8.bg -9.bg -// bh : https://en.wikipedia.org/wiki/.bh +// bh : https://www.iana.org/domains/root/db/bh.html bh com.bh edu.bh +gov.bh net.bh org.bh -gov.bh -// bi : https://en.wikipedia.org/wiki/.bi +// bi : https://www.iana.org/domains/root/db/bi.html // http://whois.nic.bi/ bi co.bi @@ -388,11 +416,11 @@ edu.bi or.bi org.bi -// biz : https://en.wikipedia.org/wiki/.biz +// biz : https://www.iana.org/domains/root/db/biz.html biz // bj : https://nic.bj/bj-suffixes.txt -// submitted by registry +// Submitted by registry bj africa.bj agro.bj @@ -410,12 +438,12 @@ money.bj net.bj org.bj ote.bj -resto.bj restaurant.bj +resto.bj tourism.bj univ.bj -// bm : http://www.bermudanic.bm/dnr-text.txt +// bm : https://www.bermudanic.bm/domain-registration/index.php bm com.bm edu.bm @@ -431,15 +459,16 @@ gov.bn net.bn org.bn -// bo : https://nic.bo/delegacion2015.php#h-1.10 +// bo : https://nic.bo +// Confirmed by registry 2024-11-19 bo com.bo edu.bo gob.bo int.bo -org.bo -net.bo mil.bo +net.bo +org.bo tv.bo web.bo // Social Domains @@ -465,9 +494,9 @@ natural.bo nombre.bo noticias.bo patria.bo +plurinacional.bo politica.bo profesional.bo -plurinacional.bo pueblo.bo revista.bo salud.bo @@ -488,6 +517,7 @@ aju.br am.br anani.br aparecida.br +api.br app.br arq.br art.br @@ -495,6 +525,7 @@ ato.br b.br barueri.br belem.br +bet.br bhz.br bib.br bio.br @@ -572,6 +603,7 @@ se.gov.br sp.gov.br to.gov.br gru.br +ia.br imb.br ind.br inf.br @@ -582,6 +614,7 @@ joinville.br jor.br jus.br leg.br +leilao.br lel.br log.br londrina.br @@ -631,6 +664,7 @@ seg.br sjc.br slg.br slz.br +social.br sorocaba.br srv.br taxi.br @@ -647,17 +681,18 @@ vet.br vix.br vlog.br wiki.br +xyz.br zlg.br // bs : http://www.nic.bs/rules.html bs com.bs -net.bs -org.bs edu.bs gov.bs +net.bs +org.bs -// bt : https://en.wikipedia.org/wiki/.bt +// bt : https://www.iana.org/domains/root/db/bt.html bt com.bt edu.bt @@ -669,14 +704,16 @@ org.bt // Submitted by registry bv -// bw : https://en.wikipedia.org/wiki/.bw -// http://www.gobin.info/domainname/bw.doc -// list of other 2nd level tlds ? +// bw : https://www.iana.org/domains/root/db/bw.html +// https://nic.net.bw/bw-name-structure bw +ac.bw co.bw +gov.bw +net.bw org.bw -// by : https://en.wikipedia.org/wiki/.by +// by : https://www.iana.org/domains/root/db/by.html // http://tld.by/rules_2006_en.html // list of other 2nd level tlds ? by @@ -689,16 +726,17 @@ com.by // http://hoster.by/ of.by -// bz : https://en.wikipedia.org/wiki/.bz +// bz : https://www.iana.org/domains/root/db/bz.html // http://www.belizenic.bz/ bz +co.bz com.bz -net.bz -org.bz edu.bz gov.bz +net.bz +org.bz -// ca : https://en.wikipedia.org/wiki/.ca +// ca : https://www.iana.org/domains/root/db/ca.html ca // ca geographical names ab.ca @@ -719,46 +757,43 @@ yk.ca // see also: http://registry.gc.ca/en/SubdomainFAQ gc.ca -// cat : https://en.wikipedia.org/wiki/.cat +// cat : https://www.iana.org/domains/root/db/cat.html cat -// cc : https://en.wikipedia.org/wiki/.cc +// cc : https://www.iana.org/domains/root/db/cc.html cc -// cd : https://en.wikipedia.org/wiki/.cd -// see also: https://www.nic.cd/domain/insertDomain_2.jsp?act=1 +// cd : https://www.iana.org/domains/root/db/cd.html +// https://www.nic.cd cd gov.cd -// cf : https://en.wikipedia.org/wiki/.cf +// cf : https://www.iana.org/domains/root/db/cf.html cf -// cg : https://en.wikipedia.org/wiki/.cg +// cg : https://www.iana.org/domains/root/db/cg.html cg -// ch : https://en.wikipedia.org/wiki/.ch +// ch : https://www.iana.org/domains/root/db/ch.html ch -// ci : https://en.wikipedia.org/wiki/.ci -// http://www.nic.ci/index.php?page=charte +// ci : https://www.iana.org/domains/root/db/ci.html ci -org.ci -or.ci -com.ci +ac.ci +aéroport.ci +asso.ci co.ci -edu.ci +com.ci ed.ci -ac.ci -net.ci +edu.ci go.ci -asso.ci -aéroport.ci -int.ci -presse.ci -md.ci gouv.ci +int.ci +net.ci +or.ci +org.ci -// ck : https://en.wikipedia.org/wiki/.ck +// ck : https://www.iana.org/domains/root/db/ck.html *.ck !www.ck @@ -770,26 +805,26 @@ gob.cl gov.cl mil.cl -// cm : https://en.wikipedia.org/wiki/.cm plus bug 981927 +// cm : https://www.iana.org/domains/root/db/cm.html plus bug 981927 cm co.cm com.cm gov.cm net.cm -// cn : https://en.wikipedia.org/wiki/.cn +// cn : https://www.iana.org/domains/root/db/cn.html // Submitted by registry cn ac.cn com.cn edu.cn gov.cn +mil.cn net.cn org.cn -mil.cn 公司.cn -网络.cn 網絡.cn +网络.cn // cn geographic names ah.cn bj.cn @@ -797,18 +832,20 @@ cq.cn fj.cn gd.cn gs.cn -gz.cn gx.cn +gz.cn ha.cn hb.cn he.cn hi.cn +hk.cn hl.cn hn.cn jl.cn js.cn jx.cn ln.cn +mo.cn nm.cn nx.cn qh.cn @@ -818,38 +855,31 @@ sh.cn sn.cn sx.cn tj.cn +tw.cn xj.cn xz.cn yn.cn zj.cn -hk.cn -mo.cn -tw.cn -// co : https://en.wikipedia.org/wiki/.co -// Submitted by registry +// co : https://www.iana.org/domains/root/db/co.html +// https://www.cointernet.com.co/como-funciona-un-dominio-restringido +// Confirmed by registry 2024-11-18 co -arts.co com.co edu.co -firm.co gov.co -info.co -int.co mil.co net.co nom.co org.co -rec.co -web.co -// com : https://en.wikipedia.org/wiki/.com +// com : https://www.iana.org/domains/root/db/com.html com -// coop : https://en.wikipedia.org/wiki/.coop +// coop : https://www.iana.org/domains/root/db/coop.html coop -// cr : http://www.nic.cr/niccr_publico/showRegistroDominiosScreen.do +// cr : https://nic.cr/capitulo-1-registro-de-un-nombre-de-dominio/ cr ac.cr co.cr @@ -859,40 +889,45 @@ go.cr or.cr sa.cr -// cu : https://en.wikipedia.org/wiki/.cu +// cu : https://www.iana.org/domains/root/db/cu.html cu com.cu edu.cu -org.cu -net.cu -gov.cu +gob.cu inf.cu +nat.cu +net.cu +org.cu -// cv : https://en.wikipedia.org/wiki/.cv -// cv : http://www.dns.cv/tldcv_portal/do?com=DS;5446457100;111;+PAGE(4000018)+K-CAT-CODIGO(RDOM)+RCNT(100); <- registration rules +// cv : https://www.iana.org/domains/root/db/cv.html +// https://ola.cv/domain-extensions-under-cv/ +// Confirmed by registry 2024-11-26 cv com.cv edu.cv +id.cv int.cv +net.cv nome.cv org.cv +publ.cv -// cw : http://www.una.cw/cw_registry/ -// Confirmed by registry 2013-03-26 +// cw : https://www.uoc.cw/cw-registry +// Confirmed by registry 2024-11-19 cw com.cw edu.cw net.cw org.cw -// cx : https://en.wikipedia.org/wiki/.cx +// cx : https://www.iana.org/domains/root/db/cx.html // list of other 2nd level tlds ? cx gov.cx // cy : http://www.nic.cy/ -// Submitted by registry Panayiotou Fotia -// namespace policies URL https://www.nic.cy/portal//sites/default/files/symfonia_gia_eggrafi.pdf +// Submitted by Panayiotou Fotia +// https://nic.cy/wp-content/uploads/2024/01/Create-Request-for-domain-name-registration-1.pdf cy ac.cy biz.cy @@ -907,30 +942,35 @@ press.cy pro.cy tm.cy -// cz : https://en.wikipedia.org/wiki/.cz +// cz : https://www.iana.org/domains/root/db/cz.html +// Confirmed by registry 2025-08-06 cz +gov.cz -// de : https://en.wikipedia.org/wiki/.de +// de : https://www.iana.org/domains/root/db/de.html // Confirmed by registry (with technical // reservations) 2008-07-01 de -// dj : https://en.wikipedia.org/wiki/.dj +// dj : https://www.iana.org/domains/root/db/dj.html dj -// dk : https://en.wikipedia.org/wiki/.dk +// dk : https://www.iana.org/domains/root/db/dk.html // Confirmed by registry 2008-06-17 dk -// dm : https://en.wikipedia.org/wiki/.dm +// dm : https://www.iana.org/domains/root/db/dm.html +// https://nic.dm/policies/pdf/DMRulesandGuidelines2024v1.pdf +// Confirmed by registry 2024-11-19 dm +co.dm com.dm -net.dm -org.dm edu.dm gov.dm +net.dm +org.dm -// do : https://en.wikipedia.org/wiki/.do +// do : https://www.iana.org/domains/root/db/do.html do art.do com.do @@ -950,79 +990,124 @@ asso.dz com.dz edu.dz gov.dz -org.dz net.dz +org.dz pol.dz soc.dz tm.dz -// ec : http://www.nic.ec/reg/paso1.asp -// Submitted by registry +// ec : https://www.nic.ec/ +// Submitted by registry ec +abg.ec +adm.ec +agron.ec +arqt.ec +art.ec +bar.ec +chef.ec com.ec -info.ec -net.ec +cont.ec +cpa.ec +cue.ec +dent.ec +dgn.ec +disco.ec +doc.ec +edu.ec +eng.ec +esm.ec fin.ec +fot.ec +gal.ec +gob.ec +gov.ec +gye.ec +ibr.ec +info.ec k12.ec +lat.ec +loj.ec med.ec -pro.ec -org.ec -edu.ec -gov.ec -gob.ec mil.ec - -// edu : https://en.wikipedia.org/wiki/.edu +mktg.ec +mon.ec +net.ec +ntr.ec +odont.ec +org.ec +pro.ec +prof.ec +psic.ec +psiq.ec +pub.ec +rio.ec +rrpp.ec +sal.ec +tech.ec +tul.ec +tur.ec +uio.ec +vet.ec +xxx.ec + +// edu : https://www.iana.org/domains/root/db/edu.html edu -// ee : http://www.eenet.ee/EENet/dom_reeglid.html#lisa_B +// ee : https://www.internet.ee/domains/general-domains-and-procedure-for-registration-of-sub-domains-under-general-domains ee +aip.ee +com.ee edu.ee +fie.ee gov.ee -riik.ee lib.ee med.ee -com.ee -pri.ee -aip.ee org.ee -fie.ee +pri.ee +riik.ee -// eg : https://en.wikipedia.org/wiki/.eg +// eg : https://www.iana.org/domains/root/db/eg.html +// https://domain.eg/en/domain-rules/subdomain-names-types/ eg +ac.eg com.eg edu.eg eun.eg gov.eg +info.eg +me.eg mil.eg name.eg net.eg org.eg sci.eg +sport.eg +tv.eg -// er : https://en.wikipedia.org/wiki/.er +// er : https://www.iana.org/domains/root/db/er.html *.er -// es : https://www.nic.es/site_ingles/ingles/dominios/index.html +// es : https://www.dominios.es/en es com.es +edu.es +gob.es nom.es org.es -gob.es -edu.es -// et : https://en.wikipedia.org/wiki/.et +// et : https://www.iana.org/domains/root/db/et.html et +biz.et com.et -gov.et -org.et edu.et -biz.et -name.et +gov.et info.et +name.et net.et +org.et -// eu : https://en.wikipedia.org/wiki/.eu +// eu : https://www.iana.org/domains/root/db/eu.html eu // fi : https://www.iana.org/domains/root/db/fi.html @@ -1033,13 +1118,14 @@ fi // completely removed. aland.fi -// fj : http://domains.fj/ -// Submitted by registry 2020-02-11 +// fj : https://www.iana.org/domains/root/db/fj.html fj ac.fj biz.fj com.fj +edu.fj gov.fj +id.fj info.fj mil.fj name.fj @@ -1047,17 +1133,17 @@ net.fj org.fj pro.fj -// fk : https://en.wikipedia.org/wiki/.fk +// fk : https://www.iana.org/domains/root/db/fk.html *.fk -// fm : https://en.wikipedia.org/wiki/.fm +// fm : https://www.iana.org/domains/root/db/fm.html +fm com.fm edu.fm net.fm org.fm -fm -// fo : https://en.wikipedia.org/wiki/.fo +// fo : https://www.iana.org/domains/root/db/fo.html fo // fr : https://www.afnic.fr/ https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf @@ -1074,59 +1160,62 @@ cci.fr greta.fr huissier-justice.fr -// ga : https://en.wikipedia.org/wiki/.ga +// ga : https://www.iana.org/domains/root/db/ga.html ga // gb : This registry is effectively dormant // Submitted by registry gb -// gd : https://en.wikipedia.org/wiki/.gd +// gd : https://www.iana.org/domains/root/db/gd.html +gd edu.gd gov.gd -gd -// ge : http://www.nic.net.ge/policy_en.pdf +// ge : https://nic.ge/en/administrator/the-ge-domain-regulations +// Confirmed by registry 2024-11-20 ge com.ge edu.ge gov.ge -org.ge -mil.ge net.ge +org.ge pvt.ge +school.ge -// gf : https://en.wikipedia.org/wiki/.gf +// gf : https://www.iana.org/domains/root/db/gf.html gf -// gg : http://www.channelisles.net/register-domains/ +// gg : https://www.channelisles.net/register-1/register-direct // Confirmed by registry 2013-11-28 gg co.gg net.gg org.gg -// gh : https://en.wikipedia.org/wiki/.gh -// see also: http://www.nic.gh/reg_now.php +// gh : https://www.iana.org/domains/root/db/gh.html +// https://www.nic.gh/ // Although domains directly at second level are not possible at the moment, // they have been possible for some time and may come back. gh +biz.gh com.gh edu.gh gov.gh -org.gh mil.gh +net.gh +org.gh // gi : http://www.nic.gi/rules.html gi com.gi -ltd.gi +edu.gi gov.gi +ltd.gi mod.gi -edu.gi org.gi -// gl : https://en.wikipedia.org/wiki/.gl +// gl : https://www.iana.org/domains/root/db/gl.html // http://nic.gl gl co.gl @@ -1145,34 +1234,34 @@ ac.gn com.gn edu.gn gov.gn -org.gn net.gn +org.gn -// gov : https://en.wikipedia.org/wiki/.gov +// gov : https://www.iana.org/domains/root/db/gov.html gov // gp : http://www.nic.gp/index.php?lang=en gp +asso.gp com.gp -net.gp -mobi.gp edu.gp +mobi.gp +net.gp org.gp -asso.gp -// gq : https://en.wikipedia.org/wiki/.gq +// gq : https://www.iana.org/domains/root/db/gq.html gq -// gr : https://grweb.ics.forth.gr/english/1617-B-2005.html +// gr : https://www.iana.org/domains/root/db/gr.html // Submitted by registry gr com.gr edu.gr +gov.gr net.gr org.gr -gov.gr -// gs : https://en.wikipedia.org/wiki/.gs +// gs : https://www.iana.org/domains/root/db/gs.html gs // gt : https://www.gt/sitio/registration_policy.php?lang=en @@ -1198,11 +1287,11 @@ net.gu org.gu web.gu -// gw : https://en.wikipedia.org/wiki/.gw +// gw : https://www.iana.org/domains/root/db/gw.html // gw : https://nic.gw/regras/ gw -// gy : https://en.wikipedia.org/wiki/.gy +// gy : https://www.iana.org/domains/root/db/gy.html // http://registry.gy/ gy co.gy @@ -1221,103 +1310,104 @@ gov.hk idv.hk net.hk org.hk +个人.hk +個人.hk 公司.hk -教育.hk -敎育.hk 政府.hk -個人.hk -个人.hk +敎育.hk +教育.hk 箇人.hk +組織.hk +組织.hk +網絡.hk 網络.hk -网络.hk 组織.hk -網絡.hk -网絡.hk 组织.hk -組織.hk -組织.hk +网絡.hk +网络.hk -// hm : https://en.wikipedia.org/wiki/.hm +// hm : https://www.iana.org/domains/root/db/hm.html hm -// hn : http://www.nic.hn/politicas/ps02,,05.html +// hn : https://www.iana.org/domains/root/db/hn.html hn com.hn edu.hn -org.hn -net.hn -mil.hn gob.hn +mil.hn +net.hn +org.hn // hr : http://www.dns.hr/documents/pdf/HRTLD-regulations.pdf hr -iz.hr +com.hr from.hr +iz.hr name.hr -com.hr // ht : http://www.nic.ht/info/charte.cfm ht +adult.ht +art.ht +asso.ht com.ht -shop.ht +coop.ht +edu.ht firm.ht +gouv.ht info.ht -adult.ht +med.ht net.ht -pro.ht org.ht -med.ht -art.ht -coop.ht +perso.ht pol.ht -asso.ht -edu.ht +pro.ht rel.ht -gouv.ht -perso.ht +shop.ht -// hu : http://www.domain.hu/domain/English/sld.html +// hu : https://www.iana.org/domains/root/db/hu.html // Confirmed by registry 2008-06-12 hu -co.hu -info.hu -org.hu -priv.hu -sport.hu -tm.hu 2000.hu agrar.hu bolt.hu casino.hu city.hu +co.hu erotica.hu erotika.hu film.hu forum.hu games.hu hotel.hu +info.hu ingatlan.hu jogasz.hu konyvelo.hu lakas.hu media.hu news.hu +org.hu +priv.hu reklam.hu sex.hu shop.hu +sport.hu suli.hu szex.hu +tm.hu tozsde.hu utazas.hu video.hu -// id : https://pandi.id/en/domain/registration-requirements/ +// id : https://www.iana.org/domains/root/db/id.html id ac.id biz.id co.id desa.id go.id +kop.id mil.id my.id net.id @@ -1325,14 +1415,16 @@ or.id ponpes.id sch.id web.id +// xn--9tfky.id (.id, Und-Bali) +ᬩᬮᬶ.id -// ie : https://en.wikipedia.org/wiki/.ie +// ie : https://www.iana.org/domains/root/db/ie.html ie gov.ie -// il : http://www.isoc.org.il/domains/ -// see also: https://en.isoc.org.il/il-cctld/registration-rules -// ISOC-IL (operated by .il Registry) +// il : http://www.isoc.org.il/domains/ +// see also: https://en.isoc.org.il/il-cctld/registration-rules +// ISOC-IL (operated by .il Registry) il ac.il co.il @@ -1358,24 +1450,26 @@ org.il im ac.im co.im -com.im ltd.co.im +plc.co.im +com.im net.im org.im -plc.co.im tt.im tv.im -// in : https://en.wikipedia.org/wiki/.in +// in : https://www.iana.org/domains/root/db/in.html // see also: https://registry.in/policies // Please note, that nic.in is not an official eTLD, but used by most // government institutions. +// Confirmed by Gaurav Kansal 2025-11-06 in 5g.in 6g.in ac.in ai.in am.in +bank.in bihar.in biz.in business.in @@ -1389,6 +1483,7 @@ delhi.in dr.in edu.in er.in +fin.in firm.in gen.in gov.in @@ -1413,27 +1508,33 @@ uk.in up.in us.in -// info : https://en.wikipedia.org/wiki/.info +// info : https://www.iana.org/domains/root/db/info.html info -// int : https://en.wikipedia.org/wiki/.int +// int : https://www.iana.org/domains/root/db/int.html // Confirmed by registry 2008-06-18 int eu.int // io : http://www.nic.io/rules.htm -// list of other 2nd level tlds ? io +co.io com.io +edu.io +gov.io +mil.io +net.io +nom.io +org.io // iq : http://www.cmc.iq/english/iq/iqregister1.htm iq -gov.iq +com.iq edu.iq +gov.iq mil.iq -com.iq -org.iq net.iq +org.iq // ir : http://www.nic.ir/Terms_and_Conditions_ir,_Appendix_1_Domain_Rules // Also see http://www.nic.ir/Internationalized_Domain_Names @@ -1452,22 +1553,16 @@ sch.ir ايران.ir // is : http://www.isnic.is/domain/rules.php -// Confirmed by registry 2008-12-06 +// Confirmed by registry 2024-11-17 is -net.is -com.is -edu.is -gov.is -org.is -int.is - -// it : https://en.wikipedia.org/wiki/.it + +// it : https://www.iana.org/domains/root/db/it.html +// https://www.nic.it/ it -gov.it edu.it -// Reserved geo-names (regions and provinces): -// https://www.nic.it/sites/default/files/archivio/docs/Regulation_assignation_v7.1.pdf -// Regions +gov.it +// Regions (3.3.1) +// https://www.nic.it/en/manage-your-it/forms-and-docs -> "Assignment and Management of domain names" abr.it abruzzo.it aosta-valley.it @@ -1526,6 +1621,7 @@ trentin-sudtirol.it trentin-südtirol.it trentin-sued-tirol.it trentin-suedtirol.it +trentino.it trentino-a-adige.it trentino-aadige.it trentino-alto-adige.it @@ -1538,7 +1634,6 @@ trentino-sudtirol.it trentino-südtirol.it trentino-sued-tirol.it trentino-suedtirol.it -trentino.it trentinoa-adige.it trentinoaadige.it trentinoalto-adige.it @@ -1582,7 +1677,7 @@ vao.it vda.it ven.it veneto.it -// Provinces +// Provinces (3.3.2) ag.it agrigento.it al.it @@ -1610,10 +1705,10 @@ at.it av.it avellino.it ba.it +balsan.it balsan-sudtirol.it balsan-südtirol.it balsan-suedtirol.it -balsan.it bari.it barletta-trani-andria.it barlettatraniandria.it @@ -1627,21 +1722,21 @@ bl.it bn.it bo.it bologna.it -bolzano-altoadige.it bolzano.it +bolzano-altoadige.it +bozen.it bozen-sudtirol.it bozen-südtirol.it bozen-suedtirol.it -bozen.it br.it brescia.it brindisi.it bs.it bt.it +bulsan.it bulsan-sudtirol.it bulsan-südtirol.it bulsan-suedtirol.it -bulsan.it bz.it ca.it cagliari.it @@ -1743,9 +1838,9 @@ milano.it mn.it mo.it modena.it +monza.it monza-brianza.it monza-e-della-brianza.it -monza.it monzabrianza.it monzaebrianza.it monzaedellabrianza.it @@ -1824,8 +1919,8 @@ sondrio.it sp.it sr.it ss.it -suedtirol.it südtirol.it +suedtirol.it sv.it ta.it taranto.it @@ -1874,7 +1969,7 @@ vs.it vt.it vv.it -// je : http://www.channelisles.net/register-domains/ +// je : https://www.iana.org/domains/root/db/je.html // Confirmed by registry 2013-11-28 je co.je @@ -1884,23 +1979,30 @@ org.je // jm : http://www.com.jm/register.html *.jm -// jo : http://www.dns.jo/Registration_policy.aspx +// jo : https://www.dns.jo/JoFamily.aspx +// Confirmed by registry 2024-11-17 jo +agri.jo +ai.jo com.jo -org.jo -net.jo edu.jo -sch.jo +eng.jo +fm.jo gov.jo mil.jo -name.jo +net.jo +org.jo +per.jo +phd.jo +sch.jo +tv.jo -// jobs : https://en.wikipedia.org/wiki/.jobs +// jobs : https://www.iana.org/domains/root/db/jobs.html jobs -// jp : https://en.wikipedia.org/wiki/.jp +// jp : https://www.iana.org/domains/root/db/jp.html // http://jprs.co.jp/en/jpdomain.html -// Submitted by registry +// Confirmed by registry 2024-11-22 jp // jp organizational type names ac.jp @@ -1960,26 +2062,14 @@ wakayama.jp yamagata.jp yamaguchi.jp yamanashi.jp -栃木.jp -愛知.jp -愛媛.jp +三重.jp +京都.jp +佐賀.jp 兵庫.jp -熊本.jp -茨城.jp 北海道.jp 千葉.jp 和歌山.jp -長崎.jp -長野.jp -新潟.jp -青森.jp -静岡.jp -東京.jp -石川.jp 埼玉.jp -三重.jp -京都.jp -佐賀.jp 大分.jp 大阪.jp 奈良.jp @@ -1989,26 +2079,41 @@ yamanashi.jp 山口.jp 山形.jp 山梨.jp -岩手.jp 岐阜.jp 岡山.jp +岩手.jp 島根.jp 広島.jp 徳島.jp +愛媛.jp +愛知.jp +新潟.jp +東京.jp +栃木.jp 沖縄.jp 滋賀.jp +熊本.jp +石川.jp 神奈川.jp 福井.jp 福岡.jp 福島.jp 秋田.jp 群馬.jp +茨城.jp +長崎.jp +長野.jp +青森.jp +静岡.jp 香川.jp 高知.jp 鳥取.jp 鹿児島.jp // jp geographic type names // http://jprs.jp/doc/rule/saisoku-1.html +// 2024-11-22: JPRS confirmed that jp geographic type names no longer accept new registrations. +// Once all existing registrations expire (marking full discontinuation), these suffixes +// will be removed from the PSL. *.kawasaki.jp !city.kawasaki.jp *.kitakyushu.jp @@ -3712,56 +3817,62 @@ sc.ke // kg : http://www.domain.kg/dmn_n.html kg -org.kg -net.kg com.kg edu.kg gov.kg mil.kg +net.kg +org.kg -// kh : http://www.mptc.gov.kh/dns_registration.htm -*.kh +// kh : https://trc.gov.kh +// Submitted by khnic@trc.gov.kh +kh +com.kh +edu.kh +gov.kh +net.kh +org.kh -// ki : http://www.ki/dns/index.html +// ki : https://www.iana.org/domains/root/db/ki.html ki -edu.ki biz.ki -net.ki -org.ki +com.ki +edu.ki gov.ki info.ki -com.ki +net.ki +org.ki -// km : https://en.wikipedia.org/wiki/.km +// km : https://www.iana.org/domains/root/db/km.html // http://www.domaine.km/documents/charte.doc km -org.km -nom.km +ass.km +com.km +edu.km gov.km +mil.km +nom.km +org.km prd.km tm.km -edu.km -mil.km -ass.km -com.km // These are only mentioned as proposed suggestions at domaine.km, but -// https://en.wikipedia.org/wiki/.km says they're available for registration: -coop.km +// https://www.iana.org/domains/root/db/km.html says they're available for registration: asso.km -presse.km +coop.km +gouv.km medecin.km notaires.km pharmaciens.km +presse.km veterinaire.km -gouv.km -// kn : https://en.wikipedia.org/wiki/.kn +// kn : https://www.iana.org/domains/root/db/kn.html // http://www.dot.kn/domainRules.html kn -net.kn -org.kn edu.kn gov.kn +net.kn +org.kn // kp : http://www.kcce.kp/en_index.php kp @@ -3772,15 +3883,19 @@ org.kp rep.kp tra.kp -// kr : https://en.wikipedia.org/wiki/.kr -// see also: http://domain.nida.or.kr/eng/registration.jsp +// kr : https://www.iana.org/domains/root/db/kr.html +// see also: https://krnic.kisa.or.kr/jsp/infoboard/law/domBylawsReg.jsp kr ac.kr +ai.kr co.kr es.kr go.kr hs.kr +io.kr +it.kr kg.kr +me.kr mil.kr ms.kr ne.kr @@ -3825,29 +3940,29 @@ edu.ky net.ky org.ky -// kz : https://en.wikipedia.org/wiki/.kz +// kz : https://www.iana.org/domains/root/db/kz.html // see also: http://www.nic.kz/rules/index.jsp kz -org.kz +com.kz edu.kz -net.kz gov.kz mil.kz -com.kz +net.kz +org.kz -// la : https://en.wikipedia.org/wiki/.la +// la : https://www.iana.org/domains/root/db/la.html // Submitted by registry la -int.la -net.la -info.la +com.la edu.la gov.la -per.la -com.la +info.la +int.la +net.la org.la +per.la -// lb : https://en.wikipedia.org/wiki/.lb +// lb : https://www.iana.org/domains/root/db/lb.html // Submitted by registry lb com.lb @@ -3856,36 +3971,36 @@ gov.lb net.lb org.lb -// lc : https://en.wikipedia.org/wiki/.lc +// lc : https://www.iana.org/domains/root/db/lc.html // see also: http://www.nic.lc/rules.htm lc -com.lc -net.lc co.lc -org.lc +com.lc edu.lc gov.lc +net.lc +org.lc -// li : https://en.wikipedia.org/wiki/.li +// li : https://www.iana.org/domains/root/db/li.html li -// lk : https://www.nic.lk/index.php/domain-registration/lk-domain-naming-structure +// lk : https://www.iana.org/domains/root/db/lk.html lk -gov.lk -sch.lk -net.lk -int.lk +ac.lk +assn.lk com.lk -org.lk edu.lk +gov.lk +grp.lk +hotel.lk +int.lk +ltd.lk +net.lk ngo.lk +org.lk +sch.lk soc.lk web.lk -ltd.lk -assn.lk -grp.lk -hotel.lk -ac.lk // lr : http://psg.com/dns/lr/lr.txt // Submitted by registry @@ -3893,8 +4008,8 @@ lr com.lr edu.lr gov.lr -org.lr net.lr +org.lr // ls : http://www.nic.ls/ // Confirmed by registry @@ -3909,7 +4024,7 @@ net.ls org.ls sc.ls -// lt : https://en.wikipedia.org/wiki/.lt +// lt : https://www.iana.org/domains/root/db/lt.html lt // gov.lt : http://www.gov.lt/index_en.php gov.lt @@ -3917,131 +4032,136 @@ gov.lt // lu : http://www.dns.lu/en/ lu -// lv : http://www.nic.lv/DNS/En/generic.php +// lv : https://www.iana.org/domains/root/db/lv.html lv +asn.lv com.lv +conf.lv edu.lv gov.lv -org.lv -mil.lv id.lv +mil.lv net.lv -asn.lv -conf.lv +org.lv // ly : http://www.nic.ly/regulations.php ly com.ly -net.ly -gov.ly -plc.ly edu.ly -sch.ly +gov.ly +id.ly med.ly +net.ly org.ly -id.ly +plc.ly +sch.ly -// ma : https://en.wikipedia.org/wiki/.ma +// ma : https://www.iana.org/domains/root/db/ma.html // http://www.anrt.ma/fr/admin/download/upload/file_fr782.pdf ma +ac.ma co.ma -net.ma gov.ma +net.ma org.ma -ac.ma press.ma // mc : http://www.nic.mc/ mc -tm.mc asso.mc +tm.mc -// md : https://en.wikipedia.org/wiki/.md +// md : https://www.iana.org/domains/root/db/md.html md -// me : https://en.wikipedia.org/wiki/.me +// me : https://www.iana.org/domains/root/db/me.html me +ac.me co.me -net.me -org.me edu.me -ac.me gov.me its.me +net.me +org.me priv.me -// mg : http://nic.mg/nicmg/?page_id=39 +// mg : https://nic.mg mg -org.mg -nom.mg -gov.mg -prd.mg -tm.mg +co.mg +com.mg edu.mg +gov.mg mil.mg -com.mg -co.mg +nom.mg +org.mg +prd.mg -// mh : https://en.wikipedia.org/wiki/.mh +// mh : https://www.iana.org/domains/root/db/mh.html mh -// mil : https://en.wikipedia.org/wiki/.mil +// mil : https://www.iana.org/domains/root/db/mil.html mil -// mk : https://en.wikipedia.org/wiki/.mk +// mk : https://www.iana.org/domains/root/db/mk.html // see also: http://dns.marnet.net.mk/postapka.php mk com.mk -org.mk -net.mk edu.mk gov.mk inf.mk name.mk +net.mk +org.mk -// ml : http://www.gobin.info/domainname/ml-template.doc -// see also: https://en.wikipedia.org/wiki/.ml +// ml : https://www.iana.org/domains/root/db/ml.html +// Confirmed by Boubacar NDIAYE 2024-12-31 ml +ac.ml +art.ml +asso.ml com.ml edu.ml gouv.ml gov.ml +info.ml +inst.ml net.ml org.ml +pr.ml presse.ml -// mm : https://en.wikipedia.org/wiki/.mm +// mm : https://www.iana.org/domains/root/db/mm.html *.mm -// mn : https://en.wikipedia.org/wiki/.mn +// mn : https://www.iana.org/domains/root/db/mn.html mn -gov.mn edu.mn +gov.mn org.mn // mo : http://www.monic.net.mo/ mo com.mo -net.mo -org.mo edu.mo gov.mo +net.mo +org.mo -// mobi : https://en.wikipedia.org/wiki/.mobi +// mobi : https://www.iana.org/domains/root/db/mobi.html mobi // mp : http://www.dot.mp/ // Confirmed by registry 2008-06-17 mp -// mq : https://en.wikipedia.org/wiki/.mq +// mq : https://www.iana.org/domains/root/db/mq.html mq -// mr : https://en.wikipedia.org/wiki/.mr +// mr : https://www.iana.org/domains/root/db/mr.html mr gov.mr -// ms : http://www.nic.ms/pdf/MS_Domain_Name_Rules.pdf +// ms : https://www.iana.org/domains/root/db/ms.html ms com.ms edu.ms @@ -4057,20 +4177,20 @@ edu.mt net.mt org.mt -// mu : https://en.wikipedia.org/wiki/.mu +// mu : https://www.iana.org/domains/root/db/mu.html mu -com.mu -net.mu -org.mu -gov.mu ac.mu co.mu +com.mu +gov.mu +net.mu or.mu +org.mu // museum : https://welcome.museum/wp-content/uploads/2018/05/20180525-Registration-Policy-MUSEUM-EN_VF-2.pdf https://welcome.museum/buy-your-dot-museum-2/ museum -// mv : https://en.wikipedia.org/wiki/.mv +// mv : https://www.iana.org/domains/root/db/mv.html // "mv" included because, contra Wikipedia, google.mv exists. mv aero.mv @@ -4098,7 +4218,6 @@ coop.mw edu.mw gov.mw int.mw -museum.mw net.mw org.mw @@ -4106,10 +4225,10 @@ org.mw // Submitted by registry mx com.mx -org.mx -gob.mx edu.mx +gob.mx net.mx +org.mx // my : http://www.mynic.my/ // Available strings: https://mynic.my/resources/domains/buying-a-domain/ @@ -4136,27 +4255,16 @@ net.mz org.mz // na : http://www.na-nic.com.na/ -// http://www.info.na/domain/ na -info.na -pro.na -name.na -school.na -or.na -dr.na -us.na -mx.na -ca.na -in.na -cc.na -tv.na -ws.na -mobi.na +alt.na co.na com.na +gov.na +net.na org.na -// name : has 2nd-level tlds, but there's no list of them +// name : http://www.nic.name/ +// Regarding 2LDs: https://github.com/publicsuffix/list/issues/2306 name // nc : http://www.cctld.nc/ @@ -4164,24 +4272,24 @@ nc asso.nc nom.nc -// ne : https://en.wikipedia.org/wiki/.ne +// ne : https://www.iana.org/domains/root/db/ne.html ne -// net : https://en.wikipedia.org/wiki/.net +// net : https://www.iana.org/domains/root/db/net.html net -// nf : https://en.wikipedia.org/wiki/.nf +// nf : https://www.iana.org/domains/root/db/nf.html nf -com.nf -net.nf -per.nf -rec.nf -web.nf arts.nf +com.nf firm.nf info.nf +net.nf other.nf +per.nf +rec.nf store.nf +web.nf // ng : http://www.nira.org.ng/index.php/join-us/register-ng-domain/189-nira-slds ng @@ -4213,9 +4321,8 @@ nom.ni org.ni web.ni -// nl : https://en.wikipedia.org/wiki/.nl -// https://www.sidn.nl/ -// ccTLD for the Netherlands +// nl : https://www.iana.org/domains/root/db/nl.html +// https://www.sidn.nl/ nl // no : https://www.norid.no/en/om-domenenavn/regelverk-for-no/ @@ -4226,18 +4333,18 @@ nl no // Norid category second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/ fhs.no -vgs.no -fylkesbibl.no folkebibl.no -museum.no +fylkesbibl.no idrett.no +museum.no priv.no +vgs.no // Norid category second-level domains managed by parties other than Norid : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/ -mil.no -stat.no dep.no -kommune.no herad.no +kommune.no +mil.no +stat.no // Norid geographical second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/ // counties aa.no @@ -4289,10 +4396,10 @@ akrehamn.no algard.no ålgård.no arna.no -brumunddal.no -bryne.no bronnoysund.no brønnøysund.no +brumunddal.no +bryne.no drobak.no drøbak.no egersund.no @@ -4336,27 +4443,32 @@ tananger.no tranby.no vossevangen.no // communities +aarborte.no +aejrie.no afjord.no åfjord.no agdenes.no +nes.akershus.no +aknoluokta.no +ákŋoluokta.no al.no ål.no +alaheadju.no +álaheadju.no alesund.no ålesund.no alstahaug.no alta.no áltá.no -alaheadju.no -álaheadju.no alvdal.no amli.no åmli.no amot.no åmot.no +andasuolo.no andebu.no andoy.no andøy.no -andasuolo.no ardal.no årdal.no aremark.no @@ -4366,9 +4478,9 @@ aseral.no åseral.no asker.no askim.no -askvoll.no askoy.no askøy.no +askvoll.no asnes.no åsnes.no audnedaln.no @@ -4381,65 +4493,69 @@ austevoll.no austrheim.no averoy.no averøy.no -balestrand.no -ballangen.no +badaddja.no +bådåddjå.no +bærum.no +bahcavuotna.no +báhcavuotna.no +bahccavuotna.no +báhccavuotna.no +baidar.no +báidár.no +bajddar.no +bájddar.no balat.no bálát.no +balestrand.no +ballangen.no balsfjord.no -bahccavuotna.no -báhccavuotna.no bamble.no bardu.no -beardu.no -beiarn.no -bajddar.no -bájddar.no -baidar.no -báidár.no +barum.no +batsfjord.no +båtsfjord.no +bearalvahki.no +bearalváhki.no +beardu.no +beiarn.no berg.no bergen.no berlevag.no berlevåg.no -bearalvahki.no -bearalváhki.no +bievat.no +bievát.no bindal.no birkenes.no -bjarkoy.no -bjarkøy.no bjerkreim.no bjugn.no bodo.no bodø.no -badaddja.no -bådåddjå.no -budejju.no bokn.no +bomlo.no +bømlo.no bremanger.no bronnoy.no brønnøy.no +budejju.no +nes.buskerud.no bygland.no bykle.no -barum.no -bærum.no -bo.telemark.no -bø.telemark.no -bo.nordland.no -bø.nordland.no -bievat.no -bievát.no -bomlo.no -bømlo.no -batsfjord.no -båtsfjord.no -bahcavuotna.no -báhcavuotna.no +cahcesuolo.no +čáhcesuolo.no +davvenjarga.no +davvenjárga.no +davvesiida.no +deatnu.no +dielddanuorri.no +divtasvuodna.no +divttasvuotna.no +donna.no +dønna.no dovre.no drammen.no drangedal.no dyroy.no dyrøy.no -donna.no -dønna.no eid.no eidfjord.no eidsberg.no @@ -4451,14 +4567,12 @@ enebakk.no engerdal.no etne.no etnedal.no -evenes.no evenassi.no evenášši.no +evenes.no evje-og-hornnes.no farsund.no fauske.no -fuossko.no -fuoisku.no fedje.no fet.no finnoy.no @@ -4466,33 +4580,40 @@ finnøy.no fitjar.no fjaler.no fjell.no +fla.no +flå.no flakstad.no flatanger.no flekkefjord.no flesberg.no flora.no -fla.no -flå.no folldal.no +forde.no +førde.no forsand.no fosnes.no +fræna.no +frana.no frei.no frogn.no froland.no frosta.no -frana.no -fræna.no froya.no frøya.no +fuoisku.no +fuossko.no fusa.no fyresdal.no -forde.no -førde.no +gaivuotna.no +gáivuotna.no +galsa.no +gálsá.no gamvik.no gangaviika.no gáŋgaviika.no gaular.no gausdal.no +giehtavuoatna.no gildeskal.no gildeskål.no giske.no @@ -4510,38 +4631,37 @@ granvin.no gratangen.no grimstad.no grong.no -kraanghke.no -kråanghke.no grue.no gulen.no +guovdageaidnu.no +ha.no +hå.no +habmer.no +hábmer.no hadsel.no +hægebostad.no +hagebostad.no halden.no halsa.no hamar.no hamaroy.no -habmer.no -hábmer.no -hapmir.no -hápmir.no -hammerfest.no hammarfeasta.no hámmárfeasta.no +hammerfest.no +hapmir.no +hápmir.no haram.no hareid.no harstad.no hasvik.no -aknoluokta.no -ákŋoluokta.no hattfjelldal.no -aarborte.no haugesund.no +os.hedmark.no +valer.hedmark.no +våler.hedmark.no hemne.no hemnes.no hemsedal.no -heroy.more-og-romsdal.no -herøy.møre-og-romsdal.no -heroy.nordland.no -herøy.nordland.no hitra.no hjartdal.no hjelmeland.no @@ -4553,96 +4673,95 @@ hole.no holmestrand.no holtalen.no holtålen.no +os.hordaland.no hornindal.no horten.no -hurdal.no -hurum.no -hvaler.no -hyllestad.no -hagebostad.no -hægebostad.no hoyanger.no høyanger.no hoylandet.no høylandet.no -ha.no -hå.no +hurdal.no +hurum.no +hvaler.no +hyllestad.no ibestad.no inderoy.no inderøy.no iveland.no +ivgu.no jevnaker.no -jondal.no jolster.no jølster.no -karasjok.no +jondal.no +kafjord.no +kåfjord.no karasjohka.no kárášjohka.no +karasjok.no karlsoy.no -galsa.no -gálsá.no karmoy.no karmøy.no kautokeino.no -guovdageaidnu.no -klepp.no klabu.no klæbu.no +klepp.no kongsberg.no kongsvinger.no +kraanghke.no +kråanghke.no kragero.no kragerø.no kristiansand.no kristiansund.no krodsherad.no krødsherad.no +kvæfjord.no +kvænangen.no +kvafjord.no kvalsund.no -rahkkeravju.no -ráhkkerávju.no kvam.no +kvanangen.no kvinesdal.no kvinnherad.no kviteseid.no kvitsoy.no kvitsøy.no -kvafjord.no -kvæfjord.no -giehtavuoatna.no -kvanangen.no -kvænangen.no -navuotna.no -návuotna.no -kafjord.no -kåfjord.no -gaivuotna.no -gáivuotna.no +laakesvuemie.no +lærdal.no +lahppi.no +láhppi.no +lardal.no larvik.no -lavangen.no lavagis.no -loabat.no -loabát.no +lavangen.no +leangaviika.no +leaŋgaviika.no lebesby.no -davvesiida.no leikanger.no leirfjord.no leka.no leksvik.no lenvik.no -leangaviika.no -leaŋgaviika.no +lerdal.no lesja.no levanger.no lier.no lierne.no lillehammer.no lillesand.no -lindesnes.no lindas.no lindås.no +lindesnes.no +loabat.no +loabát.no +lodingen.no +lødingen.no lom.no loppa.no -lahppi.no -láhppi.no +lorenskog.no +lørenskog.no +loten.no +løten.no lund.no lunner.no luroy.no @@ -4650,25 +4769,19 @@ lurøy.no luster.no lyngdal.no lyngen.no -ivgu.no -lardal.no -lerdal.no -lærdal.no -lodingen.no -lødingen.no -lorenskog.no -lørenskog.no -loten.no -løten.no +malatvuopmi.no +málatvuopmi.no +malselv.no +målselv.no malvik.no -masoy.no -måsøy.no -muosat.no -muosát.no mandal.no marker.no marnardal.no masfjorden.no +masoy.no +måsøy.no +matta-varjjat.no +mátta-várjjat.no meland.no meldal.no melhus.no @@ -4676,39 +4789,38 @@ meloy.no meløy.no meraker.no meråker.no -moareke.no -moåreke.no midsund.no midtre-gauldal.no +moareke.no +moåreke.no modalen.no modum.no molde.no +heroy.more-og-romsdal.no +sande.more-og-romsdal.no +herøy.møre-og-romsdal.no +sande.møre-og-romsdal.no moskenes.no moss.no -mosvik.no -malselv.no -målselv.no -malatvuopmi.no -málatvuopmi.no +muosat.no +muosát.no +naamesjevuemie.no +nååmesjevuemie.no +nærøy.no namdalseid.no -aejrie.no namsos.no namsskogan.no -naamesjevuemie.no -nååmesjevuemie.no -laakesvuemie.no nannestad.no -narvik.no +naroy.no narviika.no +narvik.no naustdal.no +navuotna.no +návuotna.no nedre-eiker.no -nes.akershus.no -nes.buskerud.no nesna.no nesodden.no nesseby.no -unjarga.no -unjárga.no nesset.no nissedal.no nittedal.no @@ -4717,21 +4829,20 @@ nord-fron.no nord-odal.no norddal.no nordkapp.no -davvenjarga.no -davvenjárga.no +bo.nordland.no +bø.nordland.no +heroy.nordland.no +herøy.nordland.no nordre-land.no nordreisa.no -raisa.no -ráisa.no nore-og-uvdal.no notodden.no -naroy.no -nærøy.no notteroy.no nøtterøy.no odda.no oksnes.no øksnes.no +omasvuotna.no oppdal.no oppegard.no oppegård.no @@ -4742,11 +4853,11 @@ orskog.no ørskog.no orsta.no ørsta.no -os.hedmark.no -os.hordaland.no osen.no osteroy.no osterøy.no +valer.ostfold.no +våler.østfold.no ostre-toten.no østre-toten.no overhalla.no @@ -4762,11 +4873,18 @@ porsanger.no porsangu.no porsáŋgu.no porsgrunn.no +rade.no +råde.no radoy.no radøy.no +rælingen.no +rahkkeravju.no +ráhkkerávju.no +raisa.no +ráisa.no rakkestad.no +ralingen.no rana.no -ruovat.no randaberg.no rauma.no rendalen.no @@ -4777,16 +4895,14 @@ rindal.no ringebu.no ringerike.no ringsaker.no -rissa.no risor.no risør.no +rissa.no roan.no -rollag.no -rygge.no -ralingen.no -rælingen.no rodoy.no rødøy.no +rollag.no +romsa.no romskog.no rømskog.no roros.no @@ -4797,18 +4913,14 @@ royken.no røyken.no royrvik.no røyrvik.no -rade.no -råde.no +ruovat.no +rygge.no salangen.no -siellak.no -saltdal.no salat.no -sálát.no sálat.no +sálát.no +saltdal.no samnanger.no -sande.more-og-romsdal.no -sande.møre-og-romsdal.no -sande.vestfold.no sandefjord.no sandnes.no sandoy.no @@ -4820,39 +4932,60 @@ sel.no selbu.no selje.no seljord.no +siellak.no sigdal.no siljan.no sirdal.no +skanit.no +skánit.no +skanland.no +skånland.no skaun.no skedsmo.no ski.no skien.no -skiptvet.no -skjervoy.no -skjervøy.no skierva.no skiervá.no +skiptvet.no skjak.no skjåk.no +skjervoy.no +skjervøy.no skodje.no -skanland.no -skånland.no -skanit.no -skánit.no smola.no smøla.no -snillfjord.no +snaase.no +snåase.no snasa.no snåsa.no +snillfjord.no snoasa.no -snaase.no -snåase.no sogndal.no +sogne.no +søgne.no sokndal.no sola.no solund.no +somna.no +sømna.no +sondre-land.no +søndre-land.no songdalen.no +sor-aurdal.no +sør-aurdal.no +sor-fron.no +sør-fron.no +sor-odal.no +sør-odal.no +sor-varanger.no +sør-varanger.no +sorfold.no +sørfold.no +sorreisa.no +sørreisa.no sortland.no +sorum.no +sørum.no spydeberg.no stange.no stavanger.no @@ -4865,7 +4998,6 @@ stor-elvdal.no stord.no stordal.no storfjord.no -omasvuotna.no strand.no stranda.no stryn.no @@ -4877,72 +5009,55 @@ surnadal.no sveio.no svelvik.no sykkylven.no -sogne.no -søgne.no -somna.no -sømna.no -sondre-land.no -søndre-land.no -sor-aurdal.no -sør-aurdal.no -sor-fron.no -sør-fron.no -sor-odal.no -sør-odal.no -sor-varanger.no -sør-varanger.no -matta-varjjat.no -mátta-várjjat.no -sorfold.no -sørfold.no -sorreisa.no -sørreisa.no -sorum.no -sørum.no tana.no -deatnu.no +bo.telemark.no +bø.telemark.no time.no tingvoll.no tinn.no tjeldsund.no -dielddanuorri.no tjome.no tjøme.no tokke.no tolga.no +tonsberg.no +tønsberg.no torsken.no +træna.no +trana.no tranoy.no tranøy.no +troandin.no +trogstad.no +trøgstad.no +tromsa.no tromso.no tromsø.no -tromsa.no -romsa.no trondheim.no -troandin.no trysil.no -trana.no -træna.no -trogstad.no -trøgstad.no tvedestrand.no tydal.no tynset.no tysfjord.no -divtasvuodna.no -divttasvuotna.no tysnes.no -tysvar.no tysvær.no -tonsberg.no -tønsberg.no +tysvar.no ullensaker.no ullensvang.no ulvik.no +unjarga.no +unjárga.no utsira.no +vaapste.no vadso.no vadsø.no -cahcesuolo.no -čáhcesuolo.no +værøy.no +vaga.no +vågå.no +vagan.no +vågan.no +vagsoy.no +vågsøy.no vaksdal.no valle.no vang.no @@ -4951,8 +5066,8 @@ vardo.no vardø.no varggat.no várggát.no +varoy.no vefsn.no -vaapste.no vega.no vegarshei.no vegårshei.no @@ -4960,6 +5075,7 @@ vennesla.no verdal.no verran.no vestby.no +sande.vestfold.no vestnes.no vestre-slidre.no vestre-toten.no @@ -4969,21 +5085,9 @@ vevelstad.no vik.no vikna.no vindafjord.no +voagat.no volda.no voss.no -varoy.no -værøy.no -vagan.no -vågan.no -voagat.no -vagsoy.no -vågsøy.no -vaga.no -vågå.no -valer.ostfold.no -våler.østfold.no -valer.hedmark.no -våler.hedmark.no // np : http://www.mos.com.np/register.html *.np @@ -4992,17 +5096,17 @@ våler.hedmark.no // Submitted by registry nr biz.nr -info.nr -gov.nr +com.nr edu.nr -org.nr +gov.nr +info.nr net.nr -com.nr +org.nr -// nu : https://en.wikipedia.org/wiki/.nu +// nu : https://www.iana.org/domains/root/db/nu.html nu -// nz : https://en.wikipedia.org/wiki/.nz +// nz : https://www.iana.org/domains/root/db/nz.html // Submitted by registry nz ac.nz @@ -5015,14 +5119,14 @@ health.nz iwi.nz kiwi.nz maori.nz -mil.nz māori.nz +mil.nz net.nz org.nz parliament.nz school.nz -// om : https://en.wikipedia.org/wiki/.om +// om : https://www.iana.org/domains/root/db/om.html om co.om com.om @@ -5037,60 +5141,58 @@ pro.om // onion : https://tools.ietf.org/html/rfc7686 onion -// org : https://en.wikipedia.org/wiki/.org +// org : https://www.iana.org/domains/root/db/org.html org // pa : http://www.nic.pa/ // Some additional second level "domains" resolve directly as hostnames, such as // pannet.pa, so we add a rule for "pa". pa +abo.pa ac.pa -gob.pa com.pa -org.pa -sld.pa edu.pa -net.pa +gob.pa ing.pa -abo.pa med.pa +net.pa nom.pa +org.pa +sld.pa // pe : https://www.nic.pe/InformeFinalComision.pdf pe +com.pe edu.pe gob.pe -nom.pe mil.pe -org.pe -com.pe net.pe +nom.pe +org.pe // pf : http://www.gobin.info/domainname/formulaire-pf.pdf pf com.pf -org.pf edu.pf +org.pf -// pg : https://en.wikipedia.org/wiki/.pg +// pg : https://www.iana.org/domains/root/db/pg.html *.pg -// ph : http://www.domains.ph/FAQ2.asp +// ph : https://www.iana.org/domains/root/db/ph.html // Submitted by registry ph com.ph -net.ph -org.ph -gov.ph edu.ph -ngo.ph -mil.ph +gov.ph i.ph +mil.ph +net.ph +ngo.ph +org.ph -// pk : https://pknic.net.pk -// pk : http://pk5.pknic.net.pk/pk5/msgNamepk.PK + grandfathered old gon.pk -// Contact Email: staff@pknic.net.pk PKNIC .PK Registry - +// pk : https://pk5.pknic.net.pk/pk5/msgNamepk.PK +// Contact Email: staff@pknic.net.pk pk ac.pk biz.pk @@ -5101,7 +5203,6 @@ gkp.pk gob.pk gog.pk gok.pk -gon.pk gop.pk gos.pk gov.pk @@ -5109,15 +5210,15 @@ net.pk org.pk web.pk -// pl http://www.dns.pl/english/index.html -// Submitted by registry +// pl : https://www.dns.pl/en/ +// Confirmed by registry 2024-11-18 pl com.pl net.pl org.pl -// pl functional domains (http://www.dns.pl/english/index.html) -aid.pl +// pl functional domains : https://www.dns.pl/en/list_of_functional_domain_names agro.pl +aid.pl atm.pl auto.pl biz.pl @@ -5126,8 +5227,8 @@ gmina.pl gsm.pl info.pl mail.pl -miasta.pl media.pl +miasta.pl mil.pl nieruchomosci.pl nom.pl @@ -5146,7 +5247,8 @@ tm.pl tourism.pl travel.pl turystyka.pl -// Government domains +// Government domains : https://www.dns.pl/informacje_o_rejestracji_domen_gov_pl +// In accordance with the .gov.pl Domain Name Regulations : https://www.dns.pl/regulamin_gov_pl gov.pl ap.gov.pl griw.gov.pl @@ -5203,7 +5305,7 @@ wuoz.gov.pl wzmiuw.gov.pl zp.gov.pl zpisdn.gov.pl -// pl regional domains (http://www.dns.pl/english/index.html) +// pl regional domains : https://www.dns.pl/en/list_of_regional_domain_names augustow.pl babia-gora.pl bedzin.pl @@ -5230,11 +5332,11 @@ jaworzno.pl jelenia-gora.pl jgora.pl kalisz.pl -kazimierz-dolny.pl karpacz.pl kartuzy.pl kaszuby.pl katowice.pl +kazimierz-dolny.pl kepno.pl ketrzyn.pl klodzko.pl @@ -5277,8 +5379,8 @@ pisz.pl podhale.pl podlasie.pl polkowice.pl -pomorze.pl pomorskie.pl +pomorze.pl prochowice.pl pruszkow.pl przeworsk.pl @@ -5289,11 +5391,11 @@ rybnik.pl rzeszow.pl sanok.pl sejny.pl +skoczow.pl slask.pl slupsk.pl sosnowiec.pl stalowa-wola.pl -skoczow.pl starachowice.pl stargard.pl suwalki.pl @@ -5327,33 +5429,33 @@ zgorzelec.pl // pm : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf pm -// pn : http://www.government.pn/PnRegistry/policies.htm +// pn : https://www.iana.org/domains/root/db/pn.html pn -gov.pn co.pn -org.pn edu.pn +gov.pn net.pn +org.pn -// post : https://en.wikipedia.org/wiki/.post +// post : https://www.iana.org/domains/root/db/post.html post // pr : http://www.nic.pr/index.asp?f=1 pr +biz.pr com.pr -net.pr -org.pr -gov.pr edu.pr -isla.pr -pro.pr -biz.pr +gov.pr info.pr +isla.pr name.pr -// these aren't mentioned on nic.pr, but on https://en.wikipedia.org/wiki/.pr +net.pr +org.pr +pro.pr +// these aren't mentioned on nic.pr, but on https://www.iana.org/domains/root/db/pr.html +ac.pr est.pr prof.pr -ac.pr // pro : http://registry.pro/get-pro pro @@ -5369,38 +5471,34 @@ law.pro med.pro recht.pro -// ps : https://en.wikipedia.org/wiki/.ps +// ps : https://www.iana.org/domains/root/db/ps.html // http://www.nic.ps/registration/policy.html#reg ps +com.ps edu.ps gov.ps -sec.ps -plo.ps -com.ps -org.ps net.ps +org.ps +plo.ps +sec.ps // pt : https://www.dns.pt/en/domain/pt-terms-and-conditions-registration-rules/ pt -net.pt -gov.pt -org.pt +com.pt edu.pt +gov.pt int.pt -publ.pt -com.pt +net.pt nome.pt +org.pt +publ.pt -// pw : https://en.wikipedia.org/wiki/.pw +// pw : https://www.iana.org/domains/root/db/pw.html +// Confirmed by registry in private correspondence with @dnsguru 2024-12-09 pw -co.pw -ne.pw -or.pw -ed.pw -go.pw -belau.pw - -// py : http://www.nic.py/pautas.html#seccion_9 +gov.pw + +// py : https://www.iana.org/domains/root/db/py.html // Submitted by registry py com.py @@ -5423,10 +5521,11 @@ org.qa sch.qa // re : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf +// Confirmed by registry 2024-11-18 re +// Closed for registration on 2013-03-15 but domains are still maintained asso.re com.re -nom.re // ro : http://www.rotld.ro/ ro @@ -5455,7 +5554,7 @@ org.rs // Submitted by George Georgievsky ru -// rw : https://www.ricta.org.rw/sites/default/files/resources/registry_registrar_contract_0.pdf +// rw : https://www.iana.org/domains/root/db/rw.html rw ac.rw co.rw @@ -5468,12 +5567,12 @@ org.rw // sa : http://www.nic.net.sa/ sa com.sa -net.sa -org.sa +edu.sa gov.sa med.sa +net.sa +org.sa pub.sa -edu.sa sch.sa // sb : http://www.sbnic.net.sb/ @@ -5488,25 +5587,26 @@ org.sb // sc : http://www.nic.sc/ sc com.sc +edu.sc gov.sc net.sc org.sc -edu.sc -// sd : http://www.isoc.sd/sudanic.isoc.sd/billing_pricing.htm +// sd : https://www.iana.org/domains/root/db/sd.html // Submitted by registry sd com.sd -net.sd -org.sd edu.sd -med.sd -tv.sd gov.sd info.sd +med.sd +net.sd +org.sd +tv.sd -// se : https://en.wikipedia.org/wiki/.se -// Submitted by registry +// se : https://www.iana.org/domains/root/db/se.html +// https://data.internetstiftelsen.se/barred_domains_list.txt -> Second level domains & Sub-domains +// Confirmed by Registry Services 2024-11-20 se a.se ac.se @@ -5548,54 +5648,54 @@ x.se y.se z.se -// sg : http://www.nic.net.sg/page/registration-policies-procedures-and-guidelines +// sg : https://www.sgnic.sg/domain-registration/sg-categories-rules +// Confirmed by registry 2024-11-19 sg com.sg +edu.sg +gov.sg net.sg org.sg -gov.sg -edu.sg -per.sg // sh : http://nic.sh/rules.htm sh com.sh -net.sh gov.sh -org.sh mil.sh +net.sh +org.sh -// si : https://en.wikipedia.org/wiki/.si +// si : https://www.iana.org/domains/root/db/si.html si // sj : No registrations at this time. // Submitted by registry sj -// sk : https://en.wikipedia.org/wiki/.sk -// list of 2nd level domains ? +// sk : https://www.iana.org/domains/root/db/sk.html +// https://sk-nic.sk/ sk +org.sk // sl : http://www.nic.sl // Submitted by registry sl com.sl -net.sl edu.sl gov.sl +net.sl org.sl -// sm : https://en.wikipedia.org/wiki/.sm +// sm : https://www.iana.org/domains/root/db/sm.html sm -// sn : https://en.wikipedia.org/wiki/.sn +// sn : https://www.iana.org/domains/root/db/sn.html sn art.sn com.sn edu.sn gouv.sn org.sn -perso.sn univ.sn // so : http://sonic.so/policies/ @@ -5607,13 +5707,14 @@ me.so net.so org.so -// sr : https://en.wikipedia.org/wiki/.sr +// sr : https://www.iana.org/domains/root/db/sr.html sr // ss : https://registry.nic.ss/ // Submitted by registry ss biz.ss +co.ss com.ss edu.ss gov.ss @@ -5636,10 +5737,10 @@ principe.st saotome.st store.st -// su : https://en.wikipedia.org/wiki/.su +// su : https://www.iana.org/domains/root/db/su.html su -// sv : http://www.svnet.org.sv/niveldos.pdf +// sv : https://www.iana.org/domains/root/db/sv.html sv com.sv edu.sv @@ -5647,46 +5748,45 @@ gob.sv org.sv red.sv -// sx : https://en.wikipedia.org/wiki/.sx +// sx : https://www.iana.org/domains/root/db/sx.html // Submitted by registry sx gov.sx -// sy : https://en.wikipedia.org/wiki/.sy -// see also: http://www.gobin.info/domainname/sy.doc +// sy : https://www.iana.org/domains/root/db/sy.html sy +com.sy edu.sy gov.sy -net.sy mil.sy -com.sy +net.sy org.sy -// sz : https://en.wikipedia.org/wiki/.sz +// sz : https://www.iana.org/domains/root/db/sz.html // http://www.sispa.org.sz/ sz -co.sz ac.sz +co.sz org.sz -// tc : https://en.wikipedia.org/wiki/.tc +// tc : https://www.iana.org/domains/root/db/tc.html tc -// td : https://en.wikipedia.org/wiki/.td +// td : https://www.iana.org/domains/root/db/td.html td -// tel: https://en.wikipedia.org/wiki/.tel +// tel : https://www.iana.org/domains/root/db/tel.html // http://www.telnic.org/ tel // tf : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf tf -// tg : https://en.wikipedia.org/wiki/.tg +// tg : https://www.iana.org/domains/root/db/tg.html // http://www.nic.tg/ tg -// th : https://en.wikipedia.org/wiki/.th +// th : https://www.iana.org/domains/root/db/th.html // Submitted by registry th ac.th @@ -5715,23 +5815,24 @@ org.tj test.tj web.tj -// tk : https://en.wikipedia.org/wiki/.tk +// tk : https://www.iana.org/domains/root/db/tk.html tk -// tl : https://en.wikipedia.org/wiki/.tl +// tl : https://www.iana.org/domains/root/db/tl.html tl gov.tl -// tm : http://www.nic.tm/local.html +// tm : https://www.nic.tm/local.html +// Confirmed by registry 2024-11-19 tm -com.tm co.tm -org.tm -net.tm -nom.tm +com.tm +edu.tm gov.tm mil.tm -edu.tm +net.tm +nom.tm +org.tm // tn : http://www.registre.tn/fr/ // https://whois.ati.tn/ @@ -5750,15 +5851,15 @@ org.tn perso.tn tourism.tn -// to : https://en.wikipedia.org/wiki/.to +// to : https://www.iana.org/domains/root/db/to.html // Submitted by registry to com.to +edu.to gov.to +mil.to net.to org.to -edu.to -mil.to // tr : https://nic.tr/ // https://nic.tr/forms/eng/policies.pdf @@ -5774,9 +5875,9 @@ edu.tr gen.tr gov.tr info.tr -mil.tr k12.tr kep.tr +mil.tr name.tr net.tr org.tr @@ -5790,46 +5891,40 @@ nc.tr // Used by government agencies of Northern Cyprus gov.nc.tr -// tt : http://www.nic.tt/ +// tt : https://www.nic.tt/ +// Confirmed by registry 2024-11-19 tt +biz.tt co.tt com.tt -org.tt -net.tt -biz.tt +edu.tt +gov.tt info.tt -pro.tt -int.tt -coop.tt -jobs.tt -mobi.tt -travel.tt -museum.tt -aero.tt +mil.tt name.tt -gov.tt -edu.tt +net.tt +org.tt +pro.tt -// tv : https://en.wikipedia.org/wiki/.tv +// tv : https://www.iana.org/domains/root/db/tv.html // Not listing any 2LDs as reserved since none seem to exist in practice, // Wikipedia notwithstanding. tv -// tw : https://en.wikipedia.org/wiki/.tw +// tw : https://www.iana.org/domains/root/db/tw.html +// https://twnic.tw/dnservice_catag.php +// Confirmed by registry 2024-11-26 tw +club.tw +com.tw +ebiz.tw edu.tw +game.tw gov.tw +idv.tw mil.tw -com.tw net.tw org.tw -idv.tw -game.tw -ebiz.tw -club.tw -網路.tw -組織.tw -商業.tw // tz : http://www.tznic.or.tz/index.php/domains // Submitted by registry @@ -5934,17 +6029,23 @@ zp.ua zt.ua // ug : https://www.registry.co.ug/ +// https://www.registry.co.ug, https://whois.co.ug +// Confirmed by registry 2025-01-20 ug -co.ug -or.ug ac.ug -sc.ug +co.ug +com.ug +edu.ug go.ug +gov.ug +mil.ug ne.ug -com.ug +or.ug org.ug +sc.ug +us.ug -// uk : https://en.wikipedia.org/wiki/.uk +// uk : https://www.iana.org/domains/root/db/uk.html // Submitted by registry uk ac.uk @@ -5959,14 +6060,13 @@ plc.uk police.uk *.sch.uk -// us : https://en.wikipedia.org/wiki/.us +// us : https://www.iana.org/domains/root/db/us.html +// Confirmed via the .us zone file by William Harrison 2024-12-10 us dni.us -fed.us isa.us -kids.us nsn.us -// us geographic names +// Geographic Names ak.us al.us ar.us @@ -6015,9 +6115,9 @@ sd.us tn.us tx.us ut.us +va.us vi.us vt.us -va.us wa.us wi.us wv.us @@ -6040,7 +6140,7 @@ k12.dc.us k12.fl.us k12.ga.us k12.gu.us -// k12.hi.us Bug 614565 - Hawaii has a state-wide DOE login +// k12.hi.us - Bug 614565 - Hawaii has a state-wide DOE login k12.ia.us k12.id.us k12.il.us @@ -6057,7 +6157,7 @@ k12.mo.us k12.ms.us k12.mt.us k12.nc.us -// k12.nd.us Bug 1028347 - Removed at request of Travis Rosso +// k12.nd.us - Bug 1028347 - Removed at request of Travis Rosso k12.ne.us k12.nh.us k12.nj.us @@ -6069,139 +6169,137 @@ k12.ok.us k12.or.us k12.pa.us k12.pr.us -// k12.ri.us Removed at request of Kim Cournoyer +// k12.ri.us - Removed at request of Kim Cournoyer k12.sc.us -// k12.sd.us Bug 934131 - Removed at request of James Booze +// k12.sd.us - Bug 934131 - Removed at request of James Booze k12.tn.us k12.tx.us k12.ut.us +k12.va.us k12.vi.us k12.vt.us -k12.va.us k12.wa.us k12.wi.us -// k12.wv.us Bug 947705 - Removed at request of Verne Britton -k12.wy.us +// k12.wv.us - Bug 947705 - Removed at request of Verne Britton cc.ak.us +lib.ak.us cc.al.us +lib.al.us cc.ar.us +lib.ar.us cc.as.us +lib.as.us cc.az.us +lib.az.us cc.ca.us +lib.ca.us cc.co.us +lib.co.us cc.ct.us +lib.ct.us cc.dc.us +lib.dc.us cc.de.us cc.fl.us +lib.fl.us cc.ga.us +lib.ga.us cc.gu.us +lib.gu.us cc.hi.us +lib.hi.us cc.ia.us +lib.ia.us cc.id.us +lib.id.us cc.il.us +lib.il.us cc.in.us +lib.in.us cc.ks.us +lib.ks.us cc.ky.us +lib.ky.us cc.la.us +lib.la.us cc.ma.us +lib.ma.us cc.md.us +lib.md.us cc.me.us +lib.me.us cc.mi.us +lib.mi.us cc.mn.us +lib.mn.us cc.mo.us +lib.mo.us cc.ms.us cc.mt.us -cc.nc.us -cc.nd.us -cc.ne.us -cc.nh.us -cc.nj.us -cc.nm.us -cc.nv.us -cc.ny.us -cc.oh.us -cc.ok.us -cc.or.us -cc.pa.us -cc.pr.us -cc.ri.us -cc.sc.us -cc.sd.us -cc.tn.us -cc.tx.us -cc.ut.us -cc.vi.us -cc.vt.us -cc.va.us -cc.wa.us -cc.wi.us -cc.wv.us -cc.wy.us -lib.ak.us -lib.al.us -lib.ar.us -lib.as.us -lib.az.us -lib.ca.us -lib.co.us -lib.ct.us -lib.dc.us -// lib.de.us Issue #243 - Moved to Private section at request of Ed Moore -lib.fl.us -lib.ga.us -lib.gu.us -lib.hi.us -lib.ia.us -lib.id.us -lib.il.us -lib.in.us -lib.ks.us -lib.ky.us -lib.la.us -lib.ma.us -lib.md.us -lib.me.us -lib.mi.us -lib.mn.us -lib.mo.us -lib.ms.us lib.mt.us +cc.nc.us lib.nc.us +cc.nd.us lib.nd.us +cc.ne.us lib.ne.us +cc.nh.us lib.nh.us +cc.nj.us lib.nj.us +cc.nm.us lib.nm.us +cc.nv.us lib.nv.us +cc.ny.us lib.ny.us +cc.oh.us lib.oh.us +cc.ok.us lib.ok.us +cc.or.us lib.or.us +cc.pa.us lib.pa.us +cc.pr.us lib.pr.us +cc.ri.us lib.ri.us +cc.sc.us lib.sc.us +cc.sd.us lib.sd.us +cc.tn.us lib.tn.us +cc.tx.us lib.tx.us +cc.ut.us lib.ut.us +cc.va.us +lib.va.us +cc.vi.us lib.vi.us +cc.vt.us lib.vt.us -lib.va.us +cc.wa.us lib.wa.us +cc.wi.us lib.wi.us -// lib.wv.us Bug 941670 - Removed at request of Larry W Arnold +cc.wv.us +cc.wy.us +k12.wy.us +// lib.wv.us - Bug 941670 - Removed at request of Larry W Arnold lib.wy.us // k12.ma.us contains school districts in Massachusetts. The 4LDs are -// managed independently except for private (PVT), charter (CHTR) and -// parochial (PAROCH) schools. Those are delegated directly to the -// 5LD operators. -pvt.k12.ma.us +// managed independently except for private (PVT), charter (CHTR) and +// parochial (PAROCH) schools. Those are delegated directly to the +// 5LD operators. chtr.k12.ma.us paroch.k12.ma.us +pvt.k12.ma.us // Merit Network, Inc. maintains the registry for =~ /(k12|cc|lib).mi.us/ and the following -// see also: http://domreg.merit.edu -// see also: whois -h whois.domreg.merit.edu help +// see also: https://domreg.merit.edu : domreg@merit.edu +// see also: whois -h whois.domreg.merit.edu help ann-arbor.mi.us cog.mi.us dst.mi.us @@ -6227,20 +6325,21 @@ com.uz net.uz org.uz -// va : https://en.wikipedia.org/wiki/.va +// va : https://www.iana.org/domains/root/db/va.html va -// vc : https://en.wikipedia.org/wiki/.vc +// vc : https://www.iana.org/domains/root/db/vc.html // Submitted by registry vc com.vc -net.vc -org.vc +edu.vc gov.vc mil.vc -edu.vc +net.vc +org.vc // ve : https://registro.nic.ve/ +// https://nic.ve/site/user-agreement -> under "III. Clasificación de Nombres de Dominio" // Submitted by registry nic@nic.ve and nicve@conatel.gob.ve ve arts.ve @@ -6249,9 +6348,11 @@ co.ve com.ve e12.ve edu.ve +emprende.ve firm.ve gob.ve gov.ve +ia.ve info.ve int.ve mil.ve @@ -6264,13 +6365,12 @@ store.ve tec.ve web.ve -// vg : https://en.wikipedia.org/wiki/.vg +// vg : https://www.iana.org/domains/root/db/vg.html +// Confirmed by registry 2025-01-10 vg +edu.vg -// vi : http://www.nic.vi/newdomainform.htm -// http://www.nic.vi/Domain_Rules/body_domain_rules.html indicates some other -// TLDs are "reserved", such as edu.vi and gov.vi, but doesn't actually say they -// are available for registration (which they do not seem to be). +// vi : https://www.iana.org/domains/root/db/vi.html vi co.vi com.vi @@ -6327,6 +6427,7 @@ hanoi.vn hatinh.vn haugiang.vn hoabinh.vn +hue.vn hungyen.vn khanhhoa.vn kiengiang.vn @@ -6362,7 +6463,7 @@ vinhlong.vn vinhphuc.vn yenbai.vn -// vu : https://en.wikipedia.org/wiki/.vu +// vu : https://www.iana.org/domains/root/db/vu.html // http://www.vunic.vu/ vu com.vu @@ -6373,14 +6474,14 @@ org.vu // wf : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf wf -// ws : https://en.wikipedia.org/wiki/.ws +// ws : https://www.iana.org/domains/root/db/ws.html // http://samoanic.ws/index.dhtml ws com.ws +edu.ws +gov.ws net.ws org.ws -gov.ws -edu.ws // yt : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf yt @@ -6415,12 +6516,12 @@ yt // xn--fiqs8s ("Zhongguo/China", Chinese, Simplified) : CN // CNNIC -// http://cnnic.cn/html/Dir/2005/10/11/3218.htm +// https://www.cnnic.cn/11/192/index.html 中国 // xn--fiqz9s ("Zhongguo/China", Chinese, Traditional) : CN // CNNIC -// http://cnnic.cn/html/Dir/2005/10/11/3218.htm +// https://www.cnnic.com.cn/AU/MediaC/Announcement/201609/t20160905_54470.htm 中國 // xn--lgbbat1ad8j ("Algeria/Al Jazair", Arabic) : DZ @@ -6453,12 +6554,12 @@ yt // Submitted by registry // https://www.hkirc.hk/content.jsp?id=30#!/34 香港 +個人.香港 公司.香港 -教育.香港 政府.香港 -個人.香港 -網絡.香港 +教育.香港 組織.香港 +網絡.香港 // xn--2scrj9c ("Bharat", Kannada) : IN // India @@ -6589,12 +6690,12 @@ yt // xn--90a3ac ("srb", Cyrillic) : RS // https://www.rnids.rs/en/domains/national-domains срб -пр.срб -орг.срб +ак.срб обр.срб од.срб +орг.срб +пр.срб упр.срб -ак.срб // xn--p1ai ("rf", Russian-Cyrillic) : RU // https://cctld.ru/files/pdf/docs/en/rules_ru-rf.pdf @@ -6609,7 +6710,7 @@ yt // http://www.nic.net.sa/ السعودية -// xn--mgberp4a5d4a87g ("AlSaudiah", Arabic, variant) : SA +// xn--mgberp4a5d4a87g ("AlSaudiah", Arabic, variant): SA السعودیة // xn--mgbqly7c0a67fbc ("AlSaudiah", Arabic, variant) : SA @@ -6637,11 +6738,11 @@ yt // xn--o3cw4h ("Thai", Thai) : TH // http://www.thnic.co.th ไทย -ศึกษา.ไทย -ธุรกิจ.ไทย -รัฐบาล.ไทย ทหาร.ไทย +ธุรกิจ.ไทย เน็ต.ไทย +รัฐบาล.ไทย +ศึกษา.ไทย องค์กร.ไทย // xn--pgbs0dh ("Tunisia", Arabic) : TN @@ -6649,7 +6750,7 @@ yt تونس // xn--kpry57d ("Taiwan", Chinese, Traditional) : TW -// http://www.twnic.net/english/dn/dn_07a.htm +// https://twnic.tw/dnservice_catag.php 台灣 // xn--kprw13d ("Taiwan", Chinese, Simplified) : TW @@ -6673,11 +6774,11 @@ ye com.ye edu.ye gov.ye -net.ye mil.ye +net.ye org.ye -// za : https://www.zadna.org.za/content/page/domain-information/ +// za : https://www.iana.org/domains/root/db/za.html ac.za agric.za alt.za @@ -6723,7 +6824,7 @@ org.zw // newGTLDs -// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2024-08-12T15:17:09Z +// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2026-04-10T15:53:10Z // This list is auto-generated, don't edit it manually. // aaa : American Automobile Association, Inc. // https://www.iana.org/domains/root/db/aaa.html @@ -6937,7 +7038,7 @@ arab // https://www.iana.org/domains/root/db/aramco.html aramco -// archi : Identity Digital Limited +// archi : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/archi.html archi @@ -6953,7 +7054,7 @@ art // https://www.iana.org/domains/root/db/arte.html arte -// asda : Wal-Mart Stores, Inc. +// asda : Asda Stores Limited // https://www.iana.org/domains/root/db/asda.html asda @@ -7105,10 +7206,6 @@ beauty // https://www.iana.org/domains/root/db/beer.html beer -// bentley : Bentley Motors Limited -// https://www.iana.org/domains/root/db/bentley.html -bentley - // berlin : dotBERLIN GmbH & Co. KG // https://www.iana.org/domains/root/db/berlin.html berlin @@ -7121,7 +7218,7 @@ best // https://www.iana.org/domains/root/db/bestbuy.html bestbuy -// bet : Identity Digital Limited +// bet : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/bet.html bet @@ -7149,11 +7246,11 @@ bing // https://www.iana.org/domains/root/db/bingo.html bingo -// bio : Identity Digital Limited +// bio : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/bio.html bio -// black : Identity Digital Limited +// black : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/black.html black @@ -7173,7 +7270,7 @@ blog // https://www.iana.org/domains/root/db/bloomberg.html bloomberg -// blue : Identity Digital Limited +// blue : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/blue.html blue @@ -7469,7 +7566,7 @@ church // https://www.iana.org/domains/root/db/cipriani.html cipriani -// circle : Amazon Registry Services, Inc. +// circle : Jolly Host, LLC // https://www.iana.org/domains/root/db/circle.html circle @@ -7501,7 +7598,7 @@ claims // https://www.iana.org/domains/root/db/cleaning.html cleaning -// click : Internet Naming Company LLC +// click : Waterford Limited // https://www.iana.org/domains/root/db/click.html click @@ -7669,10 +7766,6 @@ cymru // https://www.iana.org/domains/root/db/cyou.html cyou -// dabur : Dabur India Limited -// https://www.iana.org/domains/root/db/dabur.html -dabur - // dad : Charleston Road Registry Inc. // https://www.iana.org/domains/root/db/dad.html dad @@ -7845,10 +7938,6 @@ dtv // https://www.iana.org/domains/root/db/dubai.html dubai -// dunlop : The Goodyear Tire & Rubber Company -// https://www.iana.org/domains/root/db/dunlop.html -dunlop - // dupont : DuPont Specialty Products USA, LLC // https://www.iana.org/domains/root/db/dupont.html dupont @@ -8125,7 +8214,7 @@ forex // https://www.iana.org/domains/root/db/forsale.html forsale -// forum : Fegistry, LLC +// forum : Waterford Limited // https://www.iana.org/domains/root/db/forum.html forum @@ -8165,7 +8254,7 @@ ftr // https://www.iana.org/domains/root/db/fujitsu.html fujitsu -// fun : Radix Technologies Inc. +// fun : Radix Technologies Inc SEZC // https://www.iana.org/domains/root/db/fun.html fun @@ -8273,7 +8362,7 @@ glass // https://www.iana.org/domains/root/db/gle.html gle -// global : Identity Digital Limited +// global : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/global.html global @@ -8313,10 +8402,6 @@ goldpoint // https://www.iana.org/domains/root/db/golf.html golf -// goo : NTT DOCOMO, INC. -// https://www.iana.org/domains/root/db/goo.html -goo - // goodyear : The Goodyear Tire & Rubber Company // https://www.iana.org/domains/root/db/goodyear.html goodyear @@ -8333,7 +8418,7 @@ google // https://www.iana.org/domains/root/db/gop.html gop -// got : Amazon Registry Services, Inc. +// got : Jolly Host, LLC // https://www.iana.org/domains/root/db/got.html got @@ -8349,7 +8434,7 @@ graphics // https://www.iana.org/domains/root/db/gratis.html gratis -// green : Identity Digital Limited +// green : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/green.html green @@ -8405,11 +8490,11 @@ haus // https://www.iana.org/domains/root/db/hbo.html hbo -// hdfc : HOUSING DEVELOPMENT FINANCE CORPORATION LIMITED +// hdfc : HDFC BANK LIMITED // https://www.iana.org/domains/root/db/hdfc.html hdfc -// hdfcbank : HDFC Bank Limited +// hdfcbank : HDFC BANK LIMITED // https://www.iana.org/domains/root/db/hdfcbank.html hdfcbank @@ -8497,7 +8582,7 @@ horse // https://www.iana.org/domains/root/db/hospital.html hospital -// host : Radix Technologies Inc. +// host : Radix Technologies Inc SEZC // https://www.iana.org/domains/root/db/host.html host @@ -8509,6 +8594,10 @@ hosting // https://www.iana.org/domains/root/db/hot.html hot +// hotel : HOTEL Top-Level-Domain S.a.r.l +// https://www.iana.org/domains/root/db/hotel.html +hotel + // hotels : Booking.com B.V. // https://www.iana.org/domains/root/db/hotels.html hotels @@ -8701,7 +8790,7 @@ jnj // https://www.iana.org/domains/root/db/joburg.html joburg -// jot : Amazon Registry Services, Inc. +// jot : Jolly Host, LLC // https://www.iana.org/domains/root/db/jot.html jot @@ -8737,10 +8826,6 @@ kddi // https://www.iana.org/domains/root/db/kerryhotels.html kerryhotels -// kerrylogistics : Kerry Trading Co. Limited -// https://www.iana.org/domains/root/db/kerrylogistics.html -kerrylogistics - // kerryproperties : Kerry Trading Co. Limited // https://www.iana.org/domains/root/db/kerryproperties.html kerryproperties @@ -8757,7 +8842,7 @@ kia // https://www.iana.org/domains/root/db/kids.html kids -// kim : Identity Digital Limited +// kim : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/kim.html kim @@ -8821,10 +8906,6 @@ lamborghini // https://www.iana.org/domains/root/db/lamer.html lamer -// lancaster : LANCASTER -// https://www.iana.org/domains/root/db/lancaster.html -lancaster - // land : Binky Moon, LLC // https://www.iana.org/domains/root/db/land.html land @@ -8889,7 +8970,7 @@ lego // https://www.iana.org/domains/root/db/lexus.html lexus -// lgbt : Identity Digital Limited +// lgbt : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/lgbt.html lgbt @@ -8937,10 +9018,6 @@ lincoln // https://www.iana.org/domains/root/db/link.html link -// lipsy : Lipsy Ltd -// https://www.iana.org/domains/root/db/lipsy.html -lipsy - // live : Dog Beach, LLC // https://www.iana.org/domains/root/db/live.html live @@ -8949,7 +9026,7 @@ live // https://www.iana.org/domains/root/db/living.html living -// llc : Identity Digital Limited +// llc : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/llc.html llc @@ -8985,7 +9062,7 @@ london // https://www.iana.org/domains/root/db/lotte.html lotte -// lotto : Identity Digital Limited +// lotto : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/lotto.html lotto @@ -9073,7 +9150,7 @@ marriott // https://www.iana.org/domains/root/db/marshalls.html marshalls -// mattel : Mattel Sites, Inc. +// mattel : Mattel IT Services, Inc. // https://www.iana.org/domains/root/db/mattel.html mattel @@ -9117,6 +9194,10 @@ men // https://www.iana.org/domains/root/db/menu.html menu +// merck : Merck Registry Holdings, Inc. +// https://www.iana.org/domains/root/db/merck.html +merck + // merckmsd : MSD Registry Holdings, Inc. // https://www.iana.org/domains/root/db/merckmsd.html merckmsd @@ -9329,7 +9410,7 @@ nissay // https://www.iana.org/domains/root/db/nokia.html nokia -// norton : NortonLifeLock Inc. +// norton : Gen Digital Inc. // https://www.iana.org/domains/root/db/norton.html norton @@ -9337,7 +9418,7 @@ norton // https://www.iana.org/domains/root/db/now.html now -// nowruz : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +// nowruz // https://www.iana.org/domains/root/db/nowruz.html nowruz @@ -9345,7 +9426,7 @@ nowruz // https://www.iana.org/domains/root/db/nowtv.html nowtv -// nra : NRA Holdings Company, INC. +// nra : National Rifle Association of America // https://www.iana.org/domains/root/db/nra.html nra @@ -9401,11 +9482,11 @@ one // https://www.iana.org/domains/root/db/ong.html ong -// onl : iRegistry GmbH +// onl : Jolly Host, LLC // https://www.iana.org/domains/root/db/onl.html onl -// online : Radix Technologies Inc. +// online : Radix Technologies Inc SEZC // https://www.iana.org/domains/root/db/online.html online @@ -9425,7 +9506,7 @@ oracle // https://www.iana.org/domains/root/db/orange.html orange -// organic : Identity Digital Limited +// organic : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/organic.html organic @@ -9461,7 +9542,7 @@ panasonic // https://www.iana.org/domains/root/db/paris.html paris -// pars : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +// pars // https://www.iana.org/domains/root/db/pars.html pars @@ -9485,7 +9566,7 @@ pay // https://www.iana.org/domains/root/db/pccw.html pccw -// pet : Identity Digital Limited +// pet : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/pet.html pet @@ -9529,7 +9610,7 @@ physio // https://www.iana.org/domains/root/db/pics.html pics -// pictet : Pictet Europe S.A. +// pictet : Banque Pictet & Cie SA // https://www.iana.org/domains/root/db/pictet.html pictet @@ -9549,7 +9630,7 @@ pin // https://www.iana.org/domains/root/db/ping.html ping -// pink : Identity Digital Limited +// pink : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/pink.html pink @@ -9589,7 +9670,7 @@ pnc // https://www.iana.org/domains/root/db/pohl.html pohl -// poker : Identity Digital Limited +// poker : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/poker.html poker @@ -9601,15 +9682,11 @@ politie // https://www.iana.org/domains/root/db/porn.html porn -// pramerica : Prudential Financial, Inc. -// https://www.iana.org/domains/root/db/pramerica.html -pramerica - // praxi : Praxi S.p.A. // https://www.iana.org/domains/root/db/praxi.html praxi -// press : Radix Technologies Inc. +// press : Radix Technologies Inc SEZC // https://www.iana.org/domains/root/db/press.html press @@ -9633,7 +9710,7 @@ prof // https://www.iana.org/domains/root/db/progressive.html progressive -// promo : Identity Digital Limited +// promo : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/promo.html promo @@ -9681,7 +9758,7 @@ quest // https://www.iana.org/domains/root/db/racing.html racing -// radio : European Broadcasting Union (EBU) +// radio : Digity, LLC // https://www.iana.org/domains/root/db/radio.html radio @@ -9697,7 +9774,7 @@ realestate // https://www.iana.org/domains/root/db/realtor.html realtor -// realty : Internet Naming Company LLC +// realty : Waterford Limited // https://www.iana.org/domains/root/db/realty.html realty @@ -9705,14 +9782,10 @@ realty // https://www.iana.org/domains/root/db/recipes.html recipes -// red : Identity Digital Limited +// red : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/red.html red -// redstone : Redstone Haute Couture Co., Ltd. -// https://www.iana.org/domains/root/db/redstone.html -redstone - // redumbrella : Travelers TLD, LLC // https://www.iana.org/domains/root/db/redumbrella.html redumbrella @@ -10017,11 +10090,11 @@ sharp // https://www.iana.org/domains/root/db/shell.html shell -// shia : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +// shia // https://www.iana.org/domains/root/db/shia.html shia -// shiksha : Identity Digital Limited +// shiksha : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/shiksha.html shiksha @@ -10057,11 +10130,11 @@ sina // https://www.iana.org/domains/root/db/singles.html singles -// site : Radix Technologies Inc. +// site : Radix Technologies Inc SEZC // https://www.iana.org/domains/root/db/site.html site -// ski : Identity Digital Limited +// ski : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/ski.html ski @@ -10069,7 +10142,7 @@ ski // https://www.iana.org/domains/root/db/skin.html skin -// sky : Sky International AG +// sky : Sky UK Limited // https://www.iana.org/domains/root/db/sky.html sky @@ -10125,7 +10198,7 @@ solutions // https://www.iana.org/domains/root/db/song.html song -// sony : Sony Corporation +// sony : Sony Group Corporation // https://www.iana.org/domains/root/db/sony.html sony @@ -10137,7 +10210,7 @@ soy // https://www.iana.org/domains/root/db/spa.html spa -// space : Radix Technologies Inc. +// space : Radix Technologies Inc SEZC // https://www.iana.org/domains/root/db/space.html space @@ -10189,7 +10262,7 @@ stockholm // https://www.iana.org/domains/root/db/storage.html storage -// store : Radix Technologies Inc. +// store : Radix Technologies Inc SEZC // https://www.iana.org/domains/root/db/store.html store @@ -10293,7 +10366,7 @@ tax // https://www.iana.org/domains/root/db/taxi.html taxi -// tci : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +// tci // https://www.iana.org/domains/root/db/tci.html tci @@ -10305,7 +10378,7 @@ tdk // https://www.iana.org/domains/root/db/team.html team -// tech : Radix Technologies Inc. +// tech : Radix Technologies Inc SEZC // https://www.iana.org/domains/root/db/tech.html tech @@ -10389,7 +10462,7 @@ tokyo // https://www.iana.org/domains/root/db/tools.html tools -// top : .TOP Registry +// top : Hong Kong Zhongze International Limited // https://www.iana.org/domains/root/db/top.html top @@ -10489,7 +10562,7 @@ unicom // https://www.iana.org/domains/root/db/university.html university -// uno : Radix Technologies Inc. +// uno : Radix Technologies Inc SEZC // https://www.iana.org/domains/root/db/uno.html uno @@ -10633,15 +10706,15 @@ wanggou // https://www.iana.org/domains/root/db/watch.html watch -// watches : Identity Digital Limited +// watches : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/watches.html watches -// weather : International Business Machines Corporation +// weather : The Weather Company, LLC // https://www.iana.org/domains/root/db/weather.html weather -// weatherchannel : International Business Machines Corporation +// weatherchannel : The Weather Company, LLC // https://www.iana.org/domains/root/db/weatherchannel.html weatherchannel @@ -10653,7 +10726,7 @@ webcam // https://www.iana.org/domains/root/db/weber.html weber -// website : Radix Technologies Inc. +// website : Radix Technologies Inc SEZC // https://www.iana.org/domains/root/db/website.html website @@ -10677,7 +10750,7 @@ weir // https://www.iana.org/domains/root/db/whoswho.html whoswho -// wien : punkt.wien GmbH +// wien : domainworx Service & Management GmbH // https://www.iana.org/domains/root/db/wien.html wien @@ -10709,10 +10782,6 @@ winners // https://www.iana.org/domains/root/db/wme.html wme -// wolterskluwer : Wolters Kluwer N.V. -// https://www.iana.org/domains/root/db/wolterskluwer.html -wolterskluwer - // woodside : Woodside Petroleum Limited // https://www.iana.org/domains/root/db/woodside.html woodside @@ -10777,7 +10846,7 @@ xin // https://www.iana.org/domains/root/db/xn--3bst00m.html 集团 -// xn--3ds443g : TLD REGISTRY LIMITED OY +// xn--3ds443g : Beijing TLD Registry Technology Limited // https://www.iana.org/domains/root/db/xn--3ds443g.html 在线 @@ -10813,7 +10882,7 @@ xin // https://www.iana.org/domains/root/db/xn--5tzm5g.html 网站 -// xn--6frz82g : Identity Digital Limited +// xn--6frz82g : Identity Digital Domains Limited // https://www.iana.org/domains/root/db/xn--6frz82g.html 移动 @@ -10913,7 +10982,7 @@ xin // https://www.iana.org/domains/root/db/xn--fhbei.html كوم -// xn--fiq228c5hs : TLD REGISTRY LIMITED OY +// xn--fiq228c5hs : Beijing TLD Registry Technology Limited // https://www.iana.org/domains/root/db/xn--fiq228c5hs.html 中文网 @@ -11001,7 +11070,7 @@ xin // https://www.iana.org/domains/root/db/xn--mgbi4ecexp.html كاثوليك -// xn--mgbt3dhd : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. +// xn--mgbt3dhd // https://www.iana.org/domains/root/db/xn--mgbt3dhd.html همراه @@ -11133,7 +11202,7 @@ yahoo // https://www.iana.org/domains/root/db/yamaxun.html yamaxun -// yandex : Yandex Europe B.V. +// yandex : YANDEX, LLC // https://www.iana.org/domains/root/db/yandex.html yandex @@ -11191,7 +11260,7 @@ zuerich // (Note: these are in alphabetical order by company name) -// .KRD : http://nic.krd/data/krd/Registration%20Policy.pdf +// .KRD : https://nic.krd co.krd edu.krd @@ -11203,23 +11272,13 @@ poznan.pl wroc.pl zakopane.pl -// .US -// Submitted by Ed Moore -lib.de.us - -// 12CHARS: https://12chars.com -// Submitted by Kenny Niehage -12chars.dev -12chars.it -12chars.pro - // 1GB LLC : https://www.1gb.ua/ // Submitted by 1GB LLC cc.ua inf.ua ltd.ua -// 611 blockchain domain name system : https://611project.net/ +// 611 blockchain domain name system : https://sixone.one/ 611.to // A2 Hosting @@ -11227,15 +11286,11 @@ ltd.ua a2hosted.com cpserver.com -// AAA workspace : https://aaa.vodka -// Submitted by Kirill Rezraf -aaa.vodka - // Acorn Labs : https://acorn.io // Submitted by Craig Jellick *.on-acorn.io -// ActiveTrail: https://www.activetrail.biz/ +// ActiveTrail : https://www.activetrail.biz/ // Submitted by Ofer Kalaora activetrail.biz @@ -11243,6 +11298,13 @@ activetrail.biz // Submitted by Mark Terrel adaptable.app +// addr.tools : https://addr.tools/ +// Submitted by Brian Shea +myaddr.dev +myaddr.io +dyn.addr.tools +myaddr.tools + // Adobe : https://www.adobe.com/ // Submitted by Ian Boston and Lars Trieloff adobeaemcloud.com @@ -11250,9 +11312,10 @@ adobeaemcloud.com aem.live hlx.live adobeaemcloud.net +aem.network aem.page hlx.page -hlx3.page +aem.reviews // Adobe Developer Platform : https://developer.adobe.com // Submitted by Jesse MacFadyen @@ -11263,18 +11326,17 @@ adobeioruntime.net // Submitted by Gavin Brown africa.com +// AgentbaseAI Inc. : https://assistant-ui.com +// Submitted by Simon Farshid +*.auiusercontent.com + // Agnat sp. z o.o. : https://domena.pl // Submitted by Przemyslaw Plewa beep.pl -// Airkit : https://www.airkit.com/ -// Submitted by Grant Cooksey -airkitapps.com -airkitapps-au.com -airkitapps.eu - -// Aiven: https://aiven.io/ -// Submitted by Etienne Stalmans +// Aiven : https://aiven.io/ +// Submitted by Aiven Security Team +aiven.app aivencloud.com // Akamai : https://www.akamai.com/ @@ -11304,11 +11366,17 @@ barsy.ca *.compute.estate *.alces.network +// Alibaba Cloud API Gateway +// Submitted by Alibaba Cloud Security +alibabacloudcs.com +ms.fun +ms.show + // all-inkl.com : https://all-inkl.com // Submitted by Werner Kaltofen kasserver.com -// Altervista: https://www.altervista.org +// Altervista : https://www.altervista.org // Submitted by Carlo Cannas altervista.org @@ -11326,7 +11394,7 @@ myamaze.net // Amazon API Gateway // Submitted by AWS Security -// Reference: 9e37648f-a66c-4655-9ab1-5981f8737197 +// Reference: 6a4f5a95-8c7d-4077-a7af-9cf1abec0a53 execute-api.cn-north-1.amazonaws.com.cn execute-api.cn-northwest-1.amazonaws.com.cn execute-api.af-south-1.amazonaws.com @@ -11340,6 +11408,7 @@ execute-api.ap-southeast-1.amazonaws.com execute-api.ap-southeast-2.amazonaws.com execute-api.ap-southeast-3.amazonaws.com execute-api.ap-southeast-4.amazonaws.com +execute-api.ap-southeast-5.amazonaws.com execute-api.ca-central-1.amazonaws.com execute-api.ca-west-1.amazonaws.com execute-api.eu-central-1.amazonaws.com @@ -11368,7 +11437,7 @@ cloudfront.net // Amazon Cognito // Submitted by AWS Security -// Reference: cb38c251-c93d-4cda-81ec-e72c4f0fdb72 +// Reference: d7d4a954-976e-403e-a010-de9ed0cfbbd1 auth.af-south-1.amazoncognito.com auth.ap-east-1.amazoncognito.com auth.ap-northeast-1.amazoncognito.com @@ -11380,6 +11449,8 @@ auth.ap-southeast-1.amazoncognito.com auth.ap-southeast-2.amazoncognito.com auth.ap-southeast-3.amazoncognito.com auth.ap-southeast-4.amazoncognito.com +auth.ap-southeast-5.amazoncognito.com +auth.ap-southeast-7.amazoncognito.com auth.ca-central-1.amazoncognito.com auth.ca-west-1.amazoncognito.com auth.eu-central-1.amazoncognito.com @@ -11393,16 +11464,19 @@ auth.eu-west-3.amazoncognito.com auth.il-central-1.amazoncognito.com auth.me-central-1.amazoncognito.com auth.me-south-1.amazoncognito.com +auth.mx-central-1.amazoncognito.com auth.sa-east-1.amazoncognito.com auth.us-east-1.amazoncognito.com auth-fips.us-east-1.amazoncognito.com auth.us-east-2.amazoncognito.com auth-fips.us-east-2.amazoncognito.com +auth-fips.us-gov-east-1.amazoncognito.com auth-fips.us-gov-west-1.amazoncognito.com auth.us-west-1.amazoncognito.com auth-fips.us-west-1.amazoncognito.com auth.us-west-2.amazoncognito.com auth-fips.us-west-2.amazoncognito.com +auth.cognito-idp.eusc-de-east-1.on.amazonwebservices.eu // Amazon EC2 // Submitted by Luke Wells @@ -11517,9 +11591,41 @@ emrstudio-prod.us-west-2.amazonaws.com // Amazon Managed Workflows for Apache Airflow // Submitted by AWS Security -// Reference: f5ea5d0a-ec6a-4f23-ac1c-553fbff13f5c +// Reference: bfd043cc-2816-451d-894e-612c6b61a438 +*.airflow.af-south-1.on.aws +*.airflow.ap-east-1.on.aws +*.airflow.ap-northeast-1.on.aws +*.airflow.ap-northeast-2.on.aws +*.airflow.ap-northeast-3.on.aws +*.airflow.ap-south-1.on.aws +*.airflow.ap-south-2.on.aws +*.airflow.ap-southeast-1.on.aws +*.airflow.ap-southeast-2.on.aws +*.airflow.ap-southeast-3.on.aws +*.airflow.ap-southeast-4.on.aws +*.airflow.ap-southeast-5.on.aws +*.airflow.ca-central-1.on.aws +*.airflow.ca-west-1.on.aws +*.airflow.eu-central-1.on.aws +*.airflow.eu-central-2.on.aws +*.airflow.eu-north-1.on.aws +*.airflow.eu-south-1.on.aws +*.airflow.eu-south-2.on.aws +*.airflow.eu-west-1.on.aws +*.airflow.eu-west-2.on.aws +*.airflow.eu-west-3.on.aws +*.airflow.il-central-1.on.aws +*.airflow.me-central-1.on.aws +*.airflow.me-south-1.on.aws +*.airflow.sa-east-1.on.aws +*.airflow.us-east-1.on.aws +*.airflow.us-east-2.on.aws +*.airflow.us-west-1.on.aws +*.airflow.us-west-2.on.aws *.cn-north-1.airflow.amazonaws.com.cn *.cn-northwest-1.airflow.amazonaws.com.cn +*.airflow.cn-north-1.on.amazonwebservices.com.cn +*.airflow.cn-northwest-1.on.amazonwebservices.com.cn *.af-south-1.airflow.amazonaws.com *.ap-east-1.airflow.amazonaws.com *.ap-northeast-1.airflow.amazonaws.com @@ -11531,6 +11637,8 @@ emrstudio-prod.us-west-2.amazonaws.com *.ap-southeast-2.airflow.amazonaws.com *.ap-southeast-3.airflow.amazonaws.com *.ap-southeast-4.airflow.amazonaws.com +*.ap-southeast-5.airflow.amazonaws.com +*.ap-southeast-7.airflow.amazonaws.com *.ca-central-1.airflow.amazonaws.com *.ca-west-1.airflow.amazonaws.com *.eu-central-1.airflow.amazonaws.com @@ -11550,9 +11658,49 @@ emrstudio-prod.us-west-2.amazonaws.com *.us-west-1.airflow.amazonaws.com *.us-west-2.airflow.amazonaws.com +// Amazon Relational Database Service +// Submitted by: AWS Security +// Reference: 5aa87906-fd4f-4831-8727-4ffca6094159 +*.rds.cn-north-1.amazonaws.com.cn +*.rds.cn-northwest-1.amazonaws.com.cn +*.af-south-1.rds.amazonaws.com +*.ap-east-1.rds.amazonaws.com +*.ap-east-2.rds.amazonaws.com +*.ap-northeast-1.rds.amazonaws.com +*.ap-northeast-2.rds.amazonaws.com +*.ap-northeast-3.rds.amazonaws.com +*.ap-south-1.rds.amazonaws.com +*.ap-south-2.rds.amazonaws.com +*.ap-southeast-1.rds.amazonaws.com +*.ap-southeast-2.rds.amazonaws.com +*.ap-southeast-3.rds.amazonaws.com +*.ap-southeast-4.rds.amazonaws.com +*.ap-southeast-5.rds.amazonaws.com +*.ap-southeast-6.rds.amazonaws.com +*.ap-southeast-7.rds.amazonaws.com +*.ca-central-1.rds.amazonaws.com +*.ca-west-1.rds.amazonaws.com +*.eu-central-1.rds.amazonaws.com +*.eu-central-2.rds.amazonaws.com +*.eu-west-1.rds.amazonaws.com +*.eu-west-2.rds.amazonaws.com +*.eu-west-3.rds.amazonaws.com +*.il-central-1.rds.amazonaws.com +*.me-central-1.rds.amazonaws.com +*.me-south-1.rds.amazonaws.com +*.mx-central-1.rds.amazonaws.com +*.sa-east-1.rds.amazonaws.com +*.us-east-1.rds.amazonaws.com +*.us-east-2.rds.amazonaws.com +*.us-gov-east-1.rds.amazonaws.com +*.us-gov-west-1.rds.amazonaws.com +*.us-northeast-1.rds.amazonaws.com +*.us-west-1.rds.amazonaws.com +*.us-west-2.rds.amazonaws.com + // Amazon S3 // Submitted by AWS Security -// Reference: cd5c8b3a-67b7-4b40-9236-c87ce81a3d10 +// Reference: 6f374c1c-1cc9-47de-8b2a-69ca56a3a3b6 s3.dualstack.cn-north-1.amazonaws.com.cn s3-accesspoint.dualstack.cn-north-1.amazonaws.com.cn s3-website.dualstack.cn-north-1.amazonaws.com.cn @@ -11610,6 +11758,7 @@ s3-object-lambda.ap-south-1.amazonaws.com s3-website.ap-south-1.amazonaws.com s3.dualstack.ap-south-2.amazonaws.com s3-accesspoint.dualstack.ap-south-2.amazonaws.com +s3-website.dualstack.ap-south-2.amazonaws.com s3.ap-south-2.amazonaws.com s3-accesspoint.ap-south-2.amazonaws.com s3-object-lambda.ap-south-2.amazonaws.com @@ -11630,16 +11779,26 @@ s3-object-lambda.ap-southeast-2.amazonaws.com s3-website.ap-southeast-2.amazonaws.com s3.dualstack.ap-southeast-3.amazonaws.com s3-accesspoint.dualstack.ap-southeast-3.amazonaws.com +s3-website.dualstack.ap-southeast-3.amazonaws.com s3.ap-southeast-3.amazonaws.com s3-accesspoint.ap-southeast-3.amazonaws.com s3-object-lambda.ap-southeast-3.amazonaws.com s3-website.ap-southeast-3.amazonaws.com s3.dualstack.ap-southeast-4.amazonaws.com s3-accesspoint.dualstack.ap-southeast-4.amazonaws.com +s3-website.dualstack.ap-southeast-4.amazonaws.com s3.ap-southeast-4.amazonaws.com s3-accesspoint.ap-southeast-4.amazonaws.com s3-object-lambda.ap-southeast-4.amazonaws.com s3-website.ap-southeast-4.amazonaws.com +s3.dualstack.ap-southeast-5.amazonaws.com +s3-accesspoint.dualstack.ap-southeast-5.amazonaws.com +s3-website.dualstack.ap-southeast-5.amazonaws.com +s3.ap-southeast-5.amazonaws.com +s3-accesspoint.ap-southeast-5.amazonaws.com +s3-deprecated.ap-southeast-5.amazonaws.com +s3-object-lambda.ap-southeast-5.amazonaws.com +s3-website.ap-southeast-5.amazonaws.com s3.dualstack.ca-central-1.amazonaws.com s3-accesspoint.dualstack.ca-central-1.amazonaws.com s3-accesspoint-fips.dualstack.ca-central-1.amazonaws.com @@ -11660,6 +11819,7 @@ s3.ca-west-1.amazonaws.com s3-accesspoint.ca-west-1.amazonaws.com s3-accesspoint-fips.ca-west-1.amazonaws.com s3-fips.ca-west-1.amazonaws.com +s3-object-lambda.ca-west-1.amazonaws.com s3-website.ca-west-1.amazonaws.com s3.dualstack.eu-central-1.amazonaws.com s3-accesspoint.dualstack.eu-central-1.amazonaws.com @@ -11670,6 +11830,7 @@ s3-object-lambda.eu-central-1.amazonaws.com s3-website.eu-central-1.amazonaws.com s3.dualstack.eu-central-2.amazonaws.com s3-accesspoint.dualstack.eu-central-2.amazonaws.com +s3-website.dualstack.eu-central-2.amazonaws.com s3.eu-central-2.amazonaws.com s3-accesspoint.eu-central-2.amazonaws.com s3-object-lambda.eu-central-2.amazonaws.com @@ -11689,6 +11850,7 @@ s3-object-lambda.eu-south-1.amazonaws.com s3-website.eu-south-1.amazonaws.com s3.dualstack.eu-south-2.amazonaws.com s3-accesspoint.dualstack.eu-south-2.amazonaws.com +s3-website.dualstack.eu-south-2.amazonaws.com s3.eu-south-2.amazonaws.com s3-accesspoint.eu-south-2.amazonaws.com s3-object-lambda.eu-south-2.amazonaws.com @@ -11716,12 +11878,14 @@ s3-object-lambda.eu-west-3.amazonaws.com s3-website.eu-west-3.amazonaws.com s3.dualstack.il-central-1.amazonaws.com s3-accesspoint.dualstack.il-central-1.amazonaws.com +s3-website.dualstack.il-central-1.amazonaws.com s3.il-central-1.amazonaws.com s3-accesspoint.il-central-1.amazonaws.com s3-object-lambda.il-central-1.amazonaws.com s3-website.il-central-1.amazonaws.com s3.dualstack.me-central-1.amazonaws.com s3-accesspoint.dualstack.me-central-1.amazonaws.com +s3-website.dualstack.me-central-1.amazonaws.com s3.me-central-1.amazonaws.com s3-accesspoint.me-central-1.amazonaws.com s3-object-lambda.me-central-1.amazonaws.com @@ -11790,6 +11954,7 @@ s3.dualstack.us-east-2.amazonaws.com s3-accesspoint.dualstack.us-east-2.amazonaws.com s3-accesspoint-fips.dualstack.us-east-2.amazonaws.com s3-fips.dualstack.us-east-2.amazonaws.com +s3-website.dualstack.us-east-2.amazonaws.com s3.us-east-2.amazonaws.com s3-accesspoint.us-east-2.amazonaws.com s3-accesspoint-fips.us-east-2.amazonaws.com @@ -11801,6 +11966,7 @@ s3.dualstack.us-gov-east-1.amazonaws.com s3-accesspoint.dualstack.us-gov-east-1.amazonaws.com s3-accesspoint-fips.dualstack.us-gov-east-1.amazonaws.com s3-fips.dualstack.us-gov-east-1.amazonaws.com +s3-website.dualstack.us-gov-east-1.amazonaws.com s3.us-gov-east-1.amazonaws.com s3-accesspoint.us-gov-east-1.amazonaws.com s3-accesspoint-fips.us-gov-east-1.amazonaws.com @@ -11811,6 +11977,7 @@ s3.dualstack.us-gov-west-1.amazonaws.com s3-accesspoint.dualstack.us-gov-west-1.amazonaws.com s3-accesspoint-fips.dualstack.us-gov-west-1.amazonaws.com s3-fips.dualstack.us-gov-west-1.amazonaws.com +s3-website.dualstack.us-gov-west-1.amazonaws.com s3.us-gov-west-1.amazonaws.com s3-accesspoint.us-gov-west-1.amazonaws.com s3-accesspoint-fips.us-gov-west-1.amazonaws.com @@ -11904,7 +12071,7 @@ notebook.cn-northwest-1.sagemaker.com.cn // Amazon SageMaker Studio // Submitted by AWS Security -// Reference: 69c723d9-6e1a-4bff-a203-48eecd203183 +// Reference: 475f237e-ab88-4041-9f41-7cfccdf66aeb studio.af-south-1.sagemaker.aws studio.ap-east-1.sagemaker.aws studio.ap-northeast-1.sagemaker.aws @@ -11916,6 +12083,7 @@ studio.ap-southeast-2.sagemaker.aws studio.ap-southeast-3.sagemaker.aws studio.ca-central-1.sagemaker.aws studio.eu-central-1.sagemaker.aws +studio.eu-central-2.sagemaker.aws studio.eu-north-1.sagemaker.aws studio.eu-south-1.sagemaker.aws studio.eu-south-2.sagemaker.aws @@ -12042,7 +12210,7 @@ awsapps.com // AWS Elastic Beanstalk // Submitted by AWS Security -// Reference: bb5a965c-dec3-4967-aa22-e306ad064797 +// Reference: e4e02a54-eaf9-4fe7-b662-39ccbc011a04 cn-north-1.eb.amazonaws.com.cn cn-northwest-1.eb.amazonaws.com.cn elasticbeanstalk.com @@ -12055,14 +12223,18 @@ ap-south-1.elasticbeanstalk.com ap-southeast-1.elasticbeanstalk.com ap-southeast-2.elasticbeanstalk.com ap-southeast-3.elasticbeanstalk.com +ap-southeast-5.elasticbeanstalk.com +ap-southeast-7.elasticbeanstalk.com ca-central-1.elasticbeanstalk.com eu-central-1.elasticbeanstalk.com eu-north-1.elasticbeanstalk.com eu-south-1.elasticbeanstalk.com +eu-south-2.elasticbeanstalk.com eu-west-1.elasticbeanstalk.com eu-west-2.elasticbeanstalk.com eu-west-3.elasticbeanstalk.com il-central-1.elasticbeanstalk.com +me-central-1.elasticbeanstalk.com me-south-1.elasticbeanstalk.com sa-east-1.elasticbeanstalk.com us-east-1.elasticbeanstalk.com @@ -12083,11 +12255,79 @@ us-west-2.elasticbeanstalk.com // Reference: d916759d-a08b-4241-b536-4db887383a6a awsglobalaccelerator.com +// AWS Lambda Function URLs +// Submitted by AWS Security +// Reference: 57df74ca-0820-46a5-89ea-0f0d0c4714b7 +lambda-url.af-south-1.on.aws +lambda-url.ap-east-1.on.aws +lambda-url.ap-northeast-1.on.aws +lambda-url.ap-northeast-2.on.aws +lambda-url.ap-northeast-3.on.aws +lambda-url.ap-south-1.on.aws +lambda-url.ap-southeast-1.on.aws +lambda-url.ap-southeast-2.on.aws +lambda-url.ap-southeast-3.on.aws +lambda-url.ca-central-1.on.aws +lambda-url.eu-central-1.on.aws +lambda-url.eu-north-1.on.aws +lambda-url.eu-south-1.on.aws +lambda-url.eu-west-1.on.aws +lambda-url.eu-west-2.on.aws +lambda-url.eu-west-3.on.aws +lambda-url.me-south-1.on.aws +lambda-url.sa-east-1.on.aws +lambda-url.us-east-1.on.aws +lambda-url.us-east-2.on.aws +lambda-url.us-west-1.on.aws +lambda-url.us-west-2.on.aws + // AWS re:Post Private // Submitted by AWS Security // Reference: 83385945-225f-416e-9aa0-ad0632bfdcee *.private.repost.aws +// AWS Transfer Family web apps +// Submitted by AWS Security +// Reference: 9265cdd3-f017-42ab-98bb-08bf427d3fc9 +transfer-webapp.af-south-1.on.aws +transfer-webapp.ap-east-1.on.aws +transfer-webapp.ap-northeast-1.on.aws +transfer-webapp.ap-northeast-2.on.aws +transfer-webapp.ap-northeast-3.on.aws +transfer-webapp.ap-south-1.on.aws +transfer-webapp.ap-south-2.on.aws +transfer-webapp.ap-southeast-1.on.aws +transfer-webapp.ap-southeast-2.on.aws +transfer-webapp.ap-southeast-3.on.aws +transfer-webapp.ap-southeast-4.on.aws +transfer-webapp.ap-southeast-5.on.aws +transfer-webapp.ap-southeast-7.on.aws +transfer-webapp.ca-central-1.on.aws +transfer-webapp.ca-west-1.on.aws +transfer-webapp.eu-central-1.on.aws +transfer-webapp.eu-central-2.on.aws +transfer-webapp.eu-north-1.on.aws +transfer-webapp.eu-south-1.on.aws +transfer-webapp.eu-south-2.on.aws +transfer-webapp.eu-west-1.on.aws +transfer-webapp.eu-west-2.on.aws +transfer-webapp.eu-west-3.on.aws +transfer-webapp.il-central-1.on.aws +transfer-webapp.me-central-1.on.aws +transfer-webapp.me-south-1.on.aws +transfer-webapp.mx-central-1.on.aws +transfer-webapp.sa-east-1.on.aws +transfer-webapp.us-east-1.on.aws +transfer-webapp.us-east-2.on.aws +transfer-webapp.us-gov-east-1.on.aws +transfer-webapp-fips.us-gov-east-1.on.aws +transfer-webapp.us-gov-west-1.on.aws +transfer-webapp-fips.us-gov-west-1.on.aws +transfer-webapp.us-west-1.on.aws +transfer-webapp.us-west-2.on.aws +transfer-webapp.cn-north-1.on.amazonwebservices.com.cn +transfer-webapp.cn-northwest-1.on.amazonwebservices.com.cn + // eero // Submitted by Yue Kang // Reference: 264afe70-f62c-4c02-8ab9-b5281ed24461 @@ -12096,11 +12336,19 @@ eero-stage.online // concludes Amazon +// Anomaly : https://opencode.ai +// Submitted by Dax Raad +opentunnel.xyz + +// Antagonist B.V. : https://www.antagonist.nl/ +// Submitted by Sander Hoentjen +antagonist.cloud + // Apigee : https://apigee.com/ // Submitted by Apigee Security Team apigee.io -// Apis Networks: https://apisnetworks.com +// Apis Networks : https://apisnetworks.com // Submitted by Matt Saladna panel.dev @@ -12108,6 +12356,24 @@ panel.dev // Submitted by Alexander Selivanov siiites.com +// Apple : https://www.apple.com +// Submitted by Apple DNS +int.apple +*.cloud.int.apple +*.r.cloud.int.apple +*.ap-north-1.r.cloud.int.apple +*.ap-south-1.r.cloud.int.apple +*.ap-south-2.r.cloud.int.apple +*.eu-central-1.r.cloud.int.apple +*.eu-north-1.r.cloud.int.apple +*.us-central-1.r.cloud.int.apple +*.us-central-2.r.cloud.int.apple +*.us-east-1.r.cloud.int.apple +*.us-east-2.r.cloud.int.apple +*.us-west-1.r.cloud.int.apple +*.us-west-2.r.cloud.int.apple +*.us-west-3.r.cloud.int.apple + // Appspace : https://www.appspace.com // Submitted by Appspace Security Team appspacehosted.com @@ -12117,6 +12383,12 @@ appspaceusercontent.com // Submitted by Alexander Hochbaum appudo.net +// Appwrite : https://appwrite.io +// Submitted by Steven Nguyen +appwrite.global +appwrite.network +*.appwrite.run + // Aptible : https://www.aptible.com/ // Submitted by Thomas Orozco on-aptible.com @@ -12125,6 +12397,10 @@ on-aptible.com // Submitted by Aki Ueno f5.si +// ArvanCloud EdgeCompute +// Submitted by ArvanCloud CDN +arvanedge.ir + // ASEINet : https://www.aseinet.com/ // Submitted by Asei SEKIGUCHI user.aseinet.ne.jp @@ -12150,29 +12426,17 @@ myasustor.com // Submitted by Sam Smyth cdn.prod.atlassian-dev.net -// Authentick UG (haftungsbeschränkt) : https://authentick.net -// Submitted by Lukas Reschke -translated.page - -// Autocode : https://autocode.com -// Submitted by Jacob Lee -autocode.dev - // AVM : https://avm.de // Submitted by Andreas Weise myfritz.link myfritz.net -// AVStack Pte. Ltd. : https://avstack.io -// Submitted by Jasper Hugo -onavstack.net - // AW AdvisorWebsites.com Software Inc : https://advisorwebsites.com // Submitted by James Kennedy *.awdev.ca *.advisor.ws -// AZ.pl sp. z.o.o: https://az.pl +// AZ.pl sp. z.o.o : https://az.pl // Submitted by Krzysztof Wolski ecommerce-shop.pl @@ -12184,12 +12448,6 @@ b-data.io // Submitted by Petros Angelatos balena-devices.com -// Banzai Cloud -// Submitted by Janos Matyas -*.banzai.cloud -app.banzaicloud.io -*.backyards.banzaicloud.io - // BASE, Inc. : https://binc.jp // Submitted by Yuya NAGASAWA base.ec @@ -12207,18 +12465,19 @@ base.shop // Submitted by Jason Kridner beagleboard.io -// Beget Ltd -// Submitted by Lev Nekrasov +// Bear Blog : https://bearblog.dev +// Submitted by Herman Martinus +bearblog.dev + +// Beget LLC : https://beget.com +// Submitted by Lev Nekrasov & Nikita Radchenko *.beget.app +*.begetcdn.cloud // Besties : https://besties.house // Submitted by Hazel Cora pages.gay -// BetaInABox -// Submitted by Adrian -betainabox.com - // BinaryLane : http://www.binarylane.com // Submitted by Nathan O'Sullivan bnr.la @@ -12235,6 +12494,10 @@ blackbaudcdn.net // Submitted by Luke Bratch of.je +// Block, Inc. : https://block.xyz +// Submitted by Jonathan Boice +square.site + // Blue Bite, LLC : https://bluebite.com // Submitted by Joshua Weiss bluebite.io @@ -12262,10 +12525,16 @@ square7.net // Brave : https://brave.com // Submitted by Andrea Brancaleoni +brave.app +*.s.brave.app +brave.dev +*.s.brave.dev +brave.io *.s.brave.io // Brendly : https://brendly.rs // Submitted by Dusan Radovanovic +shop.brendly.ba shop.brendly.hr shop.brendly.rs @@ -12278,6 +12547,15 @@ browsersafetymark.io radio.am radio.fm +// Bubble : https://bubble.io/ +// Submitted by Merlin Zhao +cdn.bubble.io +bubbleapps.io + +// bwCloud-OS : https://bwcloud-os.de/ +// Submitted by Klara Mall +*.bwcloud-os-instance.de + // Bytemark Hosting : https://www.bytemark.co.uk // Submitted by Paul Cammish uk0.bigv.io @@ -12288,16 +12566,16 @@ vm.bytemark.co.uk // Submitted by Antonio Lain cafjs.com -// callidomus : https://www.callidomus.com/ -// Submitted by Marcus Popp -mycd.eu - // Canva Pty Ltd : https://canva.com/ // Submitted by Joel Aquilina canva-apps.cn -*.my.canvasite.cn +my.canvasite.cn canva-apps.com -*.my.canva.site +canva-hosted-embed.com +canvacode.com +rice-labs.com +canva.run +my.canva.site // Carrd : https://carrd.co // Submitted by AJ @@ -12321,7 +12599,7 @@ c.cdn77.org rsc.cdn77.org ssl.origin.cdn77-secure.org -// CentralNic : http://www.centralnic.com/names/domains +// CentralNic : https://teaminternet.com/ // Submitted by registry za.bz br.com @@ -12344,16 +12622,13 @@ uk.net ae.org com.se -// certmgr.org : https://certmgr.org -// Submitted by B. Blechschmidt -certmgr.org - -// Cityhost LLC : https://cityhost.ua +// Cityhost LLC : https://cityhost.ua // Submitted by Maksym Rivtin cx.ua // Civilized Discourse Construction Kit, Inc. : https://www.discourse.org/ -// Submitted by Rishabh Nambiar & Michael Brown +// Submitted by Rishabh Nambiar, Michael Brown, Rafael dos Santos Silva +discourse.diy discourse.group discourse.team @@ -12381,20 +12656,26 @@ clickrising.net // Submitted by Aleksander Hristov & Boyan Peychev cloudns.asia cloudns.be +cloud-ip.biz cloudns.biz +cloud-ip.cc cloudns.cc cloudns.ch cloudns.cl cloudns.club +abrdns.com dnsabr.com +ip-ddns.com cloudns.cx cloudns.eu cloudns.in cloudns.info +ddns-ip.net dns-cloud.net dns-dynamic.net cloudns.nz cloudns.org +ip-dynamic.org cloudns.ph cloudns.pro cloudns.pw @@ -12404,7 +12685,6 @@ cloudns.us // Submitted by Khash Sajadi c66.me cloud66.ws -cloud66.zone // CloudAccess.net : https://www.cloudaccess.net/ // Submitted by Pawel Panek @@ -12414,12 +12694,17 @@ cloudaccess.host freesite.host cloudaccess.net +// Cloudbees, Inc. : https://www.cloudbees.com/ +// Submitted by Mohideen Shajith +cloudbeesusercontent.io + // Cloudera, Inc. : https://www.cloudera.com/ // Submitted by Kedarnath Waikar *.cloudera.site // Cloudflare, Inc. : https://www.cloudflare.com/ // Submitted by Cloudflare Team +cloudflare.app cf-ipfs.com cloudflare-ipfs.com trycloudflare.com @@ -12437,6 +12722,8 @@ cdn.cloudflareglobal.net cust.cloudscale.ch objects.lpg.cloudscale.ch objects.rma.cloudscale.ch +lpg.objectstorage.ch +rma.objectstorage.ch // Clovyr : https://clovyr.io // Submitted by Patrick Nielsen @@ -12470,14 +12757,29 @@ preview.csb.app co.nl co.no +// Cognition AI, Inc. : https://cognition.ai +// Submitted by Philip Papurt +*.devinapps.com + // Combell.com : https://www.combell.com -// Submitted by Thomas Wouters +// Submitted by Combell Team webhosting.be +prvw.eu hosting-cluster.nl +// Contentful GmbH : https://www.contentful.com +// Submitted by Contentful Developer Experience Team +ctfcloud.net + // Convex : https://convex.dev/ // Submitted by James Cowling +convex.app +convex.cloud +eu-west-1.convex.cloud +us-east-1.convex.cloud convex.site +eu-west-1.convex.site +us-east-1.convex.site // Coordination Center for TLD RU and XN--P1AI : https://cctld.ru/en/domains/domens_ru/reserved/ // Submitted by George Georgievsky @@ -12486,7 +12788,10 @@ edu.ru gov.ru int.ru mil.ru -test.ru + +// CoreSpeed, Inc. : https://corespeed.io +// Submitted by CoreSpeed Team +corespeed.app // COSIMO GmbH : http://www.cosimo.de // Submitted by Rene Marticke @@ -12516,18 +12821,6 @@ on.crisp.email // Submitted by Andrew Cady *.cryptonomic.net -// Curv UG : https://curv-labs.de/ -// Submitted by Marvin Wiesner -curv.dev - -// Customer OCI - Oracle Dyn https://cloud.oracle.com/home https://dyn.com/dns/ -// Submitted by Gregory Drake -// Note: This is intended to also include customer-oci.com due to wildcards implicitly including the current label -*.customer-oci.com -*.oci.customer-oci.com -*.ocp.customer-oci.com -*.ocs.customer-oci.com - // cyber_Folks S.A. : https://cyberfolks.pl // Submitted by Bartlomiej Kida cfolks.pl @@ -12537,12 +12830,6 @@ cfolks.pl cyon.link cyon.site -// Danger Science Group: https://dangerscience.com/ -// Submitted by Skylar MacDonald -platform0.app -fnwk.site -folionetwork.site - // Dansk.net : http://www.dansk.net/ // Submitted by Anani Voule biz.dk @@ -12551,20 +12838,10 @@ firm.dk reg.dk store.dk -// Daplie, Inc : https://daplie.com -// Submitted by AJ ONeal -daplie.me -localhost.daplie.me - // dappnode.io : https://dappnode.io/ // Submitted by Abel Boldu / DAppNode Team dyndns.dappnode.io -// dapps.earth : https://dapps.earth/ -// Submitted by Daniil Burdakov -*.dapps.earth -*.bzz.dapps.earth - // Dark, Inc. : https://darklang.com // Submitted by Paul Biggar builtwithdark.com @@ -12588,10 +12865,6 @@ mydatto.com dattolocal.net mydatto.net -// DDNS5 : https://ddns5.com -// Submitted by Cameron Elliott -ddns5.com - // ddnss.de : https://www.ddnss.de/ // Submitted by Robert Niedziela ddnss.de @@ -12617,18 +12890,52 @@ definima.net // Submitted by Luca Casonato deno.dev deno-staging.dev +deno.net +sandbox.deno.net + +// DeployAgent : https://deployagent.com +// Submitted by Danny +deployagent.com // deSEC : https://desec.io/ // Submitted by Peter Thomassen dedyn.io -// Deta: https://www.deta.sh/ +// Deta : https://www.deta.sh/ // Submitted by Aavash Shrestha deta.app deta.dev -// dhosting.pl Sp. z o.o.: https://dhosting.pl/ -// Submitted by Michal Kokoszkiewicz +// Deuxfleurs : https://deuxfleurs.fr +// Submitted by Aeddis Desauw +deuxfleurs.eu +deuxfleurs.page + +// Developed Methods LLC : https://methods.dev +// Submitted by Patrick Lorio +*.at.ply.gg +d6.ply.gg +joinmc.link +playit.plus +*.at.playit.plus +with.playit.plus + +// Dfinity Foundation: https://dfinity.org/ +// Submitted by Dfinity Team +icp0.io +*.raw.icp0.io +icp1.io +*.raw.icp1.io +*.icp.net +caffeine.site +caffeine.xyz + +// dhosting.pl Sp. z o.o. : https://dhosting.pl/ +// Submitted by Szczepan Redzioch +mybox.company +intouch.email +mybox.me +mybox.page dfirma.pl dkonto.pl you2.pl @@ -12643,35 +12950,42 @@ ondigitalocean.app // DigitalPlat : https://www.digitalplat.org/ // Submitted by Edward Hsing +qzz.io us.kg - -// Diher Solutions : https://diher.solutions -// Submitted by Didi Hermawan -*.rss.my.id -*.diher.solutions +xx.kg +dpdns.org // Discord Inc : https://discord.com // Submitted by Sahn Lam discordsays.com discordsez.com -// DNS Africa Ltd https://dns.business +// DNS Africa Ltd : https://dns.business // Submitted by Calvin Browne jozi.biz +// DNSHE : https://www.dnshe.com +// Submitted by DNSHE Team +ccwu.cc +cc.cd +us.ci +de5.net + // DNShome : https://www.dnshome.de/ // Submitted by Norbert Auler dnshome.de -// dnstrace.pro : https://dnstrace.pro/ -// Submitted by Chris Partridge -bci.dnstrace.pro - // DotArai : https://www.dotarai.com/ // Submitted by Atsadawat Netcharadsang online.th shop.th +// dotScot Domains : https://domains.scot/ +// Submitted by DNS Team +co.scot +me.scot +org.scot + // DrayTek Corp. : https://www.draytek.com/ // Submitted by Paul Fang drayddns.com @@ -12688,15 +13002,6 @@ dreamhosters.com // Submitted by Infra Team durumis.com -// Drobo : http://www.drobo.com/ -// Submitted by Ricardo Padilha -mydrobo.com - -// Drud Holdings, LLC. : https://www.drud.com/ -// Submitted by Kevin Bridges -drud.io -drud.us - // DuckDNS : http://www.duckdns.org/ // Submitted by Richard Harper duckdns.org @@ -12988,21 +13293,33 @@ dyndns.ws mypets.ws // Dynu.com : https://www.dynu.com/ -// Submitted by Sue Ye +// Submitted by Sue Ye +1cooldns.com +bumbleshrimp.com ddnsfree.com ddnsgeek.com +ddnsguru.com +dynuddns.com +dynuhosting.com giize.com gleeze.com kozow.com loseyourip.com ooguy.com +pivohosting.com theworkpc.com +wiredbladehosting.com casacam.net dynu.net +dynuddns.net +mysynology.net +opik.net +spryt.net accesscam.org camdvr.org freeddns.org mywire.org +roxa.org webredirect.org myddns.rocks @@ -13023,11 +13340,6 @@ easypanel.host // Submitted by *.ewp.live -// ECG Robotics, Inc: https://ecgrobotics.org -// Submitted by -onred.one -staging.onred.one - // eDirect Corp. : https://hosting.url.com.tw/ // Submitted by C.S. chang twmail.cc @@ -13049,25 +13361,31 @@ rt.ht elementor.cloud elementor.cool -// En root‽ : https://en-root.org -// Submitted by Emmanuel Raviart -en-root.fr +// Emergent : https://emergent.sh +// Submitted by Emergent Security Team +emergent.cloud +preview.emergentagent.com +emergent.host -// Enalean SAS: https://www.enalean.com +// Enalean SAS : https://www.enalean.com // Submitted by Enalean Security Team mytuleap.com tuleap-partners.com -// Encoretivity AB: https://encore.dev -// Submitted by André Eriksson +// Encoretivity AB : https://encore.cloud +// Submitted by André Eriksson encr.app +frontend.encr.app encoreapi.com +lp.dev +api.lp.dev +objects.lp.dev // encoway GmbH : https://www.encoway.de // Submitted by Marcel Daus eu.encoway.cloud -// EU.org https://eu.org/ +// EU.org : https://eu.org/ // Submitted by Pierre Beyssac eu.org al.eu.org @@ -13103,7 +13421,6 @@ kr.eu.org lt.eu.org lu.eu.org lv.eu.org -mc.eu.org me.eu.org mk.eu.org mt.eu.org @@ -13113,10 +13430,8 @@ ng.eu.org nl.eu.org no.eu.org nz.eu.org -paris.eu.org pl.eu.org pt.eu.org -q-a.eu.org ro.eu.org ru.eu.org se.eu.org @@ -13146,10 +13461,16 @@ us-4.evennode.com relay.evervault.app relay.evervault.dev +// Exe : https://exe.dev +// Submitted by Josh Bleecher Snyder +exe.xyz + // Expo : https://expo.dev/ -// Submitted by James Ide +// Submitted by Phil Pluckthun expo.app +on.expo.app staging.expo.app +on.staging.expo.app // Fabrica Technologies, Inc. : https://www.fabrica.dev/ // Submitted by Eric Jiang @@ -13264,13 +13585,13 @@ fastvps.site myfast.space // FearWorks Media Ltd. : https://fearworksmedia.co.uk -// submitted by Keith Fairley +// Submitted by Keith Fairley conn.uk copro.uk hosp.uk // Fedora : https://fedoraproject.org/ -// submitted by Patrick Uiterwijk +// Submitted by Patrick Uiterwijk fedorainfracloud.org fedorapeople.org cloud.fedoraproject.org @@ -13278,13 +13599,20 @@ app.os.fedoraproject.org app.os.stg.fedoraproject.org // Fermax : https://fermax.com/ -// submitted by Koen Van Isterdael +// Submitted by Koen Van Isterdael mydobiss.com // FH Muenster : https://www.fh-muenster.de // Submitted by Robin Naundorf fh-muenster.io +// Figma : https://www.figma.com +// Submitted by Nick Frost +payload.dev +figma.site +figma-gov.site +preview.site + // Filegear Inc. : https://www.filegear.com // Submitted by Jason Zhu filegear.me @@ -13293,32 +13621,26 @@ filegear.me // Submitted by Chris Raynor firebaseapp.com -// Firewebkit : https://www.firewebkit.com -// Submitted by Majid Qureshi -fireweb.app - -// FLAP : https://www.flap.cloud -// Submitted by Louis Chemineau -flap.id - // FlashDrive : https://flashdrive.io // Submitted by Eric Chan fldrv.com +// Fleek Labs Inc : https://fleek.xyz +// Submitted by Parsa Ghadimi +on-fleek.app + // FlutterFlow : https://flutterflow.io // Submitted by Anton Emelyanov flutterflow.app -// fly.io: https://fly.io -// Submitted by Kurt Mackey +// fly.io : https://fly.io +// Submitted by Kurt Mackey +sprites.app fly.dev -shw.io -edgeapp.net -// Forgerock : https://www.forgerock.com -// Submitted by Roderick Parr -forgeblocks.com -id.forgerock.io +// FoundryLabs, Inc : https://e2b.dev/ +// Submitted by Jiri Sveceny +e2b.app // Framer : https://www.framer.com // Submitted by Koen Rouwhorst @@ -13330,9 +13652,9 @@ framer.photos framer.website framer.wiki -// Frederik Braun https://frederik-braun.com +// Frederik Braun : https://frederik-braun.com // Submitted by Frederik Braun -0e.vc +*.0e.vc // Freebox : http://www.freebox.fr // Submitted by Romain Fliedel @@ -13388,6 +13710,11 @@ futuremailing.at *.kunden.ortsinfo.at *.statics.cloud +// Gadget Software Inc. : https://gadget.dev +// Submitted by Harry Brundage +gadget.app +gadget.host + // GCom Internet : https://www.gcom.net.au // Submitted by Leo Julius aliases121.com @@ -13413,38 +13740,32 @@ usercontent.jp // Submitted by Tom Klein gentapps.com gentlentapis.com -lab.ms cdn-edges.net -// Getlocalcert: https://www.getlocalcert.net -// Submitted by Robert Alexander -localcert.net -localhostcert.net -corpnet.work - -// GignoSystemJapan: http://gsj.bz +// GignoSystemJapan : http://gsj.bz // Submitted by GignoSystemJapan gsj.bz +// GitBook Inc. : https://www.gitbook.com/ +// Submitted by Samy Pesse +gitbook.io + // GitHub, Inc. // Submitted by Patrick Toomey +github.app githubusercontent.com githubpreview.dev github.io -// GitLab, Inc. +// GitLab, Inc. : https://about.gitlab.com/ // Submitted by Alex Hanselka gitlab.io -// Gitplac.si - https://gitplac.si +// Gitplac.si : https://gitplac.si // Submitted by Aljaž Starc gitapp.si gitpage.si -// Glitch, Inc : https://glitch.com -// Submitted by Mads Hartmann -glitch.me - // Global NOG Alliance : https://nogalliance.org/ // Submitted by Sander Steffann nog.community @@ -13574,26 +13895,10 @@ goip.de // Google, Inc. // Submitted by Shannon McCabe -blogspot.ae -blogspot.al -blogspot.am *.hosted.app *.run.app +*.mtls.run.app web.app -blogspot.com.ar -blogspot.co.at -blogspot.com.au -blogspot.ba -blogspot.be -blogspot.bg -blogspot.bj -blogspot.com.br -blogspot.com.by -blogspot.ca -blogspot.cf -blogspot.ch -blogspot.cl -blogspot.com.co *.0emm.com appspot.com *.r.appspot.com @@ -13602,70 +13907,13 @@ codespot.com googleapis.com googlecode.com pagespeedmobilizer.com -publishproxy.com withgoogle.com withyoutube.com -blogspot.cv -blogspot.com.cy -blogspot.cz -blogspot.de *.gateway.dev -blogspot.dk -blogspot.com.ee -blogspot.com.eg -blogspot.com.es -blogspot.fi -blogspot.fr cloud.goog translate.goog *.usercontent.goog -blogspot.gr -blogspot.hk -blogspot.hr -blogspot.hu -blogspot.co.id -blogspot.ie -blogspot.co.il -blogspot.in -blogspot.is -blogspot.it -blogspot.jp -blogspot.co.ke -blogspot.kr -blogspot.li -blogspot.lt -blogspot.lu -blogspot.md -blogspot.mk -blogspot.mr -blogspot.com.mt -blogspot.mx -blogspot.my cloudfunctions.net -blogspot.com.ng -blogspot.nl -blogspot.no -blogspot.co.nz -blogspot.pe -blogspot.pt -blogspot.qa -blogspot.re -blogspot.ro -blogspot.rs -blogspot.ru -blogspot.se -blogspot.sg -blogspot.si -blogspot.sk -blogspot.sn -blogspot.td -blogspot.com.tr -blogspot.tw -blogspot.ug -blogspot.co.uk -blogspot.com.uy -blogspot.vn -blogspot.co.za // Goupile : https://goupile.fr // Submitted by Niels Martignene @@ -13680,36 +13928,39 @@ pymnt.uk cloudapps.digital london.cloudapps.digital -// Government of the Netherlands: https://www.government.nl +// Government of the Netherlands : https://www.government.nl // Submitted by gov.nl +// Grafana Labs : https://grafana.com/ +// Submitted by Platform Engineering +grafana-dev.net + // GrayJay Web Solutions Inc. : https://grayjaysports.ca // Submitted by Matt Yamkowy grayjayleagues.com +// Grebedoc : https://grebedoc.dev +// Submitted by Catherine Zotova +grebedoc.dev + // GünstigBestellen : https://günstigbestellen.de // Submitted by Furkan Akkoc günstigbestellen.de günstigliefern.de -// Hakaran group: http://hakaran.cz -// Submitted by Arseniy Sokolov -fin.ci -free.hr -caa.li -ua.rs -conf.se +// GV.UY : https://nic.gv.uy +// Submitted by cheng +gv.uy + +// Hackclub Nest : https://hackclub.app +// Submitted by Cyteon +hackclub.app -// Häkkinen.fi +// Häkkinen.fi : https://www.häkkinen.fi/ // Submitted by Eero Häkkinen häkkinen.fi -// Handshake : https://handshake.org -// Submitted by Mike Damm -hs.run -hs.zone - // Hashbang : https://hashbang.sh hashbang.sh @@ -13727,11 +13978,12 @@ hatenablog.jp hatenadiary.jp hatenadiary.org -// Heilbronn University of Applied Sciences - Faculty Informatics (GitLab Pages): https://www.hs-heilbronn.de -// Submitted by Richard Zowalla +// Heilbronn University of Applied Sciences - Faculty Informatics (GitLab Pages) : https://www.hs-heilbronn.de +// Submitted by Richard Zowalla pages.it.hs-heilbronn.de +pages-research.it.hs-heilbronn.de -// HeiyuSpace: https://lazycat.cloud +// HeiyuSpace : https://lazycat.cloud // Submitted by Xia Bin heiyu.space @@ -13744,10 +13996,20 @@ heliohost.us // Submitted by David Grellscheid hepforge.org +// Hercules : https://hercules.app +// Submitted by Brendan Falk +onhercules.app +hercules-app.com +hercules-dev.com + // Heroku : https://www.heroku.com/ -// Submitted by Tom Maher +// Submitted by Shumon Huque herokuapp.com -herokussl.com + +// Heyflow : https://www.heyflow.com +// Submitted by Mirko Nitschke +heyflow.page +heyflow.site // Hibernating Rhinos // Submitted by Oren Eini @@ -13756,7 +14018,12 @@ ravendb.community development.run ravendb.run -// home.pl S.A.: https://home.pl +// HiDNS : https://www.hidoha.net +// Submitted by ifeng +hidns.co +hidns.vip + +// home.pl S.A. : https://home.pl // Submitted by Krzysztof Wolski homesklep.pl @@ -13766,9 +14033,9 @@ homesklep.pl *.id.pub *.kin.pub -// Hong Kong Productivity Council: https://www.hkpc.org/ -// Submitted by SECaaS Team -secaas.hk +// HOOC AG : https://www.hooc.ch +// Submitted by Fabrizio Steiner +seprox.hooc.me // Hoplix : https://www.hoplix.com // Submitted by Danilo De Franco @@ -13777,22 +14044,27 @@ hoplix.shop // HOSTBIP REGISTRY : https://www.hostbip.com/ // Submitted by Atanunu Igbunuroghene orx.biz -biz.gl +biz.ng +co.biz.ng +dl.biz.ng +go.biz.ng +lg.biz.ng +on.biz.ng col.ng firm.ng gen.ng ltd.ng ngo.ng -edu.scot -sch.so +plc.ng -// HostFly : https://www.ie.ua -// Submitted by Bohdan Dub -ie.ua - -// HostyHosting (https://hostyhosting.com) +// HostyHosting : https://hostyhosting.com hostyhosting.io +// Hugging Face : https://huggingface.co +// Submitted by Eliott Coyac +hf.space +static.hf.space + // Hypernode B.V. : https://www.hypernode.com/ // Submitted by Cipriano Groenendal hypernode.io @@ -13818,12 +14090,17 @@ gr.com // Submitted by Hannu Aronsson iki.fi -// iliad italia: https://www.iliad.it +// iliad italia : https://www.iliad.it // Submitted by Marios Makassikis ibxos.it iliadboxos.it -// Incsub, LLC: https://incsub.com/ +// Imagine : https://imagine.dev +// Submitted by Steven Nguyen +imagine.diy +imagine-proxy.work + +// Incsub, LLC : https://incsub.com/ // Submitted by Aaron Edwards smushcdn.com wphostedmail.com @@ -13844,6 +14121,10 @@ in-vpn.net in-dsl.org in-vpn.org +// Inferno Communications : https://inferno.co.uk +// Submitted by Connor McFarlane +oninferno.net + // info.at : http://www.info.at/ biz.at info.at @@ -13886,15 +14167,25 @@ to.leg.br // Submitted by Wolfgang Schwarz pixolino.com -// Internet-Pro, LLP: https://netangels.ru/ +// Internet-Pro, LLP : https://netangels.ru/ // Submitted by Vasiliy Sheredeko na4u.ru -// IONOS SE : https://www.ionos.com/, -// IONOS Group SE: https://www.ionos-group.com/ -// submitted by Henrik Willert +// Inventor Services : https://inventor.gg/ +// Submitted by Inventor Team +botdash.app +botdash.dev +botdash.gg +botdash.net +botda.sh +botdash.xyz + +// IONOS SE : https://www.ionos.com/ +// IONOS Group SE : https://www.ionos-group.com/ +// Submitted by Henrik Willert apps-1and1.com live-website.com +webspace-host.com apps-1and1.net websitebuilder.online app-ionos.space @@ -13903,6 +14194,12 @@ app-ionos.space // Submitted by Roman Azarenko iopsys.se +// IPFS Project : https://ipfs.tech/ +// Submitted by Interplanetary Shipyard +*.inbrowser.dev +*.dweb.link +*.inbrowser.link + // IPiFony Systems, Inc. : https://www.ipifony.com/ // Submitted by Matthew Hardeman ipifony.net @@ -13911,28 +14208,29 @@ ipifony.net // Submitted by Ali Soizi ir.md -// is-a.dev : https://www.is-a.dev -// Submitted by William Harrison -is-a.dev - // is-a-good.dev : https://is-a-good.dev // Submitted by William Harrison is-a-good.dev // IServ GmbH : https://iserv.de -// Submitted by Mario Hoberg +// Submitted by Kim Brodowski iservschule.de mein-iserv.de +schuldock.de schulplattform.de schulserver.de test-iserv.de iserv.dev +iserv.host + +// Ispmanager : https://www.ispmanager.com/ +// Submitted by Ispmanager infrastructure team +ispmanager.name // Jelastic, Inc. : https://jelastic.com/ // Submitted by Ihor Kolodyuk mel.cloudlets.com.au cloud.interhostsolutions.be -mycloud.by alp1.ae.flow.ch appengine.flow.ch es-1.axarnet.cloud @@ -13954,7 +14252,6 @@ us.reclaim.cloud ch.trendhosting.cloud de.trendhosting.cloud jele.club -amscompute.com dopaas.com paas.hosted-by-previder.com rag-cloud.hosteur.com @@ -13962,10 +14259,8 @@ rag-cloud-ch.hosteur.com jcloud.ik-server.com jcloud-ver-jpc.ik-server.com demo.jelastic.com -kilatiron.com paas.massivegrid.com jed.wafaicloud.com -lon.wafaicloud.com ryd.wafaicloud.com j.scaleforce.com.cy jelastic.dogado.eu @@ -13977,18 +14272,14 @@ mircloud.host paas.beebyte.io sekd1.beebyteapp.io jele.io -cloud-fr1.unispace.io jc.neen.it -cloud.jelastic.open.tim.it jcloud.kz -upaas.kazteleport.kz cloudjiffy.net fra1-de.cloudjiffy.net west1-us.cloudjiffy.net jls-sto1.elastx.net jls-sto2.elastx.net jls-sto3.elastx.net -faststacks.net fr-1.paas.massivegrid.net lon-1.paas.massivegrid.net lon-2.paas.massivegrid.net @@ -13998,11 +14289,9 @@ sg-1.paas.massivegrid.net jelastic.saveincloud.net nordeste-idc.saveincloud.net j.scaleforce.net -jelastic.tsukaeru.net sdscloud.pl unicloud.pl mircloud.ru -jelastic.regruhosting.ru enscaled.sg jele.site jelastic.team @@ -14021,44 +14310,71 @@ myjino.ru // Jotelulu S.L. : https://jotelulu.com // Submitted by Daniel Fariña +jote.cloud jotelulu.cloud +eu1-plenit.com +la1-plenit.com +us1-plenit.com // JouwWeb B.V. : https://www.jouwweb.nl // Submitted by Camilo Sperberg webadorsite.com jouwweb.site -// Joyent : https://www.joyent.com/ -// Submitted by Brian Bennett -*.cns.joyent.com -*.triton.zone - // JS.ORG : http://dns.js.org // Submitted by Stefan Keim js.org +// K2 Cloud : https://k2.cloud/ +// Submitted by K2 Cloud +elastic.k2.cloud +lb.ru-msk.k2.cloud +s3.ru-msk.k2.cloud +website.ru-msk.k2.cloud +lb.ru-spb.k2.cloud +s3.ru-spb.k2.cloud +website.ru-spb.k2.cloud +s3.k2.cloud +website.k2.cloud + // KaasHosting : http://www.kaashosting.nl/ // Submitted by Wouter Bakker kaas.gg khplay.nl -// Kakao : https://www.kakaocorp.com/ -// Submitted by JaeYoong Lee -ktistory.com - // Kapsi : https://kapsi.fi // Submitted by Tomi Juntunen kapsi.fi -// Katholieke Universiteit Leuven: https://www.kuleuven.be +// KataBump : https://katabump.com +// Submitted by Thibault Lapeyre +kdns.fr + +// Katholieke Universiteit Leuven : https://www.kuleuven.be // Submitted by Abuse KU Leuven ezproxy.kuleuven.be kuleuven.cloud +// Keenetic : https://keenetic.com +// Submitted by Alexey Nikitin +keenetic.io +keenetic.link +keenetic.name +keenetic.pro + +// Kevin Service : https://kevsrv.me +// Submitted by Kevin Service Team +ae.kg + // Keyweb AG : https://www.keyweb.de // Submitted by Martin Dannehl keymachine.de +// Kilo Code, Inc. : https://kilo.ai +// Submitted by Remon Oldenbeuving +kiloapps.ai +kiloapps.io + // KingHost : https://king.host // Submitted by Felipe Keller Braz kinghost.net @@ -14068,7 +14384,7 @@ uni5.net // Submitted by Roy Keene knightpoint.systems -// KoobinEvent, SL: https://www.koobin.com +// KoobinEvent, SL : https://www.koobin.com // Submitted by Iván Oliva koobin.events @@ -14081,6 +14397,19 @@ krellian.net // Submitted by DisposaBoy oya.to +// KV GmbH : https://www.nic.co.de +// Submitted by KV GmbH +// Abuse reports to +co.de + +// Laravel Holdings, Inc. : https://laravel.com +// Submitted by André Valentin & James Brooks +shiptoday.app +shiptoday.build +laravel.cloud +on-forge.com +on-vapor.com + // LCube - Professional hosting e.K. : https://www.lcube-webhosting.de // Submitted by Lars Laehn git-repos.de @@ -14093,12 +14422,19 @@ leadpages.co lpages.co lpusercontent.com -// Lelux.fi : https://lelux.fi/ -// Submitted by Lelux Admin -lelux.site +// Leapcell : https://leapcell.io/ +// Submitted by Leapcell Team +leapcell.app +leapcell.dev +leapcell.online + +// Liara : https://liara.ir +// Submitted by Amirhossein Badinloo +liara.run +iran.liara.run // libp2p project : https://libp2p.io -// Submitted by Interplanetary Shipyard +// Submitted by Interplanetary Shipyard libp2p.direct // Libre IT Ltd : https://libre.nz @@ -14115,7 +14451,7 @@ co.network co.place co.technology -// linkyard ldt: https://www.linkyard.ch/ +// linkyard ldt : https://www.linkyard.ch/ // Submitted by Mario Siegenthaler linkyard-cloud.ch linkyard.cloud @@ -14140,6 +14476,20 @@ ggff.net // Submitted by Lann Martin *.user.localcert.dev +// Localtonet : https://localtonet.com/ +// Submitted by Burak Isleyici +localtonet.com +*.localto.net + +// Lodz University of Technology LODMAN regional domains : https://www.man.lodz.pl/dns +// Submitted by Piotr Wilk +lodz.pl +pabianice.pl +plock.pl +sieradz.pl +skierniewice.pl +zgierz.pl + // Log'in Line : https://www.loginline.com/ // Submitted by Rémi Mach loginline.app @@ -14148,13 +14498,16 @@ loginline.io loginline.services loginline.site -// Lõhmus Family, The -// Submitted by Heiki Lõhmus +// Lõhmus Family, The : https://lohmus.me/ +// Submitted by Heiki Lõhmus lohmus.me -// Lokalized : https://lokalized.nl -// Submitted by Noah Taheij -servers.run +// Lovable : https://lovable.dev +// Submitted by Fabian Hedin +lovable.app +lovableproject.com +lovable.run +lovable.sh // LubMAN UMCS Sp. z o.o : https://lubman.pl/ // Submitted by Ireneusz Maliszewski @@ -14204,19 +14557,28 @@ barsy.uk barsy.co.uk barsyonline.co.uk +// Lutra : https://lutra.ai +// Submitted by Joshua Newman +*.lutrausercontent.com + +// Luyani Inc. : https://luyani.com/ +// Submitted by Umut Gumeli +luyani.app +luyani.net + // Magento Commerce // Submitted by Damien Tournoud *.magentosite.cloud +// Magic Patterns : https://www.magicpatterns.com +// Submitted by Teddy Ni +magicpatterns.app +magicpatternsapp.com + // Mail.Ru Group : https://hb.cldmail.ru // Submitted by Ilya Zaretskiy hb.cldmail.ru -// May First - People Link : https://mayfirst.org/ -// Submitted by Jamie McClelland -mayfirst.info -mayfirst.org - // MathWorks : https://www.mathworks.com/ // Submitted by Emily Reed matlab.cloud @@ -14224,9 +14586,10 @@ modelscape.com mwcloudnonprod.com polyspace.com -// Maze Play: https://www.mazeplay.com -// Submitted by Adam Humpherys -mazeplay.com +// May First - People Link : https://mayfirst.org/ +// Submitted by Jamie McClelland +mayfirst.info +mayfirst.org // McHost : https://mchost.ru // Submitted by Evgeniy Subbotin @@ -14235,10 +14598,6 @@ mcdir.ru vps.mcdir.ru mcpre.ru -// mcpe.me : https://mcpe.me -// Submitted by Noa Heyl -mcpe.me - // Mediatech : https://mediatech.by // Submitted by Evgeniy Kozhuhovskiy mediatech.by @@ -14248,6 +14607,10 @@ mediatech.dev // Submitted by Michael Olson hra.health +// MedusaJS, Inc : https://medusajs.com/ +// Submitted by Stevche Radevski +medusajs.app + // Memset hosting : https://www.memset.com // Submitted by Tom Whitwell miniserver.com @@ -14263,12 +14626,9 @@ atmeta.com apps.fbsbx.com // MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ -// Submitted by Zdeněk Šustr +// Submitted by Zdeněk Šustr and Radim Janča *.cloud.metacentrum.cz custom.metacentrum.cz - -// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ -// Submitted by Radim Janča flt.cloud.muni.cz usr.cloud.muni.cz @@ -14305,23 +14665,54 @@ westus2.azurestaticapps.net azurewebsites.net cloudapp.net trafficmanager.net +blob.core.usgovcloudapi.net +file.core.usgovcloudapi.net +web.core.usgovcloudapi.net +servicebus.usgovcloudapi.net +usgovcloudapp.net +usgovtrafficmanager.net blob.core.windows.net +file.core.windows.net +web.core.windows.net servicebus.windows.net +azure-api.us +azurewebsites.us -// MikroTik: https://mikrotik.com +// MikroTik : https://mikrotik.com // Submitted by MikroTik SysAdmin Team routingthecloud.com sn.mynetname.net routingthecloud.net routingthecloud.org +// Million Software, Inc : https://million.dev/ +// Submitted by Rayhan Noufal Arayilakath +same-app.com +same-preview.com + // minion.systems : http://minion.systems // Submitted by Robert Böttinger csx.cc -// MobileEducation, LLC : https://joinforte.com -// Submitted by Grayson Martin -forte.id +// Miren, Inc. : https://miren.dev +// Submitted by Miren Product Team +miren.app +miren.systems + +// Mittwald CM Service GmbH & Co. KG : https://mittwald.de +// Submitted by Marco Rieger +mydbserver.com +webspaceconfig.de +mittwald.info +mittwaldserver.info +typo3server.info +project.space + +// Mocha : https://getmocha.com +// Submitted by Ben Reinhart +mocha.app +mochausercontent.com +mocha-sandbox.dev // MODX Systems LLC : https://modx.com // Submitted by Elizabeth Southwell @@ -14337,6 +14728,10 @@ net.ru org.ru pp.ru +// MyOwn srl : https://www.myown.eu/ +// Submitted by Stephane Bouvard +my.be + // Mythic Beasts : https://www.mythic-beasts.com // Submitted by Paul Cammish hostedpi.com @@ -14357,13 +14752,22 @@ cust.retrosnub.co.uk // Submitted by Paulus Schoutsen ui.nabu.casa +// Needle Tools GmbH : https://needle.tools +// Submitted by Felix Herbst +needle.run + +// Neo : https://www.neo.space +// Submitted by Ankit Kulkarni +co.site + // Net at Work Gmbh : https://www.netatwork.de // Submitted by Jan Jaeschke cloud.nospamproxy.com +o365.cloud.nospamproxy.com -// Netfy Domains : https://netfy.domains -// Submitted by Suranga Ranasinghe -netfy.app +// Net libre : https://www.netlib.re +// Submitted by Philippe PITTOLI +netlib.re // Netlify : https://www.netlify.com // Submitted by Jessica Parsons @@ -14402,7 +14806,7 @@ us.ngrok.io ngrok.pizza ngrok.pro -// Nicolaus Copernicus University in Torun - MSK TORMAN (https://www.man.torun.pl) +// Nicolaus Copernicus University in Torun - MSK TORMAN : https://www.man.torun.pl torun.pl // Nimbus Hosting Ltd. : https://www.nimbushosting.co.uk/ @@ -14410,15 +14814,6 @@ torun.pl nh-serv.co.uk nimsite.uk -// No longer operated by CentralNic, these entries should be adopted and/or removed by current operators -// Submitted by Gavin Brown -ar.com -hu.com -kr.com -no.com -qc.com -uy.com - // No-IP.com : https://noip.com/ // Submitted by Deven Reza mmafan.biz @@ -14524,6 +14919,35 @@ noop.app *.database.run *.migration.run +// Northwest Nexus dba NuOz : https://nuoz.net/ +// An RFC 1480 locality domain delegate host +// Submitted by Peter Briggs on behalf of NuOz +aberdeen.wa.us +bainbridge-isl.wa.us +bellevue.wa.us +bremerton.wa.us +centralia.wa.us +chehalis.wa.us +forks.wa.us +gig-harbor.wa.us +hoquiam.wa.us +keyport.wa.us +kingston.wa.us +olympia.wa.us +port-angeles.wa.us +port-ludlow.wa.us +port-orchard.wa.us +port-townsend.wa.us +poulsbo.wa.us +redmond.wa.us +renton.wa.us +sea.wa.us +seattle.wa.us +sequim.wa.us +shelton.wa.us +silverdale.wa.us +yarrow-point.wa.us + // Noticeable : https://noticeable.io // Submitted by Laurent Pellegrino noticeable.news @@ -14536,14 +14960,8 @@ notion.site // Submitted by Steve Russell dnsking.ch mypi.co -n4t.co -001www.com -ddnslive.com myiphost.com forumz.info -16-b.it -32-b.it -64-b.it soundcast.me tcp4.me dnsup.net @@ -14554,35 +14972,24 @@ vpndns.net dynserv.org now-dns.org x443.pw -now-dns.top ntdll.top freeddns.us -crafting.xyz -zapto.xyz // nsupdate.info : https://www.nsupdate.info/ // Submitted by Thomas Waldmann nsupdate.info nerdpol.ovh -// NYC.mn : http://www.information.nyc.mn -// Submitted by Matthew Brown -nyc.mn - // O3O.Foundation : https://o3o.foundation/ -// Submitted by the prvcy.page Registry Team +// Submitted by the prvcy.page Registry Team prvcy.page -// Obl.ong : -// Submitted by Reese Armstrong -obl.ong - // Observable, Inc. : https://observablehq.com // Submitted by Mike Bostock observablehq.cloud static.observableusercontent.com -// OMG.LOL : +// OMG.LOL : https://omg.lol // Submitted by Adam Newbold omg.lol @@ -14590,11 +14997,11 @@ omg.lol // Submitted by Cole Estep cloudycluster.net -// OmniWe Limited: https://omniwe.com +// OmniWe Limited : https://omniwe.com // Submitted by Vicary Archangel omniwe.site -// One.com: https://www.one.com/ +// One.com : https://www.one.com/ // Submitted by Jacob Bunk Nielsen 123webseite.at 123website.be @@ -14612,10 +15019,15 @@ simplesite.gr 123website.nl 123hjemmeside.no service.one +website.one simplesite.pl 123paginaweb.pt 123minsida.se +// ONID : https://get.onid.ca +// Submitted by ONID Engineering Team +onid.ca + // Open Domains : https://open-domains.net // Submitted by William Harrison is-a-fullstack.dev @@ -14628,11 +15040,21 @@ is-local.org // Submitted by Alexander Varwijk opensocial.site +// OpenAI : https://openai.com +// Submitted by Thomas Shadwell +*.oaiusercontent.com + // OpenCraft GmbH : http://opencraft.com/ // Submitted by Sven Marnach opencraft.hosting -// OpenResearch GmbH: https://openresearch.com/ +// OpenHost : https://registry.openhost.uk +// Submitted by OpenHost Registry Team +16-b.it +32-b.it +64-b.it + +// OpenResearch GmbH : https://openresearch.com/ // Submitted by Philipp Schmid orsites.com @@ -14640,31 +15062,41 @@ orsites.com // Submitted by Yngve Pettersen operaunite.com +// Oracle Dyn : https://cloud.oracle.com/home https://dyn.com/dns/ +// Submitted by Gregory Drake +// Note: This is intended to also include customer-oci.com due to wildcards implicitly including the current label +*.customer-oci.com +*.oci.customer-oci.com +*.ocp.customer-oci.com +*.ocs.customer-oci.com +*.oraclecloudapps.com +*.oraclegovcloudapps.com +*.oraclegovcloudapps.uk + // Orange : https://www.orange.com // Submitted by Alexandre Linte tech.orange // OsSav Technology Ltd. : https://ossav.com/ -// TLD Nic: http://nic.can.re - TLD Whois Server: whois.can.re // Submitted by OsSav Technology Ltd. +// https://nic.can.re can.re -// Oursky Limited : https://authgear.com/, https://skygear.io/ -// Submitted by Authgear Team , Skygear Developer +// Oursky Limited : https://authgear.com/ +// Submitted by Authgear Team & Skygear Developer authgear-staging.com authgearapps.com -skygearapp.com // OutSystems // Submitted by Duarte Santos outsystemscloud.com -// OVHcloud: https://ovhcloud.com +// OVHcloud : https://ovhcloud.com // Submitted by Vincent Cassé *.hosting.ovh.net *.webpaas.ovh.net -// OwnProvider GmbH: http://www.ownprovider.com +// OwnProvider GmbH : http://www.ownprovider.com // Submitted by Jan Moennich ownprovider.com own.pm @@ -14685,10 +15117,6 @@ oy.lc // Submitted by Derek Myers pgfog.com -// PageXL : https://pagexl.com -// Submitted by Yann Guichard -pagexl.com - // Pantheon Systems, Inc. : https://pantheon.io/ // Submitted by Gary Dylina gotpantheon.com @@ -14698,7 +15126,7 @@ pantheonsite.io // Submitted by Daniel Netzer *.paywhirl.com -// pcarrier.ca Software Inc: https://pcarrier.ca/ +// pcarrier.ca Software Inc : https://pcarrier.ca/ // Submitted by Pierre Carrier *.xmit.co xmit.dev @@ -14707,18 +15135,27 @@ srv.us gh.srv.us gl.srv.us -// PE Ulyanov Kirill Sergeevich : https://airy.host -// Submitted by Kirill Ulyanov -lk3.ru - // Peplink | Pepwave : http://peplink.com/ // Submitted by Steve Leung mypep.link +// Perplexity AI : https://www.perplexity.ai/ +// Submitted by Alec Xiang +pplx.app + // Perspecta : https://perspecta.com/ // Submitted by Kenneth Van Alstyne perspecta.cloud +// Ping Identity : https://www.pingidentity.com +// Submitted by Ping Identity +forgeblocks.com +id.forgerock.io + +// Plain : https://www.plain.com/ +// Submitted by Jesús Hernández +support.site + // Planet-Work : https://www.planet-work.com/ // Submitted by Frédéric VANNIÈRE on-web.fr @@ -14733,20 +15170,10 @@ us.platform.sh *.platformsh.site *.tst.site -// Platter: https://platter.dev -// Submitted by Patrick Flor -platter-app.com -platter-app.dev -platterp.us - // Pley AB : https://www.pley.com/ // Submitted by Henning Pohl pley.games -// Port53 : https://port53.io/ -// Submitted by Maximilian Schieder -dyn53.io - // Porter : https://porter.run/ // Submitted by Rudraksh MK onporter.run @@ -14774,30 +15201,52 @@ xen.prgmr.com // Submitted by registry priv.at -// Protocol Labs : https://protocol.ai/ -// Submitted by Michael Burns -*.dweb.link +// PROJECT ELIV : https://eliv.kr/ +// Submitted by PROJECT ELIV DomainName Team +c01.kr +eliv-api.kr +eliv-cdn.kr +eliv-dns.kr +mmv.kr +vki.kr + +// project-study : https://project-study.com +// Submitted by yumenewa +dev.project-study.com // Protonet GmbH : http://protonet.io // Submitted by Martin Meier protonet.io +// PSL Sandbox : https://github.com/groundcat/PSL-Sandbox +// Submitted by groundcat +platter-app.dev + +// PT Ekossistim Indo Digital : https://e.id +// Submitted by Eid Team +e.id + // Publication Presse Communication SARL : https://ppcom.fr // Submitted by Yaacov Akiba Slama chirurgiens-dentistes-en-france.fr byen.site -// pubtls.org: https://www.pubtls.org +// PublicZone : https://publiczone.org/ +// Submitted by PublicZone NOC Team +nyc.mn +*.cn.st + +// pubtls.org : https://www.pubtls.org // Submitted by Kor Nielsen pubtls.org -// PythonAnywhere LLP: https://www.pythonanywhere.com +// PythonAnywhere LLP : https://www.pythonanywhere.com // Submitted by Giles Thomas pythonanywhere.com eu.pythonanywhere.com // QA2 -// Submitted by Daniel Dent (https://www.danieldent.com/) +// Submitted by Daniel Dent : https://www.danieldent.com/ qa2.com // QCX @@ -14822,11 +15271,16 @@ qoto.io // Submitted by Xavier De Cock qualifioapp.com -// Quality Unit: https://qualityunit.com +// Quality Unit : https://qualityunit.com // Submitted by Vasyl Tsalko ladesk.com -// QuickBackend: https://www.quickbackend.com +// Qualy : https://qualyhq.com +// Submitted by Raphael Arias +*.qualyhqpartner.com +*.qualyhqportal.com + +// QuickBackend : https://www.quickbackend.com // Submitted by Dani Biro qbuser.com @@ -14844,7 +15298,7 @@ vaporcloud.io rackmaze.com rackmaze.net -// Rad Web Hosting: https://radwebhosting.com +// Rad Web Hosting : https://radwebhosting.com // Submitted by Scott Claeys cloudsite.builders myradweb.net @@ -14860,6 +15314,10 @@ in.net myrdbx.io site.rb-hosting.io +// Railway Corporation : https://railway.com +// Submitted by Phineas Walton +up.railway.app + // Rancher Labs, Inc : https://rancher.com // Submitted by Vincent Fiduccia *.on-rancher.cloud @@ -14879,10 +15337,15 @@ readthedocs.io // Submitted by Tim Kramer rhcloud.com -// Redgate Software: https://red-gate.com +// Redgate Software : https://red-gate.com // Submitted by Andrew Farries instances.spawn.cc +// Redpanda Data : https://redpanda.com +// Submitted by Infrastructure Team +*.clusters.rdpa.co +*.srvrless.rdpa.co + // Render : https://render.com // Submitted by Anurag Goel onrender.com @@ -14947,6 +15410,11 @@ itcouldbewor.se aus.basketball nz.basketball +// ROBOT PAYMENT INC. : https://www.robotpayment.co.jp/ +// Submitted by Kentaro Takamori +subsc-pay.com +subsc-pay.net + // Rochester Institute of Technology : http://www.rit.edu/ // Submitted by Jennifer Herting git-pages.rit.edu @@ -14955,7 +15423,13 @@ git-pages.rit.edu // Submitted by Neil Hanlon rocky.page -// Rusnames Limited: http://rusnames.ru/ +// Ruhr University Bochum : https://www.ruhr-uni-bochum.de/ +// Submitted by Andreas Jobs +rub.de +ruhr-uni-bochum.de +io.noc.ruhr-uni-bochum.de + +// Rusnames Limited : http://rusnames.ru/ // Submitted by Sergey Zotov биз.рус ком.рус @@ -14972,6 +15446,10 @@ rocky.page // Submitted by Tech Support ras.ru +// Sakura Frp : https://www.natfrp.com +// Submitted by Bobo Liu +nyat.app + // SAKURA Internet Inc. : https://www.sakura.ad.jp/ // Submitted by Internet Service Department 180r.com @@ -15022,13 +15500,26 @@ x0.to from.tv sakura.tv -// Salesforce.com, Inc. https://salesforce.com/ +// Salesforce.com, Inc. : https://salesforce.com/ // Submitted by Salesforce Public Suffix List Team *.builder.code.com *.dev-builder.code.com *.stg-builder.code.com *.001.test.code-builder-stg.platform.salesforce.com +*.aa.crm.dev +*.ab.crm.dev +*.ac.crm.dev +*.ad.crm.dev +*.ae.crm.dev +*.af.crm.dev +*.ci.crm.dev *.d.crm.dev +*.pa.crm.dev +*.pb.crm.dev +*.pc.crm.dev +*.pd.crm.dev +*.pe.crm.dev +*.pf.crm.dev *.w.crm.dev *.wa.crm.dev *.wb.crm.dev @@ -15041,38 +15532,63 @@ sakura.tv // Submitted by Asheesh Laroia sandcats.io +// Sav.com, LLC : https://marketing.sav.com/ +// Submitted by Mukul Kudegave +sav.case + // SBE network solutions GmbH : https://www.sbe.de/ // Submitted by Norman Meilick logoip.com logoip.de // Scaleway : https://www.scaleway.com/ -// Submitted by Rémy Léone +// Submitted by Scaleway PSL Maintainer fr-par-1.baremetal.scw.cloud fr-par-2.baremetal.scw.cloud nl-ams-1.baremetal.scw.cloud cockpit.fr-par.scw.cloud +ddl.fr-par.scw.cloud +dtwh.fr-par.scw.cloud fnc.fr-par.scw.cloud functions.fnc.fr-par.scw.cloud +ifr.fr-par.scw.cloud k8s.fr-par.scw.cloud nodes.k8s.fr-par.scw.cloud +kafk.fr-par.scw.cloud +mgdb.fr-par.scw.cloud +rdb.fr-par.scw.cloud s3.fr-par.scw.cloud s3-website.fr-par.scw.cloud +scbl.fr-par.scw.cloud whm.fr-par.scw.cloud priv.instances.scw.cloud pub.instances.scw.cloud k8s.scw.cloud cockpit.nl-ams.scw.cloud +ddl.nl-ams.scw.cloud +dtwh.nl-ams.scw.cloud +ifr.nl-ams.scw.cloud k8s.nl-ams.scw.cloud nodes.k8s.nl-ams.scw.cloud +kafk.nl-ams.scw.cloud +mgdb.nl-ams.scw.cloud +rdb.nl-ams.scw.cloud s3.nl-ams.scw.cloud s3-website.nl-ams.scw.cloud +scbl.nl-ams.scw.cloud whm.nl-ams.scw.cloud cockpit.pl-waw.scw.cloud +ddl.pl-waw.scw.cloud +dtwh.pl-waw.scw.cloud +ifr.pl-waw.scw.cloud k8s.pl-waw.scw.cloud nodes.k8s.pl-waw.scw.cloud +kafk.pl-waw.scw.cloud +mgdb.pl-waw.scw.cloud +rdb.pl-waw.scw.cloud s3.pl-waw.scw.cloud s3-website.pl-waw.scw.cloud +scbl.pl-waw.scw.cloud scalebook.scw.cloud smartlabeling.scw.cloud dedibox.fr @@ -15081,7 +15597,7 @@ dedibox.fr // Submitted by Hanno Böck schokokeks.net -// Scottish Government: https://www.gov.scot +// Scottish Government : https://www.gov.scot // Submitted by Martin Ellis gov.scot service.gov.scot @@ -15115,7 +15631,7 @@ seidat.net // Submitted by Yuriy Romadin sellfy.store -// Sendmsg: https://www.sendmsg.co.il +// Sendmsg : https://www.sendmsg.co.il // Submitted by Assaf Stern minisite.ms @@ -15123,14 +15639,10 @@ minisite.ms // Submitted by Felix Mönckemeyer senseering.net -// Servebolt AS: https://servebolt.com +// Servebolt AS : https://servebolt.com // Submitted by Daniel Kjeserud servebolt.cloud -// Service Magnet : https://myservicemagnet.com -// Submitted by Dave Sanders -magnet.page - // Service Online LLC : http://drs.ua/ // Submitted by Serhii Bulakh biz.ua @@ -15145,10 +15657,6 @@ as.sh.cn // Submitted by Nyoom sheezy.games -// ShiftEdit : https://shiftedit.net/ -// Submitted by Adam Jimenez -shiftedit.io - // Shopblocks : http://www.shopblocks.com/ // Submitted by Alex Bowers myshopblocks.com @@ -15163,6 +15671,7 @@ shopitsite.com // shopware AG : https://shopware.com // Submitted by Jens Küper +shopware.shop shopware.store // Siemens Mobility GmbH @@ -15181,17 +15690,11 @@ vipsinaapp.com // Submitted by Skylar Challand siteleaf.net -// Skyhat : http://www.skyhat.io -// Submitted by Shante Adam -bounty-full.com -alpha.bounty-full.com -beta.bounty-full.com - // Small Technology Foundation : https://small-tech.org // Submitted by Aral Balkan small-web.org -// Smallregistry by Promopixel SARL: https://www.smallregistry.net +// Smallregistry by Promopixel SARL : https://www.smallregistry.net // Former AFNIC's SLDs // Submitted by Jérôme Lipowicz aeroport.fr @@ -15224,6 +15727,10 @@ try-snowplow.com // Submitted by Michal Zalewski mafelo.net +// Solana Name Service : https://sns.id +// Submitted by Solana Name Service +sol.site + // Sony Interactive Entertainment LLC : https://sie.com/ // Submitted by David Coles playstation-cloud.com @@ -15237,15 +15744,19 @@ srht.site apps.lair.io *.stolos.io -// SpaceKit : https://www.spacekit.io/ -// Submitted by Reza Akhavan -spacekit.io +// sourceWAY GmbH : https://sourceway.de +// Submitted by Richard Reiber +4.at +my.at +my.de +*.nxa.eu +nx.gw -// SparrowHost : https://sparrowhost.in/ -// Submitted by Anant Pandey -ind.mom +// Spawnbase : https://spawnbase.ai +// Submitted by Alexander Zuev +spawnbase.app -// SpeedPartner GmbH: https://www.speedpartner.de/ +// SpeedPartner GmbH : https://www.speedpartner.de/ // Submitted by Stefan Neufeind customer.speedpartner.de @@ -15272,23 +15783,29 @@ myspreadshop.se myspreadshop.co.uk // StackBlitz : https://stackblitz.com -// Submitted by Dominic Elm +// Submitted by Dominic Elm & Albert Pai w-corp-staticblitz.com w-credentialless-staticblitz.com w-staticblitz.com +bolt.host // Stackhero : https://www.stackhero.io // Submitted by Adrien Gillon stackhero-network.com -// STACKIT : https://www.stackit.de/en/ -// Submitted by STACKIT-DNS Team (Simon Stier) +// STACKIT GmbH & Co. KG : https://www.stackit.de/en/ +// Submitted by STACKIT-DNS Team (Simon Stier) runs.onstackit.cloud stackit.gg stackit.rocks stackit.run stackit.zone +// Stackryze : https://stackryze.com +// Submitted by Sudheer Bhuvana +sryze.cc +indevs.in + // Staclar : https://staclar.com // Submitted by Q Misell // Submitted by Matthias Merkel @@ -15299,6 +15816,10 @@ novecore.site // Submitted by Jacob Lee api.stdlib.com +// statichost.eu : https://www.statichost.eu +// Submitted by Eric Selin +statichost.page + // stereosense GmbH : https://www.involve.me // Submitted by Florian Burmann feedback.ac @@ -15312,14 +15833,15 @@ researched.cx tests.cx surveys.so +// Storacha Network : https://storacha.network +// Submitted by Alan Shaw +ipfs.storacha.link +ipfs.w3s.link + // Storebase : https://www.storebase.io // Submitted by Tony Schirmer storebase.store -// Storipress : https://storipress.com -// Submitted by Benno Liu -storipress.app - // Storj Labs Inc. : https://storj.io/ // Submitted by Philip Hutchins storj.farm @@ -15329,7 +15851,7 @@ storj.farm strapiapp.com media.strapiapp.com -// Strategic System Consulting (eApps Hosting): https://www.eapps.com/ +// Strategic System Consulting (eApps Hosting) : https://www.eapps.com/ // Submitted by Alex Oancea vps-host.net atl.jelastic.vps-host.net @@ -15351,21 +15873,18 @@ user.srcf.net // Submitted by Silke Hofstra utwente.io -// Sub 6 Limited: http://www.sub6.com +// Sub 6 Limited : http://www.sub6.com // Submitted by Dan Miller temp-dns.com // Supabase : https://supabase.io -// Submitted by Inian Parameshwaran +// Submitted by Supabase Security supabase.co +realtime.supabase.co +storage.supabase.co supabase.in supabase.net -// Symfony, SAS : https://symfony.com/ -// Submitted by Fabien Potencier -*.sensiosite.cloud -*.s5y.io - // Syncloud : https://syncloud.org // Submitted by Boris Rybalkin syncloud.it @@ -15399,27 +15918,48 @@ tabitorder.co.il // Submitted by Bjoern Henke taifun-dns.de +// Tailor Inc. : https://www.tailor.tech +// Submitted by Ryuzo Yamamoto +erp.dev +web.erp.dev + // Tailscale Inc. : https://www.tailscale.com -// Submitted by David Anderson -beta.tailscale.net +// Submitted by David Anderson ts.net *.c.ts.net -// TASK geographical domains (https://www.task.gda.pl/uslugi/dns) +// TASK geographical domains : https://task.gda.pl/en/services/for-entrepreneurs/ gda.pl gdansk.pl gdynia.pl med.pl sopot.pl +// Tave Creative Corp : https://tave.com/ +// Submitted by Adrian Ziemkowski +taveusercontent.com + // tawk.to, Inc : https://www.tawk.to // Submitted by tawk.to developer team p.tawk.email p.tawkto.email -// team.blue https://team.blue -// Submitted by Cedric Dubois +// Tche.br : https://tche.br +// Submitted by Bruno Lorensi +tche.br + +// team.blue : https://team.blue +// Submitted by Cedric Dubois site.tb-hosting.com +directwp.eu + +// TechEdge Limited: https://www.nic.uk.cc/ +// Submitted by TechEdge Developer +ec.cc +eu.cc +gu.cc +uk.cc +us.cc // Teckids e.V. : https://www.teckids.org // Submitted by Dominik George @@ -15432,6 +15972,10 @@ telebit.app telebit.io *.telebit.xyz +// Teleport : https://goteleport.com +// Submitted by Rob Picard +teleport.sh + // Thingdust AG : https://thingdust.com/ // Submitted by Adrian Imboden *.firenet.ch @@ -15463,7 +16007,6 @@ pages.torproject.net // TownNews.com : http://www.townnews.com // Submitted by Dustin Ward -bloxcms.com townnews-staging.com // TrafficPlex GmbH : https://www.trafficplex.de/ @@ -15489,46 +16032,34 @@ webspace.rocks lima.zone // TransIP : https://www.transip.nl -// Submitted by Rory Breuk +// Submitted by Rory Breuk and Cedric Dubois *.transurl.be *.transurl.eu +site.transip.me *.transurl.nl -// TransIP: https://www.transip.nl -// Submitted by Cedric Dubois -site.transip.me +// Triton Data Center project : https://tritondatacenter.com +// Submitted by Triton Data Center staff +*.triton.zone + +// Tunnelmole: https://tunnelmole.com +// Submitted by Robbie Cahill +tunnelmole.net // TuxFamily : http://tuxfamily.org // Submitted by TuxFamily administrators tuxfamily.org -// TwoDNS : https://www.twodns.de/ -// Submitted by TwoDNS-Support -dd-dns.de -dray-dns.de -draydns.de -dyn-vpn.de -dynvpn.de -mein-vigor.de -my-vigor.de -my-wan.de -syno-ds.de -synology-diskstation.de -synology-ds.de -diskstation.eu -diskstation.org - // Typedream : https://typedream.com // Submitted by Putri Karunia typedream.app // Typeform : https://www.typeform.com -// Submitted by Sergi Ferriz +// Submitted by Typeform pro.typeform.com // Uberspace : https://uberspace.de // Submitted by Moritz Werner -*.uberspace.de uber.space // UDR Limited : http://www.udr.hk.com @@ -15542,6 +16073,10 @@ hk.org // Submitted by ITComdomains it.com +// Umso Software Inc. : https://www.umso.com +// Submitted by Alexis Taylor +umso.co + // Unison Computing, PBC : https://unison.cloud // Submitted by Simon Højberg unison-services.cloud @@ -15551,6 +16086,10 @@ unison-services.cloud virtual-user.de virtualuser.de +// United States Writing Corporation : https://uswriting.co +// Submitted by Andrew Sampson +obj.ag + // UNIVERSAL DOMAIN REGISTRY : https://www.udr.org.yt/ // see also: whois -h whois.udr.org.yt help // Submitted by Atanunu Igbunuroghene @@ -15565,14 +16104,10 @@ org.yt // Submitted by Marko Ivanovic rs.ba -// University of Bielsko-Biala regional domain: http://dns.bielsko.pl/ +// University of Bielsko-Biala regional domain : http://dns.bielsko.pl/ // Submitted by Marcin bielsko.pl -// Upli : https://upli.io -// Submitted by Lenny Bakkalian -upli.io - // urown.net : https://urown.net // Submitted by Hostmaster urown.cloud @@ -15582,34 +16117,46 @@ dnsupdate.info // Submitted by Gavin Brown us.org -// V.UA Domain Administrator : https://domain.v.ua/ -// Submitted by Serhii Rostilo +// V.UA Domain Registry: https://www.v.ua/ +// Submitted by Serhii Rostilo v.ua // Val Town, Inc : https://val.town/ // Submitted by Tom MacWright -express.val.run +val.run web.val.run // Vercel, Inc : https://vercel.com/ -// Submitted by Connor Davis +// Submitted by Laurens Duijvesteijn vercel.app +v0.build vercel.dev +vusercontent.net +vercel.run now.sh // VeryPositive SIA : http://very.lv // Submitted by Danko Aleksejevs 2038.io -// Viprinet Europe GmbH : http://www.viprinet.com -// Submitted by Simon Kissel -router.management - // Virtual-Info : https://www.virtual-info.info/ // Submitted by Adnan RIHAN v-info.info -// Voorloper.com: https://voorloper.com +// VistaBlog : https://vistablog.ir/ +// Submitted by Hossein Piri +vistablog.ir + +// Viva Republica, Inc. : https://toss.im/ +// Submitted by Deus Team +deus-canvas.com + +// vivenu GmbH : https://vivenu.com/ +// Submitted by Marvin Frick +vivenushop.com +vivenushop.dev + +// Voorloper.com : https://voorloper.com // Submitted by Nathan van Bakel voorloper.cloud @@ -15621,16 +16168,24 @@ voorloper.cloud // Submitted by Masayuki Note wafflecell.com +// Walrus : https://walrus.xyz +// Submitted by Max Spector +wal.app + +// Wasmer: https://wasmer.io +// Submitted by Lorentz Kinde +wasmer.app + // Webflow, Inc. : https://www.webflow.com // Submitted by Webflow Security Team webflow.io webflowtest.io -// WebHare bv: https://www.webhare.com/ +// WebHare bv : https://www.webhare.com/ // Submitted by Arnold Hendriks *.webhare.dev -// WebHotelier Technologies Ltd: https://www.webhotelier.net/ +// WebHotelier Technologies Ltd : https://www.webhotelier.net/ // Submitted by Apostolos Tsakpinis bookonline.app hotelwithflight.com @@ -15644,9 +16199,10 @@ pleskns.com wp2.host pdns.page plesk.page +cpanel.site wpsquared.site -// WebWaddle Ltd: https://webwaddle.com/ +// WebWaddle Ltd : https://webwaddle.com/ // Submitted by Merlin Glander *.wadl.top @@ -15662,15 +16218,29 @@ box.ca // Submitted by Kidd Hustle pages.wiardweb.com -// Wikimedia Labs : https://wikitech.wikimedia.org -// Submitted by Arturo Borrero Gonzalez +// Wikimedia Foundation : https://wikitech.wikimedia.org +// Submitted by Timo Tijhof toolforge.org wmcloud.org +beta.wmcloud.org wmflabs.org -// William Harrison : https://wdharrison.com -// Submitted by William Harrison -wdh.app +// William Harrison : https://wharrison.com.au +// Submitted by William Harrison +vps.hrsn.au +hrsn.dev +is-a.dev +localcert.net + +// Windsurf : https://windsurf.com +// Submitted by Douglas Chen +windsurf.app +windsurf.build + +// WirelessCar : https://wirelesscar.com +// Submitted by Martin Lindberg +drive-platform.com +drive-platform.io // WISP : https://wisp.gg // Submitted by Stepan Fedotov @@ -15679,6 +16249,8 @@ daemon.panel.gg // Wix.com, Inc. : https://www.wix.com // Submitted by Shahar Talmi / Alon Kochba +base44.app +base44-sandbox.com wixsite.com wixstudio.com editorx.io @@ -15710,8 +16282,9 @@ weeklylottery.org.uk wpenginepowered.com js.wpenginepowered.com -// XenonCloud GbR: https://xenoncloud.net +// XenonCloud GbR : https://xenoncloud.net // Submitted by Julian Uphoff +*.xenonconnect.de half.host // XnBay Technology : http://www.xnbay.com/ @@ -15726,11 +16299,16 @@ cistron.nl demon.nl xs4all.space -// Yandex.Cloud LLC: https://cloud.yandex.com +// xTool : https://xtool.com +// Submitted by Echo +xtooldevice.com + +// Yandex.Cloud LLC : https://cloud.yandex.com // Submitted by Alexander Lodin yandexcloud.net storage.yandexcloud.net website.yandexcloud.net +sourcecraft.site // YesCourse Pty Ltd : https://yescourse.com // Submitted by Atul Bhouraskar @@ -15740,16 +16318,6 @@ official.academy // Submitted by Stefano Rivera yolasite.com -// Yombo : https://yombo.net -// Submitted by Mitch Schwenk -ybo.faith -yombo.me -homelink.one -ybo.party -ybo.review -ybo.science -ybo.trade - // Yunohost : https://yunohost.org // Submitted by Valentin Grimaud ynh.fr @@ -15769,6 +16337,10 @@ zap.cloud // Submitted by Zeabur Team zeabur.app +// Zerops : https://zerops.io/ +// Submitted by Zerops Team +*.zerops.app + // Zine EOOD : https://zine.bg/ // Submitted by Martin Angelov bss.design @@ -15779,4 +16351,13 @@ basicserver.io virtualserver.io enterprisecloud.nu +// Zone.ID: https://zone.id +// Submitted by Gx1.org +zone.id +nett.to + +// ZoneABC : https://zoneabc.net +// Submitted by ZoneABC Team +zabc.net + // ===END PRIVATE DOMAINS=== diff --git a/pom.xml b/pom.xml index 500413c26e..8574ee1c55 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ org.apache.httpcomponents.client5 httpclient5-parent Apache HttpComponents Client - 5.6.1-SNAPSHOT + 5.6.2-SNAPSHOT Apache HttpComponents Client is a library of components for building client side HTTP services https://hc.apache.org/httpcomponents-client-5.5.x/${project.version}/ 1999 @@ -48,7 +48,7 @@ scm:git:https://gitbox.apache.org/repos/asf/httpcomponents-client.git scm:git:https://gitbox.apache.org/repos/asf/httpcomponents-client.git https://github.com/apache/httpcomponents-client/tree/${project.scm.tag} - 5.6.1-SNAPSHOT + 5.6.2-SNAPSHOT From a922d943da7c84aaedf582c389aaa0aaf653ee14 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Sat, 25 Apr 2026 09:42:46 +0200 Subject: [PATCH 35/36] HTTPCLIENT-2419: corrected website component URL --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8574ee1c55..b7c4a4c865 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ Apache HttpComponents Client 5.6.2-SNAPSHOT Apache HttpComponents Client is a library of components for building client side HTTP services - https://hc.apache.org/httpcomponents-client-5.5.x/${project.version}/ + https://hc.apache.org/httpcomponents-client-5.6.x/${project.version}/ 1999 pom @@ -55,7 +55,7 @@ apache.website Apache HttpComponents Website - scm:svn:https://svn.apache.org/repos/asf/httpcomponents/site/components/httpcomponents-client-5.5.x/LATEST/ + scm:svn:https://svn.apache.org/repos/asf/httpcomponents/site/components/httpcomponents-client-5.6.x/LATEST/ From 869a8dc91e2716572ea6f8798757afb93a44b586 Mon Sep 17 00:00:00 2001 From: Arturo Bernal Date: Wed, 27 May 2026 07:07:23 +0200 Subject: [PATCH 36/36] HTTPCLIENT-2422: Restore lazy content decompression Defer construction of the decompression stream until the response content is actually read. (cherry picked from commit 4b0cbd4bf94a92b703985630aa42144eed20402c) --- .../entity/compress/DecompressingEntity.java | 69 ++++++++++++++++++- .../http/entity/TestDecompressingEntity.java | 24 +++++++ 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/compress/DecompressingEntity.java b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/compress/DecompressingEntity.java index 070663ccc2..38b00a3aca 100644 --- a/httpclient5/src/main/java/org/apache/hc/client5/http/entity/compress/DecompressingEntity.java +++ b/httpclient5/src/main/java/org/apache/hc/client5/http/entity/compress/DecompressingEntity.java @@ -27,9 +27,11 @@ package org.apache.hc.client5.http.entity.compress; +import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; + import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.io.entity.HttpEntityWrapper; import org.apache.hc.core5.io.IOFunction; @@ -48,19 +50,23 @@ public DecompressingEntity( this.decoder = Args.notNull(decoder, "Stream decoder"); } + private InputStream getDecompressingStream() throws IOException { + return new LazyDecompressingInputStream(super.getContent(), decoder); + } + /** * Returns the cached decoded stream, creating it once if necessary. */ @Override public InputStream getContent() throws IOException { if (!isStreaming()) { - return decoder.apply(super.getContent()); + return getDecompressingStream(); } InputStream local = cached; if (local == null) { if (cached == null) { - cached = decoder.apply(super.getContent()); + cached = getDecompressingStream(); } local = cached; } @@ -97,4 +103,61 @@ public void writeTo(final OutputStream out) throws IOException { } } } -} + + private static final class LazyDecompressingInputStream extends FilterInputStream { + + private final IOFunction decoder; + private InputStream decompressedStream; + + private LazyDecompressingInputStream( + final InputStream inputStream, + final IOFunction decoder) { + super(inputStream); + this.decoder = decoder; + } + + private InputStream getDecompressedStream() throws IOException { + if (decompressedStream == null) { + decompressedStream = decoder.apply(in); + } + return decompressedStream; + } + + @Override + public int read() throws IOException { + return getDecompressedStream().read(); + } + + @Override + public int read(final byte[] b) throws IOException { + return getDecompressedStream().read(b); + } + + @Override + public int read(final byte[] b, final int off, final int len) throws IOException { + return getDecompressedStream().read(b, off, len); + } + + @Override + public long skip(final long n) throws IOException { + return getDecompressedStream().skip(n); + } + + @Override + public int available() throws IOException { + return getDecompressedStream().available(); + } + + @Override + public void close() throws IOException { + final InputStream local = decompressedStream; + if (local != null) { + local.close(); + } else { + super.close(); + } + } + + } + +} \ No newline at end of file diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestDecompressingEntity.java b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestDecompressingEntity.java index e19b61aca7..a24e050e6f 100644 --- a/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestDecompressingEntity.java +++ b/httpclient5/src/test/java/org/apache/hc/client5/http/entity/TestDecompressingEntity.java @@ -29,11 +29,13 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.zip.CRC32; import java.util.zip.CheckedInputStream; import java.util.zip.Checksum; +import java.util.zip.GZIPInputStream; import org.apache.hc.core5.http.ContentType; import org.apache.hc.core5.http.HttpEntity; @@ -108,6 +110,28 @@ void testWriteToStream() throws Exception { } } + @Test + void testMalformedGzipContentCanBeClosedWithoutReading() throws Exception { + final ByteArrayInputStream in = new ByteArrayInputStream(new byte[0]); + final InputStreamEntity wrapped = new InputStreamEntity(in, -1, ContentType.APPLICATION_OCTET_STREAM); + final HttpEntity entity = new org.apache.hc.client5.http.entity.compress.DecompressingEntity( + wrapped, GZIPInputStream::new); + + Assertions.assertDoesNotThrow(() -> entity.getContent().close()); + } + + @Test + void testMalformedGzipContentFailsOnRead() throws Exception { + final ByteArrayInputStream in = new ByteArrayInputStream(new byte[0]); + final InputStreamEntity wrapped = new InputStreamEntity(in, -1, ContentType.APPLICATION_OCTET_STREAM); + final HttpEntity entity = new org.apache.hc.client5.http.entity.compress.DecompressingEntity( + wrapped, GZIPInputStream::new); + + try (final InputStream content = entity.getContent()) { + Assertions.assertThrows(IOException.class, content::read); + } + } + static class ChecksumEntity extends org.apache.hc.client5.http.entity.compress.DecompressingEntity { public ChecksumEntity(final HttpEntity wrapped, final Checksum checksum) {