Throw IllegalStateException for invalid port in HierarchicalUriComponents

Prior to this commit, getPort() in HierarchicalUriComponents threw a
NumberFormatException for an invalid port supplied as a String, which
was inconsistent with exception handling elsewhere in the class as well
as within the same method.

This commit introduces a try-catch block in getPort() to consistently
throw IllegalStateExceptions for ports that cannot be parsed.

Closes gh-28521
This commit is contained in:
Sam Brannen 2022-05-25 11:28:49 +02:00
parent aa06a09dee
commit a221835558
3 changed files with 40 additions and 8 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -46,6 +46,7 @@ import org.springframework.util.StringUtils;
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Phillip Webb * @author Phillip Webb
* @author Sam Brannen
* @since 3.1.3 * @since 3.1.3
* @see <a href="https://tools.ietf.org/html/rfc3986#section-1.2.3">Hierarchical URIs</a> * @see <a href="https://tools.ietf.org/html/rfc3986#section-1.2.3">Hierarchical URIs</a>
*/ */
@ -192,7 +193,12 @@ final class HierarchicalUriComponents extends UriComponents {
throw new IllegalStateException( throw new IllegalStateException(
"The port contains a URI variable but has not been expanded yet: " + this.port); "The port contains a URI variable but has not been expanded yet: " + this.port);
} }
return Integer.parseInt(this.port); try {
return Integer.parseInt(this.port);
}
catch (NumberFormatException ex) {
throw new IllegalStateException("The port must be an integer: " + this.port);
}
} }
@Override @Override

View File

@ -40,7 +40,7 @@ import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
/** /**
* Unit tests for {@link UriComponentsBuilder}. * Unit tests for {@link UriComponentsBuilder}.
@ -1314,11 +1314,13 @@ class UriComponentsBuilderTests {
@Test @Test
void verifyInvalidPort() { void verifyInvalidPort() {
String url = "http://localhost:port/path"; String url = "http://localhost:XXX/path";
assertThatThrownBy(() -> UriComponentsBuilder.fromUriString(url).build().toUri()) assertThatIllegalStateException()
.isInstanceOf(NumberFormatException.class); .isThrownBy(() -> UriComponentsBuilder.fromUriString(url).build().toUri())
assertThatThrownBy(() -> UriComponentsBuilder.fromHttpUrl(url).build().toUri()) .withMessage("The port must be an integer: XXX");
.isInstanceOf(NumberFormatException.class); assertThatIllegalStateException()
.isThrownBy(() -> UriComponentsBuilder.fromHttpUrl(url).build().toUri())
.withMessage("The port must be an integer: XXX");
} }
@Test // gh-27039 @Test // gh-27039

View File

@ -30,6 +30,7 @@ import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.springframework.web.util.UriComponentsBuilder.fromHttpUrl;
import static org.springframework.web.util.UriComponentsBuilder.fromUriString; import static org.springframework.web.util.UriComponentsBuilder.fromUriString;
/** /**
@ -151,6 +152,29 @@ class UriComponentsTests {
assertThat(uri4.toUriString()).isEqualTo("https://example.com:8080/bar"); assertThat(uri4.toUriString()).isEqualTo("https://example.com:8080/bar");
} }
@Test // gh-28521
void invalidPort() {
assertExceptionsForInvalidPort(fromUriString("https://example.com:XXX/bar").build());
assertExceptionsForInvalidPort(fromUriString("https://example.com/bar").port("XXX").build());
assertExceptionsForInvalidPort(fromHttpUrl("https://example.com:XXX/bar").build());
assertExceptionsForInvalidPort(fromHttpUrl("https://example.com/bar").port("XXX").build());
}
private void assertExceptionsForInvalidPort(UriComponents uriComponents) {
assertThatIllegalStateException()
.isThrownBy(uriComponents::getPort)
.withMessage("The port must be an integer: XXX");
assertThatIllegalStateException()
.isThrownBy(uriComponents::toUri)
.withMessage("The port must be an integer: XXX");
assertThatIllegalStateException()
.isThrownBy(uriComponents::toUriString)
.withMessage("The port must be an integer: XXX");
assertThatIllegalStateException()
.isThrownBy(uriComponents::toString)
.withMessage("The port must be an integer: XXX");
}
@Test @Test
void expandEncoded() { void expandEncoded() {
assertThatIllegalStateException().isThrownBy(() -> assertThatIllegalStateException().isThrownBy(() ->