Sfoglia il codice sorgente

Replace Request#setHeaders with addHeader (#30588)

Adding headers rather than setting them all at once seems more
user-friendly and we already do it in a similar way for parameters
(see Request#addParameter).
Luca Cavanna 7 anni fa
parent
commit
a17d6cab98
20 ha cambiato i file con 166 aggiunte e 134 eliminazioni
  1. 9 4
      client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
  2. 2 2
      client/rest-high-level/src/test/java/org/elasticsearch/client/CustomRestHighLevelClientTests.java
  3. 46 18
      client/rest/src/main/java/org/elasticsearch/client/Request.java
  4. 24 10
      client/rest/src/main/java/org/elasticsearch/client/RestClient.java
  5. 28 30
      client/rest/src/test/java/org/elasticsearch/client/RequestTests.java
  6. 3 2
      client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostIntegTests.java
  7. 7 5
      client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostTests.java
  8. 1 1
      client/rest/src/test/java/org/elasticsearch/client/RestClientTests.java
  9. 2 7
      client/rest/src/test/java/org/elasticsearch/client/documentation/RestClientDocumentation.java
  10. 1 1
      client/test/src/main/java/org/elasticsearch/client/RestClientTestUtil.java
  11. 1 1
      docs/java-rest/low-level/usage.asciidoc
  12. 2 3
      qa/smoke-test-http/src/test/java/org/elasticsearch/http/ContextAndHeaderTransportIT.java
  13. 2 2
      qa/smoke-test-http/src/test/java/org/elasticsearch/http/CorsNotSetIT.java
  14. 28 25
      qa/smoke-test-http/src/test/java/org/elasticsearch/http/CorsRegexIT.java
  15. 1 2
      qa/smoke-test-http/src/test/java/org/elasticsearch/http/HttpCompressionIT.java
  16. 1 2
      qa/smoke-test-http/src/test/java/org/elasticsearch/http/NoHandlerIT.java
  17. 2 3
      qa/smoke-test-http/src/test/java/org/elasticsearch/http/ResponseHeaderPluginIT.java
  18. 1 2
      test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ESClientYamlSuiteTestCase.java
  19. 1 6
      x-pack/qa/sql/security/src/test/java/org/elasticsearch/xpack/qa/sql/security/RestSqlSecurityIT.java
  20. 4 8
      x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java

+ 9 - 4
client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java

@@ -26,8 +26,6 @@ import org.elasticsearch.ElasticsearchStatusException;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.ActionRequest;
 import org.elasticsearch.action.ActionRequestValidationException;
-import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesRequest;
-import org.elasticsearch.action.admin.cluster.repositories.get.GetRepositoriesResponse;
 import org.elasticsearch.action.bulk.BulkRequest;
 import org.elasticsearch.action.bulk.BulkResponse;
 import org.elasticsearch.action.delete.DeleteRequest;
@@ -592,7 +590,7 @@ public class RestHighLevelClient implements Closeable {
             throw validationException;
         }
         Request req = requestConverter.apply(request);
-        req.setHeaders(headers);
+        addHeaders(req, headers);
         Response response;
         try {
             response = client.performRequest(req);
@@ -642,12 +640,19 @@ public class RestHighLevelClient implements Closeable {
             listener.onFailure(e);
             return;
         }
-        req.setHeaders(headers);
+        addHeaders(req, headers);
 
         ResponseListener responseListener = wrapResponseListener(responseConverter, listener, ignores);
         client.performRequestAsync(req, responseListener);
     }
 
+    private static void addHeaders(Request request, Header... headers) {
+        Objects.requireNonNull(headers, "headers cannot be null");
+        for (Header header : headers) {
+            request.addHeader(header.getName(), header.getValue());
+        }
+    }
+
     final <Resp> ResponseListener wrapResponseListener(CheckedFunction<Response, Resp, IOException> responseConverter,
                                                         ActionListener<Resp> actionListener, Set<Integer> ignores) {
         return new ResponseListener() {

+ 2 - 2
client/rest-high-level/src/test/java/org/elasticsearch/client/CustomRestHighLevelClientTests.java

@@ -73,12 +73,12 @@ public class CustomRestHighLevelClientTests extends ESTestCase {
             final RestClient restClient = mock(RestClient.class);
             restHighLevelClient = new CustomRestClient(restClient);
 
-            doAnswer(inv -> mockPerformRequest(((Request) inv.getArguments()[0]).getHeaders()[0]))
+            doAnswer(inv -> mockPerformRequest(((Request) inv.getArguments()[0]).getHeaders().iterator().next()))
                     .when(restClient)
                     .performRequest(any(Request.class));
 
             doAnswer(inv -> mockPerformRequestAsync(
-                        ((Request) inv.getArguments()[0]).getHeaders()[0],
+                        ((Request) inv.getArguments()[0]).getHeaders().iterator().next(),
                         (ResponseListener) inv.getArguments()[1]))
                     .when(restClient)
                     .performRequestAsync(any(Request.class), any(ResponseListener.class));

+ 46 - 18
client/rest/src/main/java/org/elasticsearch/client/Request.java

@@ -19,14 +19,17 @@
 
 package org.elasticsearch.client;
 
-import org.apache.http.entity.ContentType;
 import org.apache.http.Header;
 import org.apache.http.HttpEntity;
+import org.apache.http.entity.ContentType;
+import org.apache.http.message.BasicHeader;
 import org.apache.http.nio.entity.NStringEntity;
 import org.apache.http.nio.protocol.HttpAsyncResponseConsumer;
 
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
@@ -36,13 +39,12 @@ import static java.util.Collections.unmodifiableMap;
  * HTTP Request to Elasticsearch.
  */
 public final class Request {
-    private static final Header[] NO_HEADERS = new Header[0];
     private final String method;
     private final String endpoint;
     private final Map<String, String> parameters = new HashMap<>();
+    private final List<Header> headers = new ArrayList<>();
 
     private HttpEntity entity;
-    private Header[] headers = NO_HEADERS;
     private HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory =
             HttpAsyncResponseConsumerFactory.DEFAULT;
 
@@ -125,21 +127,19 @@ public final class Request {
     }
 
     /**
-     * Set the headers to attach to the request.
+     * Add the provided header to the request.
      */
-    public void setHeaders(Header... headers) {
-        Objects.requireNonNull(headers, "headers cannot be null");
-        for (Header header : headers) {
-            Objects.requireNonNull(header, "header cannot be null");
-        }
-        this.headers = headers;
+    public void addHeader(String name, String value) {
+        Objects.requireNonNull(name, "header name cannot be null");
+        Objects.requireNonNull(value, "header value cannot be null");
+        this.headers.add(new ReqHeader(name, value));
     }
 
     /**
      * Headers to attach to the request.
      */
-    public Header[] getHeaders() {
-        return headers;
+    List<Header> getHeaders() {
+        return Collections.unmodifiableList(headers);
     }
 
     /**
@@ -175,13 +175,13 @@ public final class Request {
         if (entity != null) {
             b.append(", entity=").append(entity);
         }
-        if (headers.length > 0) {
+        if (headers.size() > 0) {
             b.append(", headers=");
-            for (int h = 0; h < headers.length; h++) {
+            for (int h = 0; h < headers.size(); h++) {
                 if (h != 0) {
                     b.append(',');
                 }
-                b.append(headers[h].toString());
+                b.append(headers.get(h).toString());
             }
         }
         if (httpAsyncResponseConsumerFactory != HttpAsyncResponseConsumerFactory.DEFAULT) {
@@ -204,12 +204,40 @@ public final class Request {
                 && endpoint.equals(other.endpoint)
                 && parameters.equals(other.parameters)
                 && Objects.equals(entity, other.entity)
-                && Arrays.equals(headers, other.headers)
+                && headers.equals(other.headers)
                 && httpAsyncResponseConsumerFactory.equals(other.httpAsyncResponseConsumerFactory);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(method, endpoint, parameters, entity, Arrays.hashCode(headers), httpAsyncResponseConsumerFactory);
+        return Objects.hash(method, endpoint, parameters, entity, headers.hashCode(), httpAsyncResponseConsumerFactory);
+    }
+
+    /**
+     * Custom implementation of {@link BasicHeader} that overrides equals and hashCode.
+     */
+    static final class ReqHeader extends BasicHeader {
+
+        ReqHeader(String name, String value) {
+            super(name, value);
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            if (other instanceof ReqHeader) {
+                Header otherHeader = (Header) other;
+                return Objects.equals(getName(), otherHeader.getName()) &&
+                        Objects.equals(getValue(), otherHeader.getValue());
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(getName(), getValue());
+        }
     }
 }

+ 24 - 10
client/rest/src/main/java/org/elasticsearch/client/RestClient.java

@@ -215,7 +215,7 @@ public class RestClient implements Closeable {
     @Deprecated
     public Response performRequest(String method, String endpoint, Header... headers) throws IOException {
         Request request = new Request(method, endpoint);
-        request.setHeaders(headers);
+        addHeaders(request, headers);
         return performRequest(request);
     }
 
@@ -237,7 +237,7 @@ public class RestClient implements Closeable {
     public Response performRequest(String method, String endpoint, Map<String, String> params, Header... headers) throws IOException {
         Request request = new Request(method, endpoint);
         addParameters(request, params);
-        request.setHeaders(headers);
+        addHeaders(request, headers);
         return performRequest(request);
     }
 
@@ -264,7 +264,7 @@ public class RestClient implements Closeable {
         Request request = new Request(method, endpoint);
         addParameters(request, params);
         request.setEntity(entity);
-        request.setHeaders(headers);
+        addHeaders(request, headers);
         return performRequest(request);
     }
 
@@ -305,7 +305,7 @@ public class RestClient implements Closeable {
         addParameters(request, params);
         request.setEntity(entity);
         request.setHttpAsyncResponseConsumerFactory(httpAsyncResponseConsumerFactory);
-        request.setHeaders(headers);
+        addHeaders(request, headers);
         return performRequest(request);
     }
 
@@ -325,7 +325,7 @@ public class RestClient implements Closeable {
         Request request;
         try {
             request = new Request(method, endpoint);
-            request.setHeaders(headers);
+            addHeaders(request, headers);
         } catch (Exception e) {
             responseListener.onFailure(e);
             return;
@@ -352,7 +352,7 @@ public class RestClient implements Closeable {
         try {
             request = new Request(method, endpoint);
             addParameters(request, params);
-            request.setHeaders(headers);
+            addHeaders(request, headers);
         } catch (Exception e) {
             responseListener.onFailure(e);
             return;
@@ -383,7 +383,7 @@ public class RestClient implements Closeable {
             request = new Request(method, endpoint);
             addParameters(request, params);
             request.setEntity(entity);
-            request.setHeaders(headers);
+            addHeaders(request, headers);
         } catch (Exception e) {
             responseListener.onFailure(e);
             return;
@@ -420,7 +420,7 @@ public class RestClient implements Closeable {
             addParameters(request, params);
             request.setEntity(entity);
             request.setHttpAsyncResponseConsumerFactory(httpAsyncResponseConsumerFactory);
-            request.setHeaders(headers);
+            addHeaders(request, headers);
         } catch (Exception e) {
             responseListener.onFailure(e);
             return;
@@ -539,9 +539,9 @@ public class RestClient implements Closeable {
         });
     }
 
-    private void setHeaders(HttpRequest httpRequest, Header[] requestHeaders) {
+    private void setHeaders(HttpRequest httpRequest, Collection<Header> requestHeaders) {
         // request headers override default headers, so we don't add default headers if they exist as request headers
-        final Set<String> requestNames = new HashSet<>(requestHeaders.length);
+        final Set<String> requestNames = new HashSet<>(requestHeaders.size());
         for (Header requestHeader : requestHeaders) {
             httpRequest.addHeader(requestHeader);
             requestNames.add(requestHeader.getName());
@@ -877,10 +877,24 @@ public class RestClient implements Closeable {
         }
     }
 
+    /**
+     * Add all headers from the provided varargs argument to a {@link Request}. This only exists
+     * to support methods that exist for backwards compatibility.
+     */
+    @Deprecated
+    private static void addHeaders(Request request, Header... headers) {
+        Objects.requireNonNull(headers, "headers cannot be null");
+        for (Header header : headers) {
+            Objects.requireNonNull(header, "header cannot be null");
+            request.addHeader(header.getName(), header.getValue());
+        }
+    }
+
     /**
      * Add all parameters from a map to a {@link Request}. This only exists
      * to support methods that exist for backwards compatibility.
      */
+    @Deprecated
     private static void addParameters(Request request, Map<String, String> parameters) {
         Objects.requireNonNull(parameters, "parameters cannot be null");
         for (Map.Entry<String, String> entry : parameters.entrySet()) {

+ 28 - 30
client/rest/src/test/java/org/elasticsearch/client/RequestTests.java

@@ -19,21 +19,21 @@
 
 package org.elasticsearch.client;
 
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
 import org.apache.http.Header;
 import org.apache.http.HttpEntity;
 import org.apache.http.entity.ByteArrayEntity;
 import org.apache.http.entity.ContentType;
 import org.apache.http.entity.StringEntity;
-import org.apache.http.message.BasicHeader;
 import org.apache.http.nio.entity.NStringEntity;
 import org.elasticsearch.client.HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory;
 
-import static org.junit.Assert.assertArrayEquals;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNull;
@@ -127,31 +127,33 @@ public class RequestTests extends RestClientTestCase {
         assertEquals(json, new String(os.toByteArray(), ContentType.APPLICATION_JSON.getCharset()));
     }
 
-    public void testSetHeaders() {
+    public void testAddHeader() {
         final String method = randomFrom(new String[] {"GET", "PUT", "POST", "HEAD", "DELETE"});
         final String endpoint = randomAsciiLettersOfLengthBetween(1, 10);
         Request request = new Request(method, endpoint);
 
         try {
-            request.setHeaders((Header[]) null);
+            request.addHeader(null, randomAsciiLettersOfLengthBetween(3, 10));
             fail("expected failure");
         } catch (NullPointerException e) {
-            assertEquals("headers cannot be null", e.getMessage());
+            assertEquals("header name cannot be null", e.getMessage());
         }
 
         try {
-            request.setHeaders(new Header [] {null});
+            request.addHeader(randomAsciiLettersOfLengthBetween(3, 10), null);
             fail("expected failure");
         } catch (NullPointerException e) {
-            assertEquals("header cannot be null", e.getMessage());
+            assertEquals("header value cannot be null", e.getMessage());
         }
 
-        Header[] headers = new Header[between(0, 5)];
-        for (int i = 0; i < headers.length; i++) {
-            headers[i] = new BasicHeader(randomAsciiAlphanumOfLength(3), randomAsciiAlphanumOfLength(3));
+        int numHeaders = between(0, 5);
+        List<Header> headers = new ArrayList<>();
+        for (int i = 0; i < numHeaders; i++) {
+            Header header = new Request.ReqHeader(randomAsciiAlphanumOfLengthBetween(5, 10), randomAsciiAlphanumOfLength(3));
+            headers.add(header);
+            request.addHeader(header.getName(), header.getValue());
         }
-        request.setHeaders(headers);
-        assertArrayEquals(headers, request.getHeaders());
+        assertEquals(headers, new ArrayList<>(request.getHeaders()));
     }
 
     public void testEqualsAndHashCode() {
@@ -168,7 +170,7 @@ public class RequestTests extends RestClientTestCase {
         assertNotEquals(mutant, request);
     }
 
-    private Request randomRequest() {
+    private static Request randomRequest() {
         Request request = new Request(
             randomFrom(new String[] {"GET", "PUT", "DELETE", "POST", "HEAD", "OPTIONS"}),
             randomAsciiAlphanumOfLength(5));
@@ -192,11 +194,9 @@ public class RequestTests extends RestClientTestCase {
 
         if (randomBoolean()) {
             int headerCount = between(1, 5);
-            Header[] headers = new Header[headerCount];
             for (int i = 0; i < headerCount; i++) {
-                headers[i] = new BasicHeader(randomAsciiAlphanumOfLength(3), randomAsciiAlphanumOfLength(3));
+                request.addHeader(randomAsciiAlphanumOfLength(3), randomAsciiAlphanumOfLength(3));
             }
-            request.setHeaders(headers);
         }
 
         if (randomBoolean()) {
@@ -206,13 +206,13 @@ public class RequestTests extends RestClientTestCase {
         return request;
     }
 
-    private Request copy(Request request) {
+    private static Request copy(Request request) {
         Request copy = new Request(request.getMethod(), request.getEndpoint());
         copyMutables(request, copy);
         return copy;
     }
 
-    private Request mutate(Request request) {
+    private static Request mutate(Request request) {
         if (randomBoolean()) {
             // Mutate request or method but keep everything else constant
             Request mutant = randomBoolean()
@@ -231,11 +231,7 @@ public class RequestTests extends RestClientTestCase {
             mutant.setJsonEntity("mutant"); // randomRequest can't produce this value
             return mutant;
         case 2:
-            if (mutant.getHeaders().length > 0) {
-                mutant.setHeaders(new Header[0]);
-            } else {
-                mutant.setHeaders(new BasicHeader("extra", "m"));
-            }
+            mutant.addHeader("extra", "m");
             return mutant;
         case 3:
             mutant.setHttpAsyncResponseConsumerFactory(new HeapBufferedResponseConsumerFactory(5));
@@ -245,12 +241,14 @@ public class RequestTests extends RestClientTestCase {
         }
     }
 
-    private void copyMutables(Request from, Request to) {
+    private static void copyMutables(Request from, Request to) {
         for (Map.Entry<String, String> param : from.getParameters().entrySet()) {
             to.addParameter(param.getKey(), param.getValue());
         }
         to.setEntity(from.getEntity());
-        to.setHeaders(from.getHeaders());
+        for (Header header : from.getHeaders()) {
+            to.addHeader(header.getName(), header.getValue());
+        }
         to.setHttpAsyncResponseConsumerFactory(from.getHttpAsyncResponseConsumerFactory());
     }
 }

+ 3 - 2
client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostIntegTests.java

@@ -29,7 +29,6 @@ import org.apache.http.HttpHost;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.UsernamePasswordCredentials;
 import org.apache.http.entity.ContentType;
-import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.BasicCredentialsProvider;
 import org.apache.http.impl.client.TargetAuthenticationStrategy;
 import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
@@ -379,7 +378,9 @@ public class RestClientSingleHostIntegTests extends RestClientTestCase {
         String requestBody = "{ \"field\": \"value\" }";
         Request request = new Request(method, "/" + statusCode);
         request.setJsonEntity(requestBody);
-        request.setHeaders(headers);
+        for (Header header : headers) {
+            request.addHeader(header.getName(), header.getValue());
+        }
         Response esResponse;
         try {
             esResponse = restClient.performRequest(request);

+ 7 - 5
client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostTests.java

@@ -312,7 +312,7 @@ public class RestClientSingleHostTests extends RestClientTestCase {
     }
 
     /**
-     * @deprecated will remove method in 7.0 but needs tests until then. Replaced by {@link RequestTests#testSetHeaders()}.
+     * @deprecated will remove method in 7.0 but needs tests until then. Replaced by {@link RequestTests#testAddHeaders()}.
      */
     @Deprecated
     public void tesPerformRequestOldStyleNullHeaders() throws IOException {
@@ -333,7 +333,7 @@ public class RestClientSingleHostTests extends RestClientTestCase {
     }
 
     /**
-     * @deprecated will remove method in 7.0 but needs tests until then. Replaced by {@link RequestTests#testSetParameters()}.
+     * @deprecated will remove method in 7.0 but needs tests until then. Replaced by {@link RequestTests#testAddParameters()}.
      */
     @Deprecated
     public void testPerformRequestOldStyleWithNullParams() throws IOException {
@@ -362,7 +362,9 @@ public class RestClientSingleHostTests extends RestClientTestCase {
             final Header[] requestHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header");
             final int statusCode = randomStatusCode(getRandom());
             Request request = new Request(method, "/" + statusCode);
-            request.setHeaders(requestHeaders);
+            for (Header requestHeader : requestHeaders) {
+                request.addHeader(requestHeader.getName(), requestHeader.getValue());
+            }
             Response esResponse;
             try {
                 esResponse = restClient.performRequest(request);
@@ -436,9 +438,9 @@ public class RestClientSingleHostTests extends RestClientTestCase {
         final Set<String> uniqueNames = new HashSet<>();
         if (randomBoolean()) {
             Header[] headers = RestClientTestUtil.randomHeaders(getRandom(), "Header");
-            request.setHeaders(headers);
             for (Header header : headers) {
-                expectedRequest.addHeader(header);
+                request.addHeader(header.getName(), header.getValue());
+                expectedRequest.addHeader(new Request.ReqHeader(header.getName(), header.getValue()));
                 uniqueNames.add(header.getName());
             }
         }

+ 1 - 1
client/rest/src/test/java/org/elasticsearch/client/RestClientTests.java

@@ -131,7 +131,7 @@ public class RestClientTests extends RestClientTestCase {
     }
 
     /**
-     * @deprecated will remove method in 7.0 but needs tests until then. Replaced by {@link RequestTests#testSetHeaders()}.
+     * @deprecated will remove method in 7.0 but needs tests until then. Replaced by {@link RequestTests#testAddHeader()}.
      */
     @Deprecated
     public void testPerformOldStyleAsyncWithNullHeaders() throws Exception {

+ 2 - 7
client/rest/src/test/java/org/elasticsearch/client/documentation/RestClientDocumentation.java

@@ -27,9 +27,7 @@ import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.UsernamePasswordCredentials;
 import org.apache.http.client.CredentialsProvider;
 import org.apache.http.client.config.RequestConfig;
-import org.apache.http.entity.BasicHttpEntity;
 import org.apache.http.entity.ContentType;
-import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.BasicCredentialsProvider;
 import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
 import org.apache.http.impl.nio.reactor.IOReactorConfig;
@@ -52,8 +50,6 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.security.KeyStore;
-import java.util.Collections;
-import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 
 /**
@@ -176,9 +172,8 @@ public class RestClientDocumentation {
             request.setJsonEntity("{\"json\":\"text\"}");
             //end::rest-client-body-shorter
             //tag::rest-client-headers
-            request.setHeaders(
-                    new BasicHeader("Accept", "text/plain"),
-                    new BasicHeader("Cache-Control", "no-cache"));
+            request.addHeader("Accept", "text/plain");
+            request.addHeader("Cache-Control", "no-cache");
             //end::rest-client-headers
             //tag::rest-client-response-consumer
             request.setHttpAsyncResponseConsumerFactory(

+ 1 - 1
client/test/src/main/java/org/elasticsearch/client/RestClientTestUtil.java

@@ -100,7 +100,7 @@ final class RestClientTestUtil {
             if (random.nextBoolean()) {
                 headerName = headerName + i;
             }
-            headers[i] = new BasicHeader(headerName, RandomStrings.randomAsciiOfLengthBetween(random, 3, 10));
+            headers[i] = new BasicHeader(headerName, RandomStrings.randomAsciiLettersOfLengthBetween(random, 3, 10));
         }
         return headers;
     }

+ 1 - 1
docs/java-rest/low-level/usage.asciidoc

@@ -271,7 +271,7 @@ a `ContentType` of `application/json`.
 include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-body-shorter]
 --------------------------------------------------
 
-And you can set a list of headers to send with the request:
+And you can add one or more headers to send with the request:
 
 ["source","java",subs="attributes,callouts,macros"]
 --------------------------------------------------

+ 2 - 3
qa/smoke-test-http/src/test/java/org/elasticsearch/http/ContextAndHeaderTransportIT.java

@@ -19,7 +19,6 @@
 
 package org.elasticsearch.http;
 
-import org.apache.http.message.BasicHeader;
 import org.apache.lucene.util.SetOnce;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.ActionRequest;
@@ -222,8 +221,8 @@ public class ContextAndHeaderTransportIT extends HttpSmokeTestCase {
     public void testThatRelevantHttpHeadersBecomeRequestHeaders() throws IOException {
         final String IRRELEVANT_HEADER = "SomeIrrelevantHeader";
         Request request = new Request("GET", "/" + queryIndex + "/_search");
-        request.setHeaders(new BasicHeader(CUSTOM_HEADER, randomHeaderValue),
-                new BasicHeader(IRRELEVANT_HEADER, randomHeaderValue));
+        request.addHeader(CUSTOM_HEADER, randomHeaderValue);
+        request.addHeader(IRRELEVANT_HEADER, randomHeaderValue);
         Response response = getRestClient().performRequest(request);
         assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
         List<RequestAndHeaders> searchRequests = getRequests(SearchRequest.class);

+ 2 - 2
qa/smoke-test-http/src/test/java/org/elasticsearch/http/CorsNotSetIT.java

@@ -19,7 +19,6 @@
 
 package org.elasticsearch.http;
 
-import org.apache.http.message.BasicHeader;
 import org.elasticsearch.client.Request;
 import org.elasticsearch.client.Response;
 
@@ -33,7 +32,8 @@ public class CorsNotSetIT extends HttpSmokeTestCase {
     public void testCorsSettingDefaultBehaviourDoesNotReturnAnything() throws IOException {
         String corsValue = "http://localhost:9200";
         Request request = new Request("GET", "/");
-        request.setHeaders(new BasicHeader("User-Agent", "Mozilla Bar"), new BasicHeader("Origin", corsValue));
+        request.addHeader("User-Agent", "Mozilla Bar");
+        request.addHeader("Origin", corsValue);
         Response response = getRestClient().performRequest(request);
         assertThat(response.getStatusLine().getStatusCode(), is(200));
         assertThat(response.getHeader("Access-Control-Allow-Origin"), nullValue());

+ 28 - 25
qa/smoke-test-http/src/test/java/org/elasticsearch/http/CorsRegexIT.java

@@ -18,7 +18,6 @@
  */
 package org.elasticsearch.http;
 
-import org.apache.http.message.BasicHeader;
 import org.elasticsearch.client.Request;
 import org.elasticsearch.client.Response;
 import org.elasticsearch.client.ResponseException;
@@ -53,25 +52,29 @@ public class CorsRegexIT extends HttpSmokeTestCase {
     }
 
     public void testThatRegularExpressionWorksOnMatch() throws IOException {
-        String corsValue = "http://localhost:9200";
-        Request request = new Request("GET", "/");
-        request.setHeaders(new BasicHeader("User-Agent", "Mozilla Bar"),
-                new BasicHeader("Origin", corsValue));
-        Response response = getRestClient().performRequest(request);
-        assertResponseWithOriginheader(response, corsValue);
-
-        corsValue = "https://localhost:9201";
-        request.setHeaders(new BasicHeader("User-Agent", "Mozilla Bar"),
-                new BasicHeader("Origin", corsValue));
-        response = getRestClient().performRequest(request);
-        assertResponseWithOriginheader(response, corsValue);
-        assertThat(response.getHeader("Access-Control-Allow-Credentials"), is("true"));
+        {
+            String corsValue = "http://localhost:9200";
+            Request request = new Request("GET", "/");
+            request.addHeader("User-Agent", "Mozilla Bar");
+            request.addHeader("Origin", corsValue);
+            Response response = getRestClient().performRequest(request);
+            assertResponseWithOriginHeader(response, corsValue);
+        }
+        {
+            String corsValue = "https://localhost:9201";
+            Request request = new Request("GET", "/");
+            request.addHeader("User-Agent", "Mozilla Bar");
+            request.addHeader("Origin", corsValue);
+            Response response = getRestClient().performRequest(request);
+            assertResponseWithOriginHeader(response, corsValue);
+            assertThat(response.getHeader("Access-Control-Allow-Credentials"), is("true"));
+        }
     }
 
     public void testThatRegularExpressionReturnsForbiddenOnNonMatch() throws IOException {
         Request request = new Request("GET", "/");
-        request.setHeaders(new BasicHeader("User-Agent", "Mozilla Bar"),
-                new BasicHeader("Origin", "http://evil-host:9200"));
+        request.addHeader("User-Agent", "Mozilla Bar");
+        request.addHeader("Origin", "http://evil-host:9200");
         try {
             getRestClient().performRequest(request);
             fail("request should have failed");
@@ -85,7 +88,7 @@ public class CorsRegexIT extends HttpSmokeTestCase {
 
     public void testThatSendingNoOriginHeaderReturnsNoAccessControlHeader() throws IOException {
         Request request = new Request("GET", "/");
-        request.setHeaders(new BasicHeader("User-Agent", "Mozilla Bar"));
+        request.addHeader("User-Agent", "Mozilla Bar");
         Response response = getRestClient().performRequest(request);
         assertThat(response.getStatusLine().getStatusCode(), is(200));
         assertThat(response.getHeader("Access-Control-Allow-Origin"), nullValue());
@@ -100,20 +103,20 @@ public class CorsRegexIT extends HttpSmokeTestCase {
     public void testThatPreFlightRequestWorksOnMatch() throws IOException {
         String corsValue = "http://localhost:9200";
         Request request = new Request("OPTIONS", "/");
-        request.setHeaders(new BasicHeader("User-Agent", "Mozilla Bar"),
-                new BasicHeader("Origin", corsValue),
-                new BasicHeader("Access-Control-Request-Method", "GET"));
+        request.addHeader("User-Agent", "Mozilla Bar");
+        request.addHeader("Origin", corsValue);
+        request.addHeader("Access-Control-Request-Method", "GET");
         Response response = getRestClient().performRequest(request);
-        assertResponseWithOriginheader(response, corsValue);
+        assertResponseWithOriginHeader(response, corsValue);
         assertNotNull(response.getHeader("Access-Control-Allow-Methods"));
     }
 
     public void testThatPreFlightRequestReturnsNullOnNonMatch() throws IOException {
         String corsValue = "http://evil-host:9200";
         Request request = new Request("OPTIONS", "/");
-        request.setHeaders(new BasicHeader("User-Agent", "Mozilla Bar"),
-                new BasicHeader("Origin", corsValue),
-                new BasicHeader("Access-Control-Request-Method", "GET"));
+        request.addHeader("User-Agent", "Mozilla Bar");
+        request.addHeader("Origin", corsValue);
+        request.addHeader("Access-Control-Request-Method", "GET");
         try {
             getRestClient().performRequest(request);
             fail("request should have failed");
@@ -126,7 +129,7 @@ public class CorsRegexIT extends HttpSmokeTestCase {
         }
     }
 
-    protected static void assertResponseWithOriginheader(Response response, String expectedCorsHeader) {
+    private static void assertResponseWithOriginHeader(Response response, String expectedCorsHeader) {
         assertThat(response.getStatusLine().getStatusCode(), is(200));
         assertThat(response.getHeader("Access-Control-Allow-Origin"), is(expectedCorsHeader));
     }

+ 1 - 2
qa/smoke-test-http/src/test/java/org/elasticsearch/http/HttpCompressionIT.java

@@ -19,7 +19,6 @@
 package org.elasticsearch.http;
 
 import org.apache.http.HttpHeaders;
-import org.apache.http.message.BasicHeader;
 import org.elasticsearch.client.Request;
 import org.elasticsearch.client.Response;
 import org.elasticsearch.test.rest.ESRestTestCase;
@@ -39,7 +38,7 @@ public class HttpCompressionIT extends ESRestTestCase {
 
     public void testCompressesResponseIfRequested() throws IOException {
         Request request = new Request("GET", "/");
-        request.setHeaders(new BasicHeader(HttpHeaders.ACCEPT_ENCODING, GZIP_ENCODING));
+        request.addHeader(HttpHeaders.ACCEPT_ENCODING, GZIP_ENCODING);
         Response response = client().performRequest(request);
         assertEquals(200, response.getStatusLine().getStatusCode());
         assertEquals(GZIP_ENCODING, response.getHeader(HttpHeaders.CONTENT_ENCODING));

+ 1 - 2
qa/smoke-test-http/src/test/java/org/elasticsearch/http/NoHandlerIT.java

@@ -19,7 +19,6 @@
 
 package org.elasticsearch.http;
 
-import org.apache.http.message.BasicHeader;
 import org.apache.http.util.EntityUtils;
 import org.elasticsearch.client.Request;
 import org.elasticsearch.client.Response;
@@ -47,7 +46,7 @@ public class NoHandlerIT extends HttpSmokeTestCase {
     private void runTestNoHandlerRespectsAcceptHeader(
             final String accept, final String contentType, final String expect) throws IOException {
         Request request = new Request("GET", "/foo/bar/baz/qux/quux");
-        request.setHeaders(new BasicHeader("Accept", accept));
+        request.addHeader("Accept", accept);
         final ResponseException e = expectThrows(ResponseException.class,
                         () -> getRestClient().performRequest(request));
 

+ 2 - 3
qa/smoke-test-http/src/test/java/org/elasticsearch/http/ResponseHeaderPluginIT.java

@@ -18,7 +18,6 @@
  */
 package org.elasticsearch.http;
 
-import org.apache.http.message.BasicHeader;
 import org.elasticsearch.client.Request;
 import org.elasticsearch.client.Response;
 import org.elasticsearch.client.ResponseException;
@@ -26,8 +25,8 @@ import org.elasticsearch.plugins.Plugin;
 import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
 import org.elasticsearch.test.ESIntegTestCase.Scope;
 
-import java.util.ArrayList;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Collection;
 
 import static org.hamcrest.Matchers.equalTo;
@@ -62,7 +61,7 @@ public class ResponseHeaderPluginIT extends HttpSmokeTestCase {
         }
 
         Request request = new Request("GET", "/_protected");
-        request.setHeaders(new BasicHeader("Secret", "password"));
+        request.addHeader("Secret", "password");
         Response authResponse = getRestClient().performRequest(request);
         assertThat(authResponse.getStatusLine().getStatusCode(), equalTo(200));
         assertThat(authResponse.getHeader("Secret"), equalTo("granted"));

+ 1 - 2
test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ESClientYamlSuiteTestCase.java

@@ -22,7 +22,6 @@ package org.elasticsearch.test.rest.yaml;
 import com.carrotsearch.randomizedtesting.RandomizedTest;
 import org.apache.http.HttpHost;
 import org.apache.http.entity.StringEntity;
-import org.apache.http.message.BasicHeader;
 import org.elasticsearch.Version;
 import org.elasticsearch.client.Request;
 import org.elasticsearch.client.Response;
@@ -323,7 +322,7 @@ public abstract class ESClientYamlSuiteTestCase extends ESRestTestCase {
         if (useDefaultNumberOfShards == false
                 && testCandidate.getTestSection().getSkipSection().getFeatures().contains("default_shards") == false) {
             final Request request = new Request("PUT", "/_template/global");
-            request.setHeaders(new BasicHeader("Content-Type", XContentType.JSON.mediaTypeWithoutParameters()));
+            request.addHeader("Content-Type", XContentType.JSON.mediaTypeWithoutParameters());
             request.setEntity(new StringEntity("{\"index_patterns\":[\"*\"],\"settings\":{\"index.number_of_shards\":2}}"));
             adminClient().performRequest(request);
         }

+ 1 - 6
x-pack/qa/sql/security/src/test/java/org/elasticsearch/xpack/qa/sql/security/RestSqlSecurityIT.java

@@ -5,20 +5,16 @@
  */
 package org.elasticsearch.xpack.qa.sql.security;
 
-import org.apache.http.Header;
 import org.apache.http.HttpEntity;
 import org.apache.http.entity.ContentType;
 import org.apache.http.entity.StringEntity;
-import org.apache.http.message.BasicHeader;
 import org.elasticsearch.client.Request;
 import org.elasticsearch.client.Response;
 import org.elasticsearch.client.ResponseException;
 import org.elasticsearch.common.Nullable;
-import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.xcontent.XContentHelper;
 import org.elasticsearch.common.xcontent.json.JsonXContent;
 import org.elasticsearch.test.NotEqualMessageBuilder;
-import org.elasticsearch.xpack.qa.sql.security.SqlSecurityTestCase.AuditLogAsserter;
 import org.hamcrest.Matcher;
 import org.hamcrest.Matchers;
 
@@ -30,7 +26,6 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.TreeMap;
 import java.util.stream.Collectors;
 
 import static org.elasticsearch.xpack.qa.sql.rest.RestSqlTestCase.columnInfo;
@@ -182,7 +177,7 @@ public class RestSqlSecurityIT extends SqlSecurityTestCase {
                 request.addParameter("mode", mode);
             }
             if (asUser != null) {
-                request.setHeaders(new BasicHeader("es-security-runas-user", asUser));
+                request.addHeader("es-security-runas-user", asUser);
             }
             request.setEntity(entity);
             return toMap(client().performRequest(request));

+ 4 - 8
x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java

@@ -6,12 +6,9 @@
 package org.elasticsearch.xpack.qa.sql.rest;
 
 import com.fasterxml.jackson.core.io.JsonStringEncoder;
-
-import org.apache.http.Header;
 import org.apache.http.HttpEntity;
 import org.apache.http.entity.ContentType;
 import org.apache.http.entity.StringEntity;
-import org.apache.http.message.BasicHeader;
 import org.elasticsearch.client.Request;
 import org.elasticsearch.client.Response;
 import org.elasticsearch.client.ResponseException;
@@ -321,10 +318,9 @@ public abstract class RestSqlTestCase extends ESRestTestCase implements ErrorsTe
         if (false == mode.isEmpty()) {
             request.addParameter("mode", mode);        // JDBC or PLAIN mode
         }
-        request.setHeaders(randomFrom(
-            new Header[] {},
-            new Header[] {new BasicHeader("Accept", "*/*")},
-            new Header[] {new BasicHeader("Accpet", "application/json")}));
+        if (randomBoolean()) {
+            request.addHeader("Accept", randomFrom("*/*", "application/json"));
+        }
         request.setEntity(sql);
         Response response = client().performRequest(request);
         try (InputStream content = response.getEntity().getContent()) {
@@ -540,7 +536,7 @@ public abstract class RestSqlTestCase extends ESRestTestCase implements ErrorsTe
         Request request = new Request("POST", "/_xpack/sql" + suffix);
         request.addParameter("error_trace", "true");
         request.setEntity(entity);
-        request.setHeaders(new BasicHeader("Accept", accept));
+        request.addHeader("Accept", accept);
         Response response = client().performRequest(request);
         return new Tuple<>(
                 Streams.copyToString(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)),