diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 2f343a4822..b633bb3a7c 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,10 +1,57 @@ -Release 5.6 ALPHA1 +Release 5.6.1 ------------------ -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 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 +------------------ + +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 +75,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 +89,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 diff --git a/httpclient5-cache/pom.xml b/httpclient5-cache/pom.xml index e1d30f756f..82d101935d 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.2-SNAPSHOT httpclient5-cache Apache HttpClient Cache 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)); + } + } diff --git a/httpclient5-fluent/pom.xml b/httpclient5-fluent/pom.xml index 85b5b6cc6f..353f152dbe 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.2-SNAPSHOT httpclient5-fluent Apache HttpClient Fluent diff --git a/httpclient5-observation/pom.xml b/httpclient5-observation/pom.xml index 6cb5260aaa..16a2a962fd 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.2-SNAPSHOT httpclient5-observation @@ -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 @@ -148,4 +135,16 @@ - + + + + com.github.siom79.japicmp + japicmp-maven-plugin + + true + + + + + + \ No newline at end of file diff --git a/httpclient5-testing/pom.xml b/httpclient5-testing/pom.xml index ffc73b9385..e4d647714b 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.2-SNAPSHOT httpclient5-testing Apache HttpClient Integration Tests @@ -159,4 +159,4 @@ - + \ No newline at end of file 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/TestAsyncSocketTimeout.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncSocketTimeout.java index ec5de2ff9b..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,23 +38,18 @@ 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; -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; abstract class AbstractTestSocketTimeout extends AbstractIntegrationTestBase { @@ -65,22 +60,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 +79,34 @@ void testReadTimeouts(final String param) throws Throwable { .setSocketTimeout(connConfigTimeout, MILLISECONDS) .build()); } + + for (final boolean drip : new boolean[]{ false, true }) { + 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 int delay, 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=" + delay + "&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() { @@ -146,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/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/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-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-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, 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..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 @@ -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,30 @@ 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 }) { + 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()), + String.format("drip=%s, reuseConnection=%s", drip, reuseConnection)); + } + } + } + + 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()) .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 +121,7 @@ public Http() { @Nested class Https extends AbstractTestSocketTimeout { public Https() { - super(URIScheme.HTTP, ClientProtocolLevel.STANDARD, false); + super(URIScheme.HTTPS, ClientProtocolLevel.STANDARD, false); } } 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..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,11 +43,11 @@ 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; -import javax.net.ssl.SSLException; import java.time.Duration; import java.time.temporal.ChronoUnit; @@ -55,7 +55,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; @@ -63,6 +62,7 @@ public class TestTlsHandshakeTimeout { private static final Duration EXPECTED_TIMEOUT = Duration.ofMillis(500); + @Tag("slow") @Timeout(5) @ParameterizedTest @ValueSource(strings = { "false", "true" }) @@ -97,23 +97,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(), diff --git a/httpclient5/pom.xml b/httpclient5/pom.xml index 4003210b9d..ba4ab52914 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.2-SNAPSHOT httpclient5 Apache HttpClient @@ -206,4 +206,4 @@ - + \ No newline at end of file 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, 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/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/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/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/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/async/ContentCompressionAsyncExec.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/ContentCompressionAsyncExec.java index d8c9a6aa4b..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 @@ -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( @@ -139,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/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..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 } @@ -866,7 +863,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; } @@ -1100,7 +1097,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( @@ -1146,10 +1143,8 @@ public CloseableHttpAsyncClient build() { } if (evictExpiredConnections || evictIdleConnections) { if (connManagerCopy instanceof ConnPoolControl) { - TimeValue sleepTime = maxIdleTime.divide(10, TimeUnit.NANOSECONDS); - sleepTime = sleepTime.compareTo(ONE_SECOND) < 0 ? ONE_SECOND : sleepTime; final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor((ConnPoolControl) connManagerCopy, - sleepTime, maxIdleTime); + null, evictIdleConnections ? maxIdleTime : null); closeablesCopy.add(connectionEvictor::shutdown); connectionEvictor.start(); } 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 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..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 @@ -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()) { @@ -273,7 +273,7 @@ private 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/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..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,8 +27,8 @@ package org.apache.hc.client5.http.impl.auth; +import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Locale; @@ -47,19 +47,19 @@ 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; 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.ParserCursor; +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; -import org.apache.hc.core5.util.CharArrayBuffer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -169,43 +169,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; } @@ -246,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/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/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..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 } @@ -780,7 +777,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 +1112,8 @@ public CloseableHttpClient build() { } if (evictExpiredConnections || evictIdleConnections) { if (connManagerCopy instanceof ConnPoolControl) { - TimeValue sleepTime = maxIdleTime.divide(10, TimeUnit.NANOSECONDS); - sleepTime = sleepTime.compareTo(ONE_SECOND) < 0 ? ONE_SECOND : sleepTime; final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor((ConnPoolControl) connManagerCopy, - sleepTime, maxIdleTime); + null, evictIdleConnections ? maxIdleTime : null); closeablesCopy.add(() -> { connectionEvictor.shutdown(); try { 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/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 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..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 @@ -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); } @@ -478,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, @@ -485,7 +503,7 @@ public Future connect( route.getTargetName(), route.getLocalSocketAddress(), connectTimeout, - route.isTunnelled() ? null : resolveTlsConfig(route.getTargetHost()), + connectAttachment, context, new FutureCallback() { 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/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/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/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/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) { 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/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))); + } + } 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..3c06ff9a49 --- /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{|}~. 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); + } +} 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/async/TestContentCompressionAsyncExec.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/async/TestContentCompressionAsyncExec.java index a02ddb45d4..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; @@ -163,7 +164,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); @@ -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 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)), 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()); + } + } 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 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()); + } } 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); + } + } + } diff --git a/pom.xml b/pom.xml index cc21e55cc1..b7c4a4c865 100644 --- a/pom.xml +++ b/pom.xml @@ -32,10 +32,10 @@ 4.0.0 org.apache.httpcomponents.client5 httpclient5-parent - Apache HttpComponents Client Parent - 5.6-alpha1-SNAPSHOT + 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 @@ -48,21 +48,21 @@ 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.2-SNAPSHOT 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/ 1.8 1.8 - 5.4-alpha1 + 5.4 2.25.0 1.20.0 2.5.2 @@ -76,13 +76,13 @@ 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 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 @@ -286,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/ @@ -335,6 +332,7 @@ com.github.siom79.japicmp japicmp-maven-plugin + 0.25.4 @@ -344,11 +342,6 @@ jar - - - ${project.build.directory}/${project.artifactId}-${project.version}.${project.packaging} - - true true @@ -362,7 +355,9 @@ @org.apache.hc.core5.annotation.Internal - true + true + false + false @@ -456,8 +451,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/ @@ -487,7 +482,6 @@ javadoc - aggregate @@ -503,6 +497,14 @@ + + + ${project.groupId} + ${project.artifactId} + ${project.version} + jar + + ${project.groupId} @@ -511,26 +513,15 @@ jar - - - ${project.build.directory}/${project.artifactId}-${project.version}.${project.packaging} - - @org.apache.hc.core5.annotation.Internal - true + true - - maven-jxr-plugin - - - maven-surefire-report-plugin - - + \ No newline at end of file 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 +