|  | @@ -47,6 +47,7 @@ import org.apache.lucene.util.automaton.Operations;
 | 
	
		
			
				|  |  |  import org.elasticsearch.ElasticsearchException;
 | 
	
		
			
				|  |  |  import org.elasticsearch.cluster.service.ClusterService;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.Strings;
 | 
	
		
			
				|  |  | +import org.elasticsearch.common.collect.Tuple;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.regex.Regex;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.settings.Settings;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.unit.ByteSizeValue;
 | 
	
	
		
			
				|  | @@ -162,7 +163,9 @@ public class HttpClient implements Closeable {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public HttpResponse execute(HttpRequest request) throws IOException {
 | 
	
		
			
				|  |  | -        URI uri = createURI(request);
 | 
	
		
			
				|  |  | +        Tuple<HttpHost, URI> tuple = createURI(request);
 | 
	
		
			
				|  |  | +        final URI uri = tuple.v2();
 | 
	
		
			
				|  |  | +        final HttpHost httpHost = tuple.v1();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          HttpRequestBase internalRequest;
 | 
	
		
			
				|  |  |          if (request.method == HttpMethod.HEAD) {
 | 
	
	
		
			
				|  | @@ -212,7 +215,7 @@ public class HttpClient implements Closeable {
 | 
	
		
			
				|  |  |              // preemptive auth, no need to wait for a 401 first
 | 
	
		
			
				|  |  |              AuthCache authCache = new BasicAuthCache();
 | 
	
		
			
				|  |  |              BasicScheme basicAuth = new BasicScheme();
 | 
	
		
			
				|  |  | -            authCache.put(new HttpHost(request.host, request.port, request.scheme.scheme()), basicAuth);
 | 
	
		
			
				|  |  | +            authCache.put(httpHost, basicAuth);
 | 
	
		
			
				|  |  |              localContext.setAuthCache(authCache);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -233,7 +236,7 @@ public class HttpClient implements Closeable {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          internalRequest.setConfig(config.build());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        try (CloseableHttpResponse response = SocketAccess.doPrivileged(() -> client.execute(internalRequest, localContext))) {
 | 
	
		
			
				|  |  | +        try (CloseableHttpResponse response = SocketAccess.doPrivileged(() -> client.execute(httpHost, internalRequest, localContext))) {
 | 
	
		
			
				|  |  |              // headers
 | 
	
		
			
				|  |  |              Header[] headers = response.getAllHeaders();
 | 
	
		
			
				|  |  |              Map<String, String[]> responseHeaders = new HashMap<>(headers.length);
 | 
	
	
		
			
				|  | @@ -310,7 +313,7 @@ public class HttpClient implements Closeable {
 | 
	
		
			
				|  |  |          return HttpProxy.NO_PROXY;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    private URI createURI(HttpRequest request) {
 | 
	
		
			
				|  |  | +    private Tuple<HttpHost, URI> createURI(HttpRequest request) {
 | 
	
		
			
				|  |  |          // this could be really simple, as the apache http client has a UriBuilder class, however this class is always doing
 | 
	
		
			
				|  |  |          // url path escaping, and we have done this already, so this would result in double escaping
 | 
	
		
			
				|  |  |          try {
 | 
	
	
		
			
				|  | @@ -320,7 +323,23 @@ public class HttpClient implements Closeable {
 | 
	
		
			
				|  |  |              URI uri = URIUtils.createURI(request.scheme.scheme(), request.host, request.port, request.path,
 | 
	
		
			
				|  |  |                      Strings.isNullOrEmpty(format) ? null : format, null);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            return uri;
 | 
	
		
			
				|  |  | +            if (uri.isAbsolute() == false) {
 | 
	
		
			
				|  |  | +                throw new IllegalStateException("URI [" + uri.toASCIIString() + "] must be absolute");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            final HttpHost httpHost = URIUtils.extractHost(uri);
 | 
	
		
			
				|  |  | +            // what a mess that we need to do this to workaround https://issues.apache.org/jira/browse/HTTPCLIENT-1968
 | 
	
		
			
				|  |  | +            // in some cases the HttpClient will re-write the URI which drops the escaping for
 | 
	
		
			
				|  |  | +            // slashes within a path. This rewriting is done to obtain a relative URI when
 | 
	
		
			
				|  |  | +            // a proxy is not being used. To avoid this we can handle making it relative ourselves
 | 
	
		
			
				|  |  | +            if (request.path != null && request.path.contains("%2F")) {
 | 
	
		
			
				|  |  | +                final boolean isUsingProxy = (request.proxy != null && request.proxy.equals(HttpProxy.NO_PROXY) == false) ||
 | 
	
		
			
				|  |  | +                    HttpProxy.NO_PROXY.equals(settingsProxy) == false;
 | 
	
		
			
				|  |  | +                if (isUsingProxy == false) {
 | 
	
		
			
				|  |  | +                    // we need a relative uri
 | 
	
		
			
				|  |  | +                    uri = URIUtils.createURI(null, null, -1, request.path, Strings.isNullOrEmpty(format) ? null : format, null);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            return new Tuple<>(httpHost, uri);
 | 
	
		
			
				|  |  |          } catch (URISyntaxException e) {
 | 
	
		
			
				|  |  |              throw new IllegalArgumentException(e);
 | 
	
		
			
				|  |  |          }
 |