diff --git a/core/src/main/java/com/linecorp/armeria/client/ClientRequestContext.java b/core/src/main/java/com/linecorp/armeria/client/ClientRequestContext.java
index 017197f2bde..833bce3d566 100644
--- a/core/src/main/java/com/linecorp/armeria/client/ClientRequestContext.java
+++ b/core/src/main/java/com/linecorp/armeria/client/ClientRequestContext.java
@@ -290,15 +290,11 @@ ClientRequestContext newDerivedContext(RequestId id, @Nullable HttpRequest req,
*
{@link Endpoint#authority()}.
*
*/
- @Nullable
- @UnstableApi
String authority();
/**
* Returns the host part of {@link #authority()}, without a port number.
*/
- @Nullable
- @UnstableApi
String host();
/**
diff --git a/core/src/main/java/com/linecorp/armeria/client/ClientRequestContextWrapper.java b/core/src/main/java/com/linecorp/armeria/client/ClientRequestContextWrapper.java
index f03e0a15de3..599e3dbfa2e 100644
--- a/core/src/main/java/com/linecorp/armeria/client/ClientRequestContextWrapper.java
+++ b/core/src/main/java/com/linecorp/armeria/client/ClientRequestContextWrapper.java
@@ -70,13 +70,11 @@ public String fragment() {
return unwrap().fragment();
}
- @Nullable
@Override
public String authority() {
return unwrap().authority();
}
- @Nullable
@Override
public String host() {
return unwrap().host();
diff --git a/core/src/main/java/com/linecorp/armeria/internal/client/DefaultClientRequestContext.java b/core/src/main/java/com/linecorp/armeria/internal/client/DefaultClientRequestContext.java
index 6af10aad221..4b58031eae0 100644
--- a/core/src/main/java/com/linecorp/armeria/internal/client/DefaultClientRequestContext.java
+++ b/core/src/main/java/com/linecorp/armeria/internal/client/DefaultClientRequestContext.java
@@ -483,15 +483,20 @@ private void failEarly(Throwable cause) {
// TODO(ikhoon): Consider moving the logic for filling authority to `HttpClientDelegate.exceute()`.
private void autoFillSchemeAuthorityAndOrigin() {
- final String authority = authority();
- if (authority != null && endpoint != null && endpoint.isIpAddrOnly()) {
- // The connection will be established with the IP address but `host` set to the `Endpoint`
- // could be used for SNI. It would make users send HTTPS requests with CSLB or configure a reverse
- // proxy based on an authority.
- final String host = SchemeAndAuthority.of(null, authority).host();
- if (!NetUtil.isValidIpV4Address(host) && !NetUtil.isValidIpV6Address(host)) {
- endpoint = endpoint.withHost(host);
+
+ try {
+ final String authority = authority();
+ if (endpoint != null && endpoint.isIpAddrOnly()) {
+ // The connection will be established with the IP address but `host` set to the `Endpoint`
+ // could be used for SNI. It would make users send HTTPS requests
+ // with CSLB or configure a reverse proxy based on an authority.
+ final String host = SchemeAndAuthority.of(null, authority).host();
+ if (!NetUtil.isValidIpV4Address(host) && !NetUtil.isValidIpV6Address(host)) {
+ endpoint = endpoint.withHost(host);
+ }
}
+ } catch (IllegalStateException e) {
+ // Just pass, because it's normal condition.
}
final HttpHeadersBuilder headersBuilder = internalRequestHeaders.toBuilder();
@@ -750,7 +755,6 @@ public String fragment() {
return requestTarget().fragment();
}
- @Nullable
@Override
public String authority() {
final HttpHeaders additionalRequestHeaders = this.additionalRequestHeaders;
@@ -774,6 +778,11 @@ public String authority() {
if (authority == null) {
authority = internalRequestHeaders.get(HttpHeaderNames.HOST);
}
+ if (authority == null) {
+ throw new IllegalStateException(
+ "ClientRequestContext may be in the process of initialization." +
+ "In this case, host() or authority() could be null");
+ }
return authority;
}
@@ -794,12 +803,12 @@ private String origin() {
return origin;
}
- @Nullable
@Override
public String host() {
final String authority = authority();
if (authority == null) {
- return null;
+ throw new IllegalStateException("ClientRequestContext may be in the process of initialization." +
+ "In this case, host() or authority() could be null");
}
return SchemeAndAuthority.of(null, authority).host();
}
diff --git a/core/src/test/java/com/linecorp/armeria/client/ClientRequestContextTest.java b/core/src/test/java/com/linecorp/armeria/client/ClientRequestContextTest.java
index d549701c386..8ed808021df 100644
--- a/core/src/test/java/com/linecorp/armeria/client/ClientRequestContextTest.java
+++ b/core/src/test/java/com/linecorp/armeria/client/ClientRequestContextTest.java
@@ -18,6 +18,8 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
import java.util.function.Function;
import java.util.stream.Stream;
@@ -29,6 +31,7 @@
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.junit.jupiter.params.provider.ValueSource;
+import com.linecorp.armeria.common.AggregatedHttpResponse;
import com.linecorp.armeria.common.HttpMethod;
import com.linecorp.armeria.common.HttpRequest;
import com.linecorp.armeria.common.RequestContext;
@@ -269,6 +272,31 @@ void hasOwnAttr() {
}
}
+ @Test
+ void callAuthorityShouldBeThrownDuringPartiallyInit() {
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+ final WebClient client = WebClient
+ .builder("http://localhost:8080")
+ .contextCustomizer(ctx -> {
+ countDownLatch.countDown();
+ assertThatThrownBy(ctx::host)
+ .isInstanceOf(IllegalStateException.class)
+ .hasMessage(
+ "ClientRequestContext may be in the process of initialization." +
+ "In this case, host() or authority() could be null");
+ assertThatThrownBy(ctx::authority)
+ .isInstanceOf(IllegalStateException.class)
+ .hasMessage(
+ "ClientRequestContext may be in the process of initialization." +
+ "In this case, host() or authority() could be null"
+ );
+ }).build();
+
+ final CompletableFuture aggregate = client.get("/").aggregate();
+ assertThat(countDownLatch.getCount()).isEqualTo(0);
+ aggregate.cancel(true);
+ }
+
@ParameterizedTest
@ValueSource(strings = {"%", "http:///", "http://foo.com/bar"})
void updateRequestWithInvalidPath(String path) {