Skip to content
Permalink
Browse files

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.
  • Loading branch information...
luccioman committed Apr 10, 2018
1 parent d5f9dc0 commit 2af3bf79c7ef06447e741b3c027cd457183dec84
@@ -189,7 +189,18 @@ public static serverObjects respond(final RequestHeader header, final serverObje
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;
@@ -482,6 +482,33 @@ public MultiProtocolURL(final String protocol, String host, final int port, fina
identSearchpart();
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.
@@ -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.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;
@@ -284,19 +282,35 @@ public boolean equals(Object o) {
return o instanceof RemoteInstance && ((RemoteInstance) o).solrurl.equals(this.solrurl);
}

/**
* @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();
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);
return u;
}
/**
* @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 boolean toExternalAddress, final String externalHost) {
String u = this.solrurl;
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;
}

@Override
public String getDefaultCoreName() {
@@ -81,9 +81,18 @@ public void close() {
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;
}
}

0 comments on commit 2af3bf7

Please sign in to comment.
You can’t perform that action at this time.