Skip to content

Commit 945e4f4

Browse files
utamastitusfortnerdiemol
authored
Allow external uri to be configurable for components that support server functionality - #12491 (#12508)
* Allow external uri to be configurable for components that support server functionality. SE nodes might be behind some sort of proxy exposed to hub on a different hostname(/ip) and/or port than component would by default report themselves (e.g.: hub and nodes are in different k8s clusters and services are exposed via node ports). Fixes #12491 * Rename external-uri to external-url. #12508 (review) Fixes #12491 * fix linting issues --------- Co-authored-by: titusfortner <[email protected]> Co-authored-by: Diego Molina <[email protected]> Co-authored-by: Titus Fortner <[email protected]>
1 parent aaec17e commit 945e4f4

File tree

3 files changed

+104
-22
lines changed

3 files changed

+104
-22
lines changed

java/src/org/openqa/selenium/grid/server/BaseServerFlags.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ public class BaseServerFlags implements HasRoles {
3333

3434
private static final String SERVER_SECTION = "server";
3535

36+
@Parameter(
37+
names = {"--external-url"},
38+
description =
39+
"External URL where component is generally available. "
40+
+ "Useful on complex network topologies when components are on different networks "
41+
+ "and proxy servers are involved.")
42+
@ConfigValue(section = SERVER_SECTION, name = "external-url", example = "http://10.0.1.1:33333")
43+
private String externalUrl;
44+
3645
@Parameter(
3746
names = {"--host"},
3847
description = "Server IP or hostname: usually determined automatically.")

java/src/org/openqa/selenium/grid/server/BaseServerOptions.java

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -84,28 +84,48 @@ public int getMaxServerThreads() {
8484

8585
@ManagedAttribute(name = "Uri")
8686
public URI getExternalUri() {
87-
// Assume the host given is addressable if it's been set
88-
String host =
89-
getHostname()
90-
.orElseGet(
91-
() -> {
92-
try {
93-
return new NetworkUtils().getNonLoopbackAddressOfThisMachine();
94-
} catch (WebDriverException e) {
95-
String name = HostIdentifier.getHostName();
96-
LOG.info("No network connection, guessing name: " + name);
97-
return name;
98-
}
99-
});
100-
101-
int port = getPort();
102-
103-
try {
104-
return new URI(
105-
(isSecure() || isSelfSigned()) ? "https" : "http", null, host, port, null, null, null);
106-
} catch (URISyntaxException e) {
107-
throw new ConfigException("Cannot determine external URI: " + e.getMessage());
108-
}
87+
return config
88+
.get(SERVER_SECTION, "external-url")
89+
.map(
90+
url -> {
91+
try {
92+
return new URI(url);
93+
} catch (URISyntaxException e) {
94+
throw new RuntimeException(
95+
"Supplied external URI is invalid: " + e.getMessage(), e);
96+
}
97+
})
98+
.orElseGet(
99+
() -> {
100+
// Assume the host given is addressable if it's been set
101+
String host =
102+
getHostname()
103+
.orElseGet(
104+
() -> {
105+
try {
106+
return new NetworkUtils().getNonLoopbackAddressOfThisMachine();
107+
} catch (WebDriverException e) {
108+
String name = HostIdentifier.getHostName();
109+
LOG.info("No network connection, guessing name: " + name);
110+
return name;
111+
}
112+
});
113+
114+
int port = getPort();
115+
116+
try {
117+
return new URI(
118+
(isSecure() || isSelfSigned()) ? "https" : "http",
119+
null,
120+
host,
121+
port,
122+
null,
123+
null,
124+
null);
125+
} catch (URISyntaxException e) {
126+
throw new ConfigException("Cannot determine external URI: " + e.getMessage());
127+
}
128+
});
109129
}
110130

111131
public boolean getAllowCORS() {

java/test/org/openqa/selenium/grid/server/BaseServerOptionsTest.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818
package org.openqa.selenium.grid.server;
1919

2020
import static org.assertj.core.api.Assertions.assertThat;
21+
import static org.junit.jupiter.api.Assertions.assertThrows;
2122

23+
import java.net.URI;
24+
import java.net.URISyntaxException;
2225
import java.util.Map;
2326
import org.junit.jupiter.api.Test;
2427
import org.openqa.selenium.grid.config.MapConfig;
@@ -43,4 +46,54 @@ void serverConfigBindsToHostByDefault() {
4346

4447
assertThat(options.getBindHost()).isEqualTo(true);
4548
}
49+
50+
@Test
51+
void externalUriFailsForNonUriStrings() {
52+
BaseServerOptions options =
53+
new BaseServerOptions(new MapConfig(Map.of("server", Map.of("external-url", "not a URL"))));
54+
55+
Exception exception =
56+
assertThrows(
57+
RuntimeException.class,
58+
() -> {
59+
options.getExternalUri();
60+
});
61+
62+
assertThat(exception.getMessage())
63+
.as("External URI must be parseable as URI.")
64+
.isEqualTo(
65+
"Supplied external URI is invalid: Illegal character in path at index 3: not a URL");
66+
}
67+
68+
@Test
69+
void externalUriTakesPriorityOverDefaults() throws URISyntaxException {
70+
URI expected = new URI("http://10.0.1.1:33333");
71+
72+
BaseServerOptions options =
73+
new BaseServerOptions(
74+
new MapConfig(
75+
Map.of(
76+
"server",
77+
Map.of(
78+
"external-url", expected.toString(), "host", "localhost", "port", 5555))));
79+
80+
assertThat(options.getExternalUri()).isEqualTo(expected);
81+
}
82+
83+
@Test
84+
void externalUriDefaultsToValueDerivedFromHostnameAndPortWhenNotDefined()
85+
throws URISyntaxException {
86+
URI expected = new URI("http://localhost:5555");
87+
88+
BaseServerOptions options =
89+
new BaseServerOptions(
90+
new MapConfig(
91+
Map.of(
92+
"server",
93+
Map.of(
94+
"host", expected.getHost(),
95+
"port", expected.getPort()))));
96+
97+
assertThat(options.getExternalUri()).isEqualTo(expected);
98+
}
4699
}

0 commit comments

Comments
 (0)