Improve rendering of remote Solr admin URLs

- properly handle IPv6 loopback address replacement
 - replace loopback address or host only when accessing peer remotely
 - replace loopback part with the peer hostname as requested rather than
with its seed public IP as this works better for Intranet mode and when
peer is behind a reverse proxy.
pull/137/head
luccioman 7 years ago
parent d5f9dc0848
commit 2af3bf79c7

@ -189,7 +189,18 @@ public class IndexFederated_p {
prop.put("table", 1);
final SolrConnector solr = sb.index.fulltext().getDefaultRemoteSolrConnector();
final long[] size = new long[]{((RemoteSolrConnector) solr).getSize()};
final ArrayList<String> urls = ((ShardInstance) ((RemoteSolrConnector) solr).getInstance()).getAdminInterfaces();
final boolean toExternalAddress = !header.accessFromLocalhost();
String externalHost = null;
if(toExternalAddress) {
/* The request does not come from the same computer than this peer : we get the external address used to reach it from the request headers, and we will use
* it if some remote solr instance(s) URLs are configured with loopback address alias (such as 'localhost', '127.0.0.1', '[::1]')
* to render the externally reachable Solr instance(s) admin URLs */
externalHost = header.getServerName();
}
final ArrayList<String> urls = ((ShardInstance) ((RemoteSolrConnector) solr).getInstance())
.getAdminInterfaces(toExternalAddress, externalHost);
boolean dark = false;
for (int i = 0; i < size.length; i++) {
prop.put("table_list_" + i + "_dark", dark ? 1 : 0); dark = !dark;

@ -483,6 +483,33 @@ public class MultiProtocolURL implements Serializable, Comparable<MultiProtocolU
escape();
}
/**
* @param host the new host to apply to the copy
* @return an exact copy of this URL instance but with a new host. The original instance remains unchanged.
* @throws IllegalArgumentException when the host parameter is null or empty.
*/
public MultiProtocolURL ofNewHost(final String host) throws IllegalArgumentException {
if(host == null || host.trim().isEmpty()) {
throw new IllegalArgumentException("Host parameter must not be null");
}
MultiProtocolURL copy = new MultiProtocolURL(this);
if (host.indexOf(':') >= 0 && host.charAt(0) != '[') {
copy.host = '[' + host + ']'; // IPv6 host must be enclosed in square brackets
} else {
copy.host = host;
}
if (!Punycode.isBasic(this.host)) try {
this.host = toPunycode(this.host);
} catch (final PunycodeException e) {
ConcurrentLog.logException(e);
}
return copy;
}
/**
* Resolve '..' segments in the path.
* For standard pseudo algorithms, see :

@ -21,7 +21,6 @@
package net.yacy.cora.federate.solr.instance;
import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
@ -58,7 +57,6 @@ import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient;
import net.yacy.cora.document.id.MultiProtocolURL;
import net.yacy.cora.protocol.Domains;
import net.yacy.cora.protocol.HeaderFramework;
import net.yacy.cora.util.CommonPattern;
import net.yacy.cora.util.ConcurrentLog;
@ -285,16 +283,32 @@ public class RemoteInstance implements SolrInstance {
}
/**
* @param toExternalAddress
* when true, try to replace the eventual loopback host part of the
* Solr URL with the external host name of the hosting machine
* @param externalHost
* the eventual external host name or address to use when
* toExternalAddress is true
* @return the administration URL of the remote Solr instance
*/
public String getAdminInterface() {
final InetAddress localhostExternAddress = Domains.myPublicLocalIP();
final String localhostExtern = localhostExternAddress == null ? "127.0.0.1" : localhostExternAddress.getHostAddress();
public String getAdminInterface(final boolean toExternalAddress, final String externalHost) {
String u = this.solrurl;
int p = u.indexOf("localhost",0);
if (p < 0) p = u.indexOf("127.0.0.1",0);
if (p < 0) p = u.indexOf("0:0:0:0:0:0:0:1",0);
if (p >= 0) u = u.substring(0, p) + localhostExtern + u.substring(p + 9);
if (toExternalAddress && externalHost != null && !externalHost.trim().isEmpty()) {
try {
MultiProtocolURL url = new MultiProtocolURL(u);
if(url.isLocal()) {
url = url.ofNewHost(externalHost);
u = url.toString();
}
} catch (final MalformedURLException ignored) {
/*
* This should not happen as the solrurl attribute has already been parsed in
* the constructor
*/
}
}
return u;
}

@ -81,9 +81,18 @@ public class ShardInstance implements SolrInstance {
for (RemoteInstance instance: instances) instance.close();
}
public ArrayList<String> getAdminInterfaces() {
/**
* @param toExternalAddress
* when true, try to replace the eventual loopback host part of the
* Solr instances URLs with the external host name of the hosting machine
* @param externalHost
* the eventual external host name or address to use when
* toExternalAddress is true
* @return the administration URLs of the Solr instances
*/
public ArrayList<String> getAdminInterfaces(final boolean toExternalAddress, final String externalHost) {
ArrayList<String> a = new ArrayList<String>();
for (RemoteInstance i: this.instances) a.add(i.getAdminInterface());
for (RemoteInstance i: this.instances) a.add(i.getAdminInterface(toExternalAddress, externalHost));
return a;
}
}

Loading…
Cancel
Save