Skip to content

Commit

Permalink
Simplify header parsing logic (#601)
Browse files Browse the repository at this point in the history
  • Loading branch information
basil committed Nov 14, 2022
1 parent 404fd10 commit 21f7a72
Showing 1 changed file with 20 additions and 58 deletions.
Expand Up @@ -60,16 +60,18 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.StringJoiner;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.logging.Level.INFO;
import static org.jenkinsci.remoting.util.ThrowableUtils.chain;
Expand Down Expand Up @@ -112,7 +114,7 @@ public JnlpAgentEndpointResolver(@NonNull List<String> jenkinsUrls) {
this(jenkinsUrls, null, null, null, null, false);
}

public JnlpAgentEndpointResolver(List<String> jenkinsUrls, String credentials, String proxyCredentials,
public JnlpAgentEndpointResolver(@NonNull List<String> jenkinsUrls, String credentials, String proxyCredentials,
String tunnel, SSLSocketFactory sslSocketFactory, boolean disableHttpsCertValidation) {
this.jenkinsUrls = new ArrayList<>(jenkinsUrls);
this.credentials = credentials;
Expand Down Expand Up @@ -221,7 +223,7 @@ public JnlpAgentEndpoint resolve() throws IOException {
}

// Check if current version of agent is supported
String minimumSupportedVersionHeader = first(header(con, Engine.REMOTING_MINIMUM_VERSION_HEADER));
String minimumSupportedVersionHeader = con.getHeaderField(Engine.REMOTING_MINIMUM_VERSION_HEADER);
if (minimumSupportedVersionHeader != null) {
VersionNumber minimumSupportedVersion = new VersionNumber(minimumSupportedVersionHeader);
VersionNumber currentVersion = new VersionNumber(Launcher.VERSION);
Expand All @@ -233,24 +235,17 @@ public JnlpAgentEndpoint resolve() throws IOException {
}
}

String host;
String portStr;
Set<String> agentProtocolNames = null;

portStr = first(header(con, "X-Jenkins-JNLP-Port", "X-Hudson-JNLP-Port"));
host = defaultString(first(header(con, "X-Jenkins-JNLP-Host")), salURL.getHost());
List<String> protocols = header(con, "X-Jenkins-Agent-Protocols");
String portStr = Optional.ofNullable(con.getHeaderField("X-Jenkins-JNLP-Port")).orElse(con.getHeaderField("X-Hudson-JNLP-Port"));
String host = Optional.ofNullable(con.getHeaderField("X-Jenkins-JNLP-Host")).orElse(salURL.getHost());
String protocols = con.getHeaderField("X-Jenkins-Agent-Protocols");
if (protocols != null) {
// Take the list of protocols to try from the headers
agentProtocolNames = new HashSet<>();
for (String names : protocols) {
for (String name : names.split(",")) {
name = name.trim();
if (!name.isEmpty()) {
agentProtocolNames.add(name);
}
}
}
agentProtocolNames = Stream.of(protocols.split(","))
.map(String::trim)
.filter(Predicate.not(String::isEmpty))
.collect(Collectors.toSet());

if (agentProtocolNames.isEmpty()) {
LOGGER.log(Level.WARNING, "Received the empty list of supported protocols from the server. " +
Expand All @@ -265,18 +260,15 @@ public JnlpAgentEndpoint resolve() throws IOException {

if (PROTOCOL_NAMES_TO_TRY != null) {
// Take a list of protocols to try from the system property
agentProtocolNames = new HashSet<>();
LOGGER.log(Level.INFO, "Ignoring the list of supported remoting protocols provided by the server, because the " +
"'org.jenkinsci.remoting.engine.JnlpAgentEndpointResolver.protocolNamesToTry' property is defined. Will try {0}", PROTOCOL_NAMES_TO_TRY);
for (String name : PROTOCOL_NAMES_TO_TRY.split(",")) {
name = name.trim();
if (!name.isEmpty()) {
agentProtocolNames.add(name);
}
}
agentProtocolNames = Stream.of(PROTOCOL_NAMES_TO_TRY.split(","))
.map(String::trim)
.filter(Predicate.not(String::isEmpty))
.collect(Collectors.toSet());
}

String idHeader = first(header(con, "X-Instance-Identity"));
String idHeader = con.getHeaderField("X-Instance-Identity");
RSAPublicKey identity;
try {
identity = getIdentity(idHeader);
Expand Down Expand Up @@ -390,12 +382,11 @@ public void waitForReady() throws InterruptedException {
try {
// Jenkins top page might be read-protected. see http://www.nabble
// .com/more-lenient-retry-logic-in-Engine.waitForServerToBack-td24703172.html
final String firstUrl = first(jenkinsUrls);
if (firstUrl == null) {
if (jenkinsUrls.isEmpty()) {
// returning here will cause the whole loop to be broken and all the urls to be tried again
return;
}
URL url = toAgentListenerURL(firstUrl);
URL url = toAgentListenerURL(jenkinsUrls.get(0));

retries++;
t.setName(oldName + ": trying " + url + " for " + retries + " times");
Expand Down Expand Up @@ -565,33 +556,4 @@ static URLConnection openURLConnection(URL url, String credentials, String proxy
static boolean inNoProxyEnvVar(String host) {
return !NoProxyEvaluator.shouldProxy(host);
}

@CheckForNull
private static List<String> header(@NonNull HttpURLConnection connection, String... headerNames) {
Map<String, List<String>> headerFields = connection.getHeaderFields();
for (String headerName : headerNames) {
for (Map.Entry<String, List<String>> entry: headerFields.entrySet()) {
final String headerField = entry.getKey();
if (isMatchingHeader(headerName, headerField)) {
return entry.getValue();
}
}
}
return null;
}

@SuppressFBWarnings(value = "IMPROPER_UNICODE", justification = "Header fields are provided by controller and header names are hardcoded.")
private static boolean isMatchingHeader(String headerName, String headerField) {
return headerField != null && headerField.equalsIgnoreCase(headerName);
}

@CheckForNull
private static String first(@CheckForNull List<String> values) {
return values == null || values.isEmpty() ? null : values.get(0);
}

@NonNull
private static String defaultString(@CheckForNull String value, @NonNull String defaultValue) {
return value == null ? defaultValue : value;
}
}

0 comments on commit 21f7a72

Please sign in to comment.