diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
index 8537bf3b450..fc74a43dd80 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
@@ -279,6 +279,17 @@ public class RestHighLevelClient implements Closeable {
*
* See Bulk API on elastic.co
*/
+ public final BulkResponse bulk(BulkRequest bulkRequest, RequestOptions options) throws IOException {
+ return performRequestAndParseEntity(bulkRequest, RequestConverters::bulk, options, BulkResponse::fromXContent, emptySet());
+ }
+
+ /**
+ * Executes a bulk request using the Bulk API
+ *
+ * See Bulk API on elastic.co
+ * @deprecated Prefer {@link #bulk(BulkRequest, RequestOptions)}
+ */
+ @Deprecated
public final BulkResponse bulk(BulkRequest bulkRequest, Header... headers) throws IOException {
return performRequestAndParseEntity(bulkRequest, RequestConverters::bulk, BulkResponse::fromXContent, emptySet(), headers);
}
@@ -288,6 +299,17 @@ public class RestHighLevelClient implements Closeable {
*
* See Bulk API on elastic.co
*/
+ public final void bulkAsync(BulkRequest bulkRequest, RequestOptions options, ActionListener listener) {
+ performRequestAsyncAndParseEntity(bulkRequest, RequestConverters::bulk, options, BulkResponse::fromXContent, listener, emptySet());
+ }
+
+ /**
+ * Asynchronously executes a bulk request using the Bulk API
+ *
+ * See Bulk API on elastic.co
+ * @deprecated Prefer {@link #bulkAsync(BulkRequest, RequestOptions, ActionListener)}
+ */
+ @Deprecated
public final void bulkAsync(BulkRequest bulkRequest, ActionListener listener, Header... headers) {
performRequestAsyncAndParseEntity(bulkRequest, RequestConverters::bulk, BulkResponse::fromXContent, listener, emptySet(), headers);
}
@@ -584,6 +606,7 @@ public class RestHighLevelClient implements Closeable {
FieldCapabilitiesResponse::fromXContent, listener, emptySet(), headers);
}
+ @Deprecated
protected final Resp performRequestAndParseEntity(Req request,
CheckedFunction requestConverter,
CheckedFunction entityParser,
@@ -591,16 +614,34 @@ public class RestHighLevelClient implements Closeable {
return performRequest(request, requestConverter, (response) -> parseEntity(response.getEntity(), entityParser), ignores, headers);
}
+ protected final Resp performRequestAndParseEntity(Req request,
+ CheckedFunction requestConverter,
+ RequestOptions options,
+ CheckedFunction entityParser,
+ Set ignores) throws IOException {
+ return performRequest(request, requestConverter, options,
+ response -> parseEntity(response.getEntity(), entityParser), ignores);
+ }
+
+ @Deprecated
protected final Resp performRequest(Req request,
CheckedFunction requestConverter,
CheckedFunction responseConverter,
Set ignores, Header... headers) throws IOException {
+ return performRequest(request, requestConverter, optionsForHeaders(headers), responseConverter, ignores);
+ }
+
+ protected final Resp performRequest(Req request,
+ CheckedFunction requestConverter,
+ RequestOptions options,
+ CheckedFunction responseConverter,
+ Set ignores) throws IOException {
ActionRequestValidationException validationException = request.validate();
if (validationException != null) {
throw validationException;
}
Request req = requestConverter.apply(request);
- addHeaders(req, headers);
+ req.setOptions(options);
Response response;
try {
response = client.performRequest(req);
@@ -626,6 +667,7 @@ public class RestHighLevelClient implements Closeable {
}
}
+ @Deprecated
protected final void performRequestAsyncAndParseEntity(Req request,
CheckedFunction requestConverter,
CheckedFunction entityParser,
@@ -634,10 +676,28 @@ public class RestHighLevelClient implements Closeable {
listener, ignores, headers);
}
+ protected final void performRequestAsyncAndParseEntity(Req request,
+ CheckedFunction requestConverter,
+ RequestOptions options,
+ CheckedFunction entityParser,
+ ActionListener listener, Set ignores) {
+ performRequestAsync(request, requestConverter, options,
+ response -> parseEntity(response.getEntity(), entityParser), listener, ignores);
+ }
+
+ @Deprecated
protected final void performRequestAsync(Req request,
CheckedFunction requestConverter,
CheckedFunction responseConverter,
ActionListener listener, Set ignores, Header... headers) {
+ performRequestAsync(request, requestConverter, optionsForHeaders(headers), responseConverter, listener, ignores);
+ }
+
+ protected final void performRequestAsync(Req request,
+ CheckedFunction requestConverter,
+ RequestOptions options,
+ CheckedFunction responseConverter,
+ ActionListener listener, Set ignores) {
ActionRequestValidationException validationException = request.validate();
if (validationException != null) {
listener.onFailure(validationException);
@@ -650,19 +710,12 @@ public class RestHighLevelClient implements Closeable {
listener.onFailure(e);
return;
}
- addHeaders(req, headers);
+ req.setOptions(options);
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 ResponseListener wrapResponseListener(CheckedFunction responseConverter,
ActionListener actionListener, Set ignores) {
return new ResponseListener() {
@@ -746,6 +799,15 @@ public class RestHighLevelClient implements Closeable {
}
}
+ private static RequestOptions optionsForHeaders(Header[] headers) {
+ RequestOptions.Builder options = RequestOptions.DEFAULT.toBuilder();
+ for (Header header : headers) {
+ Objects.requireNonNull(header, "header cannot be null");
+ options.addHeader(header.getName(), header.getValue());
+ }
+ return options.build();
+ }
+
static boolean convertExistsResponse(Response response) {
return response.getStatusLine().getStatusCode() == 200;
}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/CustomRestHighLevelClientTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/CustomRestHighLevelClientTests.java
index 0bd6ecef8fb..3d1db23da16 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/CustomRestHighLevelClientTests.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/CustomRestHighLevelClientTests.java
@@ -26,7 +26,6 @@ import org.apache.http.RequestLine;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
-import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicRequestLine;
import org.apache.http.message.BasicStatusLine;
import org.apache.lucene.util.BytesRef;
@@ -48,11 +47,13 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collections;
-import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
import java.util.stream.Collectors;
import static java.util.Collections.emptySet;
-import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.hasSize;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
@@ -73,12 +74,12 @@ public class CustomRestHighLevelClientTests extends ESTestCase {
final RestClient restClient = mock(RestClient.class);
restHighLevelClient = new CustomRestClient(restClient);
- doAnswer(inv -> mockPerformRequest(((Request) inv.getArguments()[0]).getHeaders().iterator().next()))
+ doAnswer(inv -> mockPerformRequest((Request) inv.getArguments()[0]))
.when(restClient)
.performRequest(any(Request.class));
doAnswer(inv -> mockPerformRequestAsync(
- ((Request) inv.getArguments()[0]).getHeaders().iterator().next(),
+ ((Request) inv.getArguments()[0]),
(ResponseListener) inv.getArguments()[1]))
.when(restClient)
.performRequestAsync(any(Request.class), any(ResponseListener.class));
@@ -87,26 +88,32 @@ public class CustomRestHighLevelClientTests extends ESTestCase {
public void testCustomEndpoint() throws IOException {
final MainRequest request = new MainRequest();
- final Header header = new BasicHeader("node_name", randomAlphaOfLengthBetween(1, 10));
+ String nodeName = randomAlphaOfLengthBetween(1, 10);
- MainResponse response = restHighLevelClient.custom(request, header);
- assertEquals(header.getValue(), response.getNodeName());
+ MainResponse response = restHighLevelClient.custom(request, optionsForNodeName(nodeName));
+ assertEquals(nodeName, response.getNodeName());
- response = restHighLevelClient.customAndParse(request, header);
- assertEquals(header.getValue(), response.getNodeName());
+ response = restHighLevelClient.customAndParse(request, optionsForNodeName(nodeName));
+ assertEquals(nodeName, response.getNodeName());
}
public void testCustomEndpointAsync() throws Exception {
final MainRequest request = new MainRequest();
- final Header header = new BasicHeader("node_name", randomAlphaOfLengthBetween(1, 10));
+ String nodeName = randomAlphaOfLengthBetween(1, 10);
PlainActionFuture future = PlainActionFuture.newFuture();
- restHighLevelClient.customAsync(request, future, header);
- assertEquals(header.getValue(), future.get().getNodeName());
+ restHighLevelClient.customAsync(request, optionsForNodeName(nodeName), future);
+ assertEquals(nodeName, future.get().getNodeName());
future = PlainActionFuture.newFuture();
- restHighLevelClient.customAndParseAsync(request, future, header);
- assertEquals(header.getValue(), future.get().getNodeName());
+ restHighLevelClient.customAndParseAsync(request, optionsForNodeName(nodeName), future);
+ assertEquals(nodeName, future.get().getNodeName());
+ }
+
+ private static RequestOptions optionsForNodeName(String nodeName) {
+ RequestOptions.Builder options = RequestOptions.DEFAULT.toBuilder();
+ options.addHeader("node_name", nodeName);
+ return options.build();
}
/**
@@ -115,27 +122,27 @@ public class CustomRestHighLevelClientTests extends ESTestCase {
*/
@SuppressForbidden(reason = "We're forced to uses Class#getDeclaredMethods() here because this test checks protected methods")
public void testMethodsVisibility() throws ClassNotFoundException {
- final String[] methodNames = new String[]{"performRequest",
- "performRequestAsync",
+ final String[] methodNames = new String[]{"parseEntity",
+ "parseResponseException",
+ "performRequest",
"performRequestAndParseEntity",
- "performRequestAsyncAndParseEntity",
- "parseEntity",
- "parseResponseException"};
+ "performRequestAsync",
+ "performRequestAsyncAndParseEntity"};
- final List protectedMethods = Arrays.stream(RestHighLevelClient.class.getDeclaredMethods())
+ final Set protectedMethods = Arrays.stream(RestHighLevelClient.class.getDeclaredMethods())
.filter(method -> Modifier.isProtected(method.getModifiers()))
.map(Method::getName)
- .collect(Collectors.toList());
+ .collect(Collectors.toCollection(TreeSet::new));
- assertThat(protectedMethods, containsInAnyOrder(methodNames));
+ assertThat(protectedMethods, contains(methodNames));
}
/**
- * Mocks the asynchronous request execution by calling the {@link #mockPerformRequest(Header)} method.
+ * Mocks the asynchronous request execution by calling the {@link #mockPerformRequest(Request)} method.
*/
- private Void mockPerformRequestAsync(Header httpHeader, ResponseListener responseListener) {
+ private Void mockPerformRequestAsync(Request request, ResponseListener responseListener) {
try {
- responseListener.onSuccess(mockPerformRequest(httpHeader));
+ responseListener.onSuccess(mockPerformRequest(request));
} catch (IOException e) {
responseListener.onFailure(e);
}
@@ -145,7 +152,9 @@ public class CustomRestHighLevelClientTests extends ESTestCase {
/**
* Mocks the synchronous request execution like if it was executed by Elasticsearch.
*/
- private Response mockPerformRequest(Header httpHeader) throws IOException {
+ private Response mockPerformRequest(Request request) throws IOException {
+ assertThat(request.getOptions().getHeaders(), hasSize(1));
+ Header httpHeader = request.getOptions().getHeaders().get(0);
final Response mockResponse = mock(Response.class);
when(mockResponse.getHost()).thenReturn(new HttpHost("localhost", 9200));
@@ -171,20 +180,20 @@ public class CustomRestHighLevelClientTests extends ESTestCase {
super(restClient, RestClient::close, Collections.emptyList());
}
- MainResponse custom(MainRequest mainRequest, Header... headers) throws IOException {
- return performRequest(mainRequest, this::toRequest, this::toResponse, emptySet(), headers);
+ MainResponse custom(MainRequest mainRequest, RequestOptions options) throws IOException {
+ return performRequest(mainRequest, this::toRequest, options, this::toResponse, emptySet());
}
- MainResponse customAndParse(MainRequest mainRequest, Header... headers) throws IOException {
- return performRequestAndParseEntity(mainRequest, this::toRequest, MainResponse::fromXContent, emptySet(), headers);
+ MainResponse customAndParse(MainRequest mainRequest, RequestOptions options) throws IOException {
+ return performRequestAndParseEntity(mainRequest, this::toRequest, options, MainResponse::fromXContent, emptySet());
}
- void customAsync(MainRequest mainRequest, ActionListener listener, Header... headers) {
- performRequestAsync(mainRequest, this::toRequest, this::toResponse, listener, emptySet(), headers);
+ void customAsync(MainRequest mainRequest, RequestOptions options, ActionListener listener) {
+ performRequestAsync(mainRequest, this::toRequest, options, this::toResponse, listener, emptySet());
}
- void customAndParseAsync(MainRequest mainRequest, ActionListener listener, Header... headers) {
- performRequestAsyncAndParseEntity(mainRequest, this::toRequest, MainResponse::fromXContent, listener, emptySet(), headers);
+ void customAndParseAsync(MainRequest mainRequest, RequestOptions options, ActionListener listener) {
+ performRequestAsyncAndParseEntity(mainRequest, this::toRequest, options, MainResponse::fromXContent, listener, emptySet());
}
Request toRequest(MainRequest mainRequest) throws IOException {
diff --git a/client/rest/src/main/java/org/elasticsearch/client/Request.java b/client/rest/src/main/java/org/elasticsearch/client/Request.java
index 59b82e5bf96..a6febe91ae8 100644
--- a/client/rest/src/main/java/org/elasticsearch/client/Request.java
+++ b/client/rest/src/main/java/org/elasticsearch/client/Request.java
@@ -19,17 +19,11 @@
package org.elasticsearch.client;
-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.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -42,11 +36,9 @@ public final class Request {
private final String method;
private final String endpoint;
private final Map parameters = new HashMap<>();
- private final List headers = new ArrayList<>();
private HttpEntity entity;
- private HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory =
- HttpAsyncResponseConsumerFactory.DEFAULT;
+ private RequestOptions options = RequestOptions.DEFAULT;
/**
* Create the {@linkplain Request}.
@@ -127,40 +119,29 @@ public final class Request {
}
/**
- * Add the provided header to the request.
+ * Set the portion of an HTTP request to Elasticsearch that can be
+ * manipulated without changing Elasticsearch's behavior.
*/
- 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));
+ public void setOptions(RequestOptions options) {
+ Objects.requireNonNull(options, "options cannot be null");
+ this.options = options;
}
/**
- * Headers to attach to the request.
+ * Set the portion of an HTTP request to Elasticsearch that can be
+ * manipulated without changing Elasticsearch's behavior.
*/
- List getHeaders() {
- return Collections.unmodifiableList(headers);
+ public void setOptions(RequestOptions.Builder options) {
+ Objects.requireNonNull(options, "options cannot be null");
+ this.options = options.build();
}
/**
- * set the {@link HttpAsyncResponseConsumerFactory} used to create one
- * {@link HttpAsyncResponseConsumer} callback per retry. Controls how the
- * response body gets streamed from a non-blocking HTTP connection on the
- * client side.
+ * Get the portion of an HTTP request to Elasticsearch that can be
+ * manipulated without changing Elasticsearch's behavior.
*/
- public void setHttpAsyncResponseConsumerFactory(HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory) {
- this.httpAsyncResponseConsumerFactory =
- Objects.requireNonNull(httpAsyncResponseConsumerFactory, "httpAsyncResponseConsumerFactory cannot be null");
- }
-
- /**
- * The {@link HttpAsyncResponseConsumerFactory} used to create one
- * {@link HttpAsyncResponseConsumer} callback per retry. Controls how the
- * response body gets streamed from a non-blocking HTTP connection on the
- * client side.
- */
- public HttpAsyncResponseConsumerFactory getHttpAsyncResponseConsumerFactory() {
- return httpAsyncResponseConsumerFactory;
+ public RequestOptions getOptions() {
+ return options;
}
@Override
@@ -175,18 +156,7 @@ public final class Request {
if (entity != null) {
b.append(", entity=").append(entity);
}
- if (headers.size() > 0) {
- b.append(", headers=");
- for (int h = 0; h < headers.size(); h++) {
- if (h != 0) {
- b.append(',');
- }
- b.append(headers.get(h).toString());
- }
- }
- if (httpAsyncResponseConsumerFactory != HttpAsyncResponseConsumerFactory.DEFAULT) {
- b.append(", consumerFactory=").append(httpAsyncResponseConsumerFactory);
- }
+ b.append(", options=").append(options);
return b.append('}').toString();
}
@@ -204,40 +174,11 @@ public final class Request {
&& endpoint.equals(other.endpoint)
&& parameters.equals(other.parameters)
&& Objects.equals(entity, other.entity)
- && headers.equals(other.headers)
- && httpAsyncResponseConsumerFactory.equals(other.httpAsyncResponseConsumerFactory);
+ && options.equals(other.options);
}
@Override
public int hashCode() {
- 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());
- }
+ return Objects.hash(method, endpoint, parameters, entity, options);
}
}
diff --git a/client/rest/src/main/java/org/elasticsearch/client/RequestOptions.java b/client/rest/src/main/java/org/elasticsearch/client/RequestOptions.java
new file mode 100644
index 00000000000..e31db17a336
--- /dev/null
+++ b/client/rest/src/main/java/org/elasticsearch/client/RequestOptions.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client;
+
+import org.apache.http.message.BasicHeader;
+import org.apache.http.Header;
+import org.apache.http.nio.protocol.HttpAsyncResponseConsumer;
+import org.elasticsearch.client.HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+
+import java.util.ArrayList;
+
+/**
+ * The portion of an HTTP request to Elasticsearch that can be
+ * manipulated without changing Elasticsearch's behavior.
+ */
+public final class RequestOptions {
+ public static final RequestOptions DEFAULT = new Builder(
+ Collections.emptyList(), HeapBufferedResponseConsumerFactory.DEFAULT).build();
+
+ private final List headers;
+ private final HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory;
+
+ private RequestOptions(Builder builder) {
+ this.headers = Collections.unmodifiableList(new ArrayList<>(builder.headers));
+ this.httpAsyncResponseConsumerFactory = builder.httpAsyncResponseConsumerFactory;
+ }
+
+ public Builder toBuilder() {
+ Builder builder = new Builder(headers, httpAsyncResponseConsumerFactory);
+ return builder;
+ }
+
+ /**
+ * Headers to attach to the request.
+ */
+ public List getHeaders() {
+ return headers;
+ }
+
+ /**
+ * The {@link HttpAsyncResponseConsumerFactory} used to create one
+ * {@link HttpAsyncResponseConsumer} callback per retry. Controls how the
+ * response body gets streamed from a non-blocking HTTP connection on the
+ * client side.
+ */
+ public HttpAsyncResponseConsumerFactory getHttpAsyncResponseConsumerFactory() {
+ return httpAsyncResponseConsumerFactory;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder b = new StringBuilder();
+ b.append("RequestOptions{");
+ if (headers.size() > 0) {
+ b.append(", headers=");
+ for (int h = 0; h < headers.size(); h++) {
+ if (h != 0) {
+ b.append(',');
+ }
+ b.append(headers.get(h).toString());
+ }
+ }
+ if (httpAsyncResponseConsumerFactory != HttpAsyncResponseConsumerFactory.DEFAULT) {
+ b.append(", consumerFactory=").append(httpAsyncResponseConsumerFactory);
+ }
+ return b.append('}').toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || (obj.getClass() != getClass())) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+
+ RequestOptions other = (RequestOptions) obj;
+ return headers.equals(other.headers)
+ && httpAsyncResponseConsumerFactory.equals(other.httpAsyncResponseConsumerFactory);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(headers, httpAsyncResponseConsumerFactory);
+ }
+
+ public static class Builder {
+ private final List headers;
+ private HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory;
+
+ private Builder(List headers, HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory) {
+ this.headers = new ArrayList<>(headers);
+ this.httpAsyncResponseConsumerFactory = httpAsyncResponseConsumerFactory;
+ }
+
+ /**
+ * Build the {@linkplain RequestOptions}.
+ */
+ public RequestOptions build() {
+ return new RequestOptions(this);
+ }
+
+ /**
+ * Add the provided header to the request.
+ */
+ 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));
+ }
+
+ /**
+ * set the {@link HttpAsyncResponseConsumerFactory} used to create one
+ * {@link HttpAsyncResponseConsumer} callback per retry. Controls how the
+ * response body gets streamed from a non-blocking HTTP connection on the
+ * client side.
+ */
+ public void setHttpAsyncResponseConsumerFactory(HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory) {
+ this.httpAsyncResponseConsumerFactory =
+ Objects.requireNonNull(httpAsyncResponseConsumerFactory, "httpAsyncResponseConsumerFactory cannot be null");
+ }
+ }
+
+ /**
+ * Custom implementation of {@link BasicHeader} that overrides equals and
+ * hashCode so it is easier to test equality of {@link RequestOptions}.
+ */
+ 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());
+ }
+ }
+}
diff --git a/client/rest/src/main/java/org/elasticsearch/client/RestClient.java b/client/rest/src/main/java/org/elasticsearch/client/RestClient.java
index 2256274f01a..0e603c4069a 100644
--- a/client/rest/src/main/java/org/elasticsearch/client/RestClient.java
+++ b/client/rest/src/main/java/org/elasticsearch/client/RestClient.java
@@ -312,8 +312,7 @@ public class RestClient implements Closeable {
Request request = new Request(method, endpoint);
addParameters(request, params);
request.setEntity(entity);
- request.setHttpAsyncResponseConsumerFactory(httpAsyncResponseConsumerFactory);
- addHeaders(request, headers);
+ setOptions(request, httpAsyncResponseConsumerFactory, headers);
return performRequest(request);
}
@@ -427,8 +426,7 @@ public class RestClient implements Closeable {
request = new Request(method, endpoint);
addParameters(request, params);
request.setEntity(entity);
- request.setHttpAsyncResponseConsumerFactory(httpAsyncResponseConsumerFactory);
- addHeaders(request, headers);
+ setOptions(request, httpAsyncResponseConsumerFactory, headers);
} catch (Exception e) {
responseListener.onFailure(e);
return;
@@ -465,11 +463,11 @@ public class RestClient implements Closeable {
}
URI uri = buildUri(pathPrefix, request.getEndpoint(), requestParams);
HttpRequestBase httpRequest = createHttpRequest(request.getMethod(), uri, request.getEntity());
- setHeaders(httpRequest, request.getHeaders());
+ setHeaders(httpRequest, request.getOptions().getHeaders());
FailureTrackingResponseListener failureTrackingResponseListener = new FailureTrackingResponseListener(listener);
long startTime = System.nanoTime();
performRequestAsync(startTime, nextHost(), httpRequest, ignoreErrorCodes,
- request.getHttpAsyncResponseConsumerFactory(), failureTrackingResponseListener);
+ request.getOptions().getHttpAsyncResponseConsumerFactory(), failureTrackingResponseListener);
}
private void performRequestAsync(final long startTime, final HostTuple> hostTuple, final HttpRequestBase request,
@@ -891,11 +889,24 @@ public class RestClient implements Closeable {
*/
@Deprecated
private static void addHeaders(Request request, Header... headers) {
+ setOptions(request, RequestOptions.DEFAULT.getHttpAsyncResponseConsumerFactory(), headers);
+ }
+
+ /**
+ * 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 setOptions(Request request, HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory,
+ Header... headers) {
Objects.requireNonNull(headers, "headers cannot be null");
+ RequestOptions.Builder options = request.getOptions().toBuilder();
for (Header header : headers) {
Objects.requireNonNull(header, "header cannot be null");
- request.addHeader(header.getName(), header.getValue());
+ options.addHeader(header.getName(), header.getValue());
}
+ options.setHttpAsyncResponseConsumerFactory(httpAsyncResponseConsumerFactory);
+ request.setOptions(options);
}
/**
diff --git a/client/rest/src/test/java/org/elasticsearch/client/RequestOptionsTests.java b/client/rest/src/test/java/org/elasticsearch/client/RequestOptionsTests.java
new file mode 100644
index 00000000000..19106792228
--- /dev/null
+++ b/client/rest/src/test/java/org/elasticsearch/client/RequestOptionsTests.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client;
+
+import org.apache.http.Header;
+import org.elasticsearch.client.HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+
+public class RequestOptionsTests extends RestClientTestCase {
+ public void testDefault() {
+ assertEquals(Collections.emptyList(), RequestOptions.DEFAULT.getHeaders());
+ assertEquals(HttpAsyncResponseConsumerFactory.DEFAULT, RequestOptions.DEFAULT.getHttpAsyncResponseConsumerFactory());
+ assertEquals(RequestOptions.DEFAULT, RequestOptions.DEFAULT.toBuilder().build());
+ }
+
+ public void testAddHeader() {
+ try {
+ randomBuilder().addHeader(null, randomAsciiLettersOfLengthBetween(3, 10));
+ fail("expected failure");
+ } catch (NullPointerException e) {
+ assertEquals("header name cannot be null", e.getMessage());
+ }
+
+ try {
+ randomBuilder().addHeader(randomAsciiLettersOfLengthBetween(3, 10), null);
+ fail("expected failure");
+ } catch (NullPointerException e) {
+ assertEquals("header value cannot be null", e.getMessage());
+ }
+
+ RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
+ int numHeaders = between(0, 5);
+ List headers = new ArrayList<>();
+ for (int i = 0; i < numHeaders; i++) {
+ Header header = new RequestOptions.ReqHeader(randomAsciiAlphanumOfLengthBetween(5, 10), randomAsciiAlphanumOfLength(3));
+ headers.add(header);
+ builder.addHeader(header.getName(), header.getValue());
+ }
+ RequestOptions options = builder.build();
+ assertEquals(headers, options.getHeaders());
+
+ try {
+ options.getHeaders().add(
+ new RequestOptions.ReqHeader(randomAsciiAlphanumOfLengthBetween(5, 10), randomAsciiAlphanumOfLength(3)));
+ fail("expected failure");
+ } catch (UnsupportedOperationException e) {
+ assertNull(e.getMessage());
+ }
+ }
+
+ public void testSetHttpAsyncResponseConsumerFactory() {
+ try {
+ RequestOptions.DEFAULT.toBuilder().setHttpAsyncResponseConsumerFactory(null);
+ fail("expected failure");
+ } catch (NullPointerException e) {
+ assertEquals("httpAsyncResponseConsumerFactory cannot be null", e.getMessage());
+ }
+
+ HttpAsyncResponseConsumerFactory factory = mock(HttpAsyncResponseConsumerFactory.class);
+ RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
+ builder.setHttpAsyncResponseConsumerFactory(factory);
+ RequestOptions options = builder.build();
+ assertSame(factory, options.getHttpAsyncResponseConsumerFactory());
+ }
+
+ public void testEqualsAndHashCode() {
+ RequestOptions request = randomBuilder().build();
+ assertEquals(request, request);
+
+ RequestOptions copy = copy(request);
+ assertEquals(request, copy);
+ assertEquals(copy, request);
+ assertEquals(request.hashCode(), copy.hashCode());
+
+ RequestOptions mutant = mutate(request);
+ assertNotEquals(request, mutant);
+ assertNotEquals(mutant, request);
+ }
+
+ static RequestOptions.Builder randomBuilder() {
+ RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
+
+ if (randomBoolean()) {
+ int headerCount = between(1, 5);
+ for (int i = 0; i < headerCount; i++) {
+ builder.addHeader(randomAsciiAlphanumOfLength(3), randomAsciiAlphanumOfLength(3));
+ }
+ }
+
+ if (randomBoolean()) {
+ builder.setHttpAsyncResponseConsumerFactory(new HeapBufferedResponseConsumerFactory(1));
+ }
+
+ return builder;
+ }
+
+ private static RequestOptions copy(RequestOptions options) {
+ return options.toBuilder().build();
+ }
+
+ private static RequestOptions mutate(RequestOptions options) {
+ RequestOptions.Builder mutant = options.toBuilder();
+ int mutationType = between(0, 1);
+ switch (mutationType) {
+ case 0:
+ mutant.addHeader("extra", "m");
+ return mutant.build();
+ case 1:
+ mutant.setHttpAsyncResponseConsumerFactory(new HeapBufferedResponseConsumerFactory(5));
+ return mutant.build();
+ default:
+ throw new UnsupportedOperationException("Unknown mutation type [" + mutationType + "]");
+ }
+ }
+}
diff --git a/client/rest/src/test/java/org/elasticsearch/client/RequestTests.java b/client/rest/src/test/java/org/elasticsearch/client/RequestTests.java
index 29bbf23a1f2..a7cf625b61d 100644
--- a/client/rest/src/test/java/org/elasticsearch/client/RequestTests.java
+++ b/client/rest/src/test/java/org/elasticsearch/client/RequestTests.java
@@ -37,6 +37,7 @@ import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
public class RequestTests extends RestClientTestCase {
@@ -127,33 +128,33 @@ public class RequestTests extends RestClientTestCase {
assertEquals(json, new String(os.toByteArray(), ContentType.APPLICATION_JSON.getCharset()));
}
- public void testAddHeader() {
+ public void testSetOptions() {
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.addHeader(null, randomAsciiLettersOfLengthBetween(3, 10));
+ request.setOptions((RequestOptions) null);
fail("expected failure");
} catch (NullPointerException e) {
- assertEquals("header name cannot be null", e.getMessage());
+ assertEquals("options cannot be null", e.getMessage());
}
try {
- request.addHeader(randomAsciiLettersOfLengthBetween(3, 10), null);
+ request.setOptions((RequestOptions.Builder) null);
fail("expected failure");
} catch (NullPointerException e) {
- assertEquals("header value cannot be null", e.getMessage());
+ assertEquals("options cannot be null", e.getMessage());
}
- int numHeaders = between(0, 5);
- List 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());
- }
- assertEquals(headers, new ArrayList<>(request.getHeaders()));
+ RequestOptions.Builder builder = RequestOptionsTests.randomBuilder();
+ request.setOptions(builder);
+ assertEquals(builder.build(), request.getOptions());
+
+ builder = RequestOptionsTests.randomBuilder();
+ RequestOptions options = builder.build();
+ request.setOptions(options);
+ assertSame(options, request.getOptions());
}
public void testEqualsAndHashCode() {
@@ -193,14 +194,9 @@ public class RequestTests extends RestClientTestCase {
}
if (randomBoolean()) {
- int headerCount = between(1, 5);
- for (int i = 0; i < headerCount; i++) {
- request.addHeader(randomAsciiAlphanumOfLength(3), randomAsciiAlphanumOfLength(3));
- }
- }
-
- if (randomBoolean()) {
- request.setHttpAsyncResponseConsumerFactory(new HeapBufferedResponseConsumerFactory(1));
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.setHttpAsyncResponseConsumerFactory(new HeapBufferedResponseConsumerFactory(1));
+ request.setOptions(options);
}
return request;
@@ -222,7 +218,7 @@ public class RequestTests extends RestClientTestCase {
return mutant;
}
Request mutant = copy(request);
- int mutationType = between(0, 3);
+ int mutationType = between(0, 2);
switch (mutationType) {
case 0:
mutant.addParameter(randomAsciiAlphanumOfLength(mutant.getParameters().size() + 4), "extra");
@@ -231,10 +227,9 @@ public class RequestTests extends RestClientTestCase {
mutant.setJsonEntity("mutant"); // randomRequest can't produce this value
return mutant;
case 2:
- mutant.addHeader("extra", "m");
- return mutant;
- case 3:
- mutant.setHttpAsyncResponseConsumerFactory(new HeapBufferedResponseConsumerFactory(5));
+ RequestOptions.Builder options = mutant.getOptions().toBuilder();
+ options.addHeader("extra", "m");
+ mutant.setOptions(options);
return mutant;
default:
throw new UnsupportedOperationException("Unknown mutation type [" + mutationType + "]");
@@ -246,9 +241,6 @@ public class RequestTests extends RestClientTestCase {
to.addParameter(param.getKey(), param.getValue());
}
to.setEntity(from.getEntity());
- for (Header header : from.getHeaders()) {
- to.addHeader(header.getName(), header.getValue());
- }
- to.setHttpAsyncResponseConsumerFactory(from.getHttpAsyncResponseConsumerFactory());
+ to.setOptions(from.getOptions());
}
}
diff --git a/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostIntegTests.java b/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostIntegTests.java
index a3d0196dab9..114d34c73da 100644
--- a/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostIntegTests.java
+++ b/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostIntegTests.java
@@ -378,9 +378,11 @@ public class RestClientSingleHostIntegTests extends RestClientTestCase {
String requestBody = "{ \"field\": \"value\" }";
Request request = new Request(method, "/" + statusCode);
request.setJsonEntity(requestBody);
+ RequestOptions.Builder options = request.getOptions().toBuilder();
for (Header header : headers) {
- request.addHeader(header.getName(), header.getValue());
+ options.addHeader(header.getName(), header.getValue());
}
+ request.setOptions(options);
Response esResponse;
try {
esResponse = restClient.performRequest(request);
diff --git a/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostTests.java b/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostTests.java
index 3811b60023b..634929c5de1 100644
--- a/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostTests.java
+++ b/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostTests.java
@@ -362,9 +362,11 @@ public class RestClientSingleHostTests extends RestClientTestCase {
final Header[] requestHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header");
final int statusCode = randomStatusCode(getRandom());
Request request = new Request(method, "/" + statusCode);
+ RequestOptions.Builder options = request.getOptions().toBuilder();
for (Header requestHeader : requestHeaders) {
- request.addHeader(requestHeader.getName(), requestHeader.getValue());
+ options.addHeader(requestHeader.getName(), requestHeader.getValue());
}
+ request.setOptions(options);
Response esResponse;
try {
esResponse = restClient.performRequest(request);
@@ -438,11 +440,13 @@ public class RestClientSingleHostTests extends RestClientTestCase {
final Set uniqueNames = new HashSet<>();
if (randomBoolean()) {
Header[] headers = RestClientTestUtil.randomHeaders(getRandom(), "Header");
+ RequestOptions.Builder options = request.getOptions().toBuilder();
for (Header header : headers) {
- request.addHeader(header.getName(), header.getValue());
- expectedRequest.addHeader(new Request.ReqHeader(header.getName(), header.getValue()));
+ options.addHeader(header.getName(), header.getValue());
+ expectedRequest.addHeader(new RequestOptions.ReqHeader(header.getName(), header.getValue()));
uniqueNames.add(header.getName());
}
+ request.setOptions(options);
}
for (Header defaultHeader : defaultHeaders) {
// request level headers override default headers
diff --git a/client/rest/src/test/java/org/elasticsearch/client/documentation/RestClientDocumentation.java b/client/rest/src/test/java/org/elasticsearch/client/documentation/RestClientDocumentation.java
index f3ce112fea1..d73c29bd91b 100644
--- a/client/rest/src/test/java/org/elasticsearch/client/documentation/RestClientDocumentation.java
+++ b/client/rest/src/test/java/org/elasticsearch/client/documentation/RestClientDocumentation.java
@@ -38,6 +38,7 @@ import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.HttpAsyncResponseConsumerFactory;
import org.elasticsearch.client.Request;
+import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseListener;
import org.elasticsearch.client.RestClient;
@@ -171,14 +172,22 @@ public class RestClientDocumentation {
//tag::rest-client-body-shorter
request.setJsonEntity("{\"json\":\"text\"}");
//end::rest-client-body-shorter
- //tag::rest-client-headers
- request.addHeader("Accept", "text/plain");
- request.addHeader("Cache-Control", "no-cache");
- //end::rest-client-headers
- //tag::rest-client-response-consumer
- request.setHttpAsyncResponseConsumerFactory(
- new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024));
- //end::rest-client-response-consumer
+ {
+ //tag::rest-client-headers
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader("Accept", "text/plain");
+ options.addHeader("Cache-Control", "no-cache");
+ request.setOptions(options);
+ //end::rest-client-headers
+ }
+ {
+ //tag::rest-client-response-consumer
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.setHttpAsyncResponseConsumerFactory(
+ new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024));
+ request.setOptions(options);
+ //end::rest-client-response-consumer
+ }
}
{
HttpEntity[] documents = new HttpEntity[10];
diff --git a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/ContextAndHeaderTransportIT.java b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/ContextAndHeaderTransportIT.java
index 99132f0c89d..81724bd72ab 100644
--- a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/ContextAndHeaderTransportIT.java
+++ b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/ContextAndHeaderTransportIT.java
@@ -31,6 +31,7 @@ import org.elasticsearch.action.support.ActionFilter;
import org.elasticsearch.action.termvectors.MultiTermVectorsRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.Request;
+import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Strings;
@@ -221,8 +222,10 @@ public class ContextAndHeaderTransportIT extends HttpSmokeTestCase {
public void testThatRelevantHttpHeadersBecomeRequestHeaders() throws IOException {
final String IRRELEVANT_HEADER = "SomeIrrelevantHeader";
Request request = new Request("GET", "/" + queryIndex + "/_search");
- request.addHeader(CUSTOM_HEADER, randomHeaderValue);
- request.addHeader(IRRELEVANT_HEADER, randomHeaderValue);
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader(CUSTOM_HEADER, randomHeaderValue);
+ options.addHeader(IRRELEVANT_HEADER, randomHeaderValue);
+ request.setOptions(options);
Response response = getRestClient().performRequest(request);
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
List searchRequests = getRequests(SearchRequest.class);
diff --git a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/CorsNotSetIT.java b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/CorsNotSetIT.java
index 2d139e7955e..a1dd978df17 100644
--- a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/CorsNotSetIT.java
+++ b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/CorsNotSetIT.java
@@ -20,6 +20,7 @@
package org.elasticsearch.http;
import org.elasticsearch.client.Request;
+import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import java.io.IOException;
@@ -32,8 +33,10 @@ public class CorsNotSetIT extends HttpSmokeTestCase {
public void testCorsSettingDefaultBehaviourDoesNotReturnAnything() throws IOException {
String corsValue = "http://localhost:9200";
Request request = new Request("GET", "/");
- request.addHeader("User-Agent", "Mozilla Bar");
- request.addHeader("Origin", corsValue);
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader("User-Agent", "Mozilla Bar");
+ options.addHeader("Origin", corsValue);
+ request.setOptions(options);
Response response = getRestClient().performRequest(request);
assertThat(response.getStatusLine().getStatusCode(), is(200));
assertThat(response.getHeader("Access-Control-Allow-Origin"), nullValue());
diff --git a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/CorsRegexIT.java b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/CorsRegexIT.java
index e79e8031550..ad10ad80e4b 100644
--- a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/CorsRegexIT.java
+++ b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/CorsRegexIT.java
@@ -19,6 +19,7 @@
package org.elasticsearch.http;
import org.elasticsearch.client.Request;
+import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.common.settings.Settings;
@@ -55,16 +56,20 @@ public class CorsRegexIT extends HttpSmokeTestCase {
{
String corsValue = "http://localhost:9200";
Request request = new Request("GET", "/");
- request.addHeader("User-Agent", "Mozilla Bar");
- request.addHeader("Origin", corsValue);
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader("User-Agent", "Mozilla Bar");
+ options.addHeader("Origin", corsValue);
+ request.setOptions(options);
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);
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader("User-Agent", "Mozilla Bar");
+ options.addHeader("Origin", corsValue);
+ request.setOptions(options);
Response response = getRestClient().performRequest(request);
assertResponseWithOriginHeader(response, corsValue);
assertThat(response.getHeader("Access-Control-Allow-Credentials"), is("true"));
@@ -73,8 +78,10 @@ public class CorsRegexIT extends HttpSmokeTestCase {
public void testThatRegularExpressionReturnsForbiddenOnNonMatch() throws IOException {
Request request = new Request("GET", "/");
- request.addHeader("User-Agent", "Mozilla Bar");
- request.addHeader("Origin", "http://evil-host:9200");
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader("User-Agent", "Mozilla Bar");
+ options.addHeader("Origin", "http://evil-host:9200");
+ request.setOptions(options);
try {
getRestClient().performRequest(request);
fail("request should have failed");
@@ -88,7 +95,9 @@ public class CorsRegexIT extends HttpSmokeTestCase {
public void testThatSendingNoOriginHeaderReturnsNoAccessControlHeader() throws IOException {
Request request = new Request("GET", "/");
- request.addHeader("User-Agent", "Mozilla Bar");
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader("User-Agent", "Mozilla Bar");
+ request.setOptions(options);
Response response = getRestClient().performRequest(request);
assertThat(response.getStatusLine().getStatusCode(), is(200));
assertThat(response.getHeader("Access-Control-Allow-Origin"), nullValue());
@@ -103,9 +112,11 @@ public class CorsRegexIT extends HttpSmokeTestCase {
public void testThatPreFlightRequestWorksOnMatch() throws IOException {
String corsValue = "http://localhost:9200";
Request request = new Request("OPTIONS", "/");
- request.addHeader("User-Agent", "Mozilla Bar");
- request.addHeader("Origin", corsValue);
- request.addHeader("Access-Control-Request-Method", "GET");
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader("User-Agent", "Mozilla Bar");
+ options.addHeader("Origin", corsValue);
+ options.addHeader("Access-Control-Request-Method", "GET");
+ request.setOptions(options);
Response response = getRestClient().performRequest(request);
assertResponseWithOriginHeader(response, corsValue);
assertNotNull(response.getHeader("Access-Control-Allow-Methods"));
@@ -114,9 +125,11 @@ public class CorsRegexIT extends HttpSmokeTestCase {
public void testThatPreFlightRequestReturnsNullOnNonMatch() throws IOException {
String corsValue = "http://evil-host:9200";
Request request = new Request("OPTIONS", "/");
- request.addHeader("User-Agent", "Mozilla Bar");
- request.addHeader("Origin", corsValue);
- request.addHeader("Access-Control-Request-Method", "GET");
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader("User-Agent", "Mozilla Bar");
+ options.addHeader("Origin", corsValue);
+ options.addHeader("Access-Control-Request-Method", "GET");
+ request.setOptions(options);
try {
getRestClient().performRequest(request);
fail("request should have failed");
diff --git a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/HttpCompressionIT.java b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/HttpCompressionIT.java
index a9a0a0c7ed9..b287b49527a 100644
--- a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/HttpCompressionIT.java
+++ b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/HttpCompressionIT.java
@@ -20,6 +20,7 @@ package org.elasticsearch.http;
import org.apache.http.HttpHeaders;
import org.elasticsearch.client.Request;
+import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.test.rest.ESRestTestCase;
@@ -38,7 +39,9 @@ public class HttpCompressionIT extends ESRestTestCase {
public void testCompressesResponseIfRequested() throws IOException {
Request request = new Request("GET", "/");
- request.addHeader(HttpHeaders.ACCEPT_ENCODING, GZIP_ENCODING);
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader(HttpHeaders.ACCEPT_ENCODING, GZIP_ENCODING);
+ request.setOptions(options);
Response response = client().performRequest(request);
assertEquals(200, response.getStatusLine().getStatusCode());
assertEquals(GZIP_ENCODING, response.getHeader(HttpHeaders.CONTENT_ENCODING));
diff --git a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/NoHandlerIT.java b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/NoHandlerIT.java
index 976ba313115..d3707031f0e 100644
--- a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/NoHandlerIT.java
+++ b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/NoHandlerIT.java
@@ -21,6 +21,7 @@ package org.elasticsearch.http;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Request;
+import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
@@ -46,7 +47,9 @@ 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.addHeader("Accept", accept);
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader("Accept", accept);
+ request.setOptions(options);
final ResponseException e = expectThrows(ResponseException.class,
() -> getRestClient().performRequest(request));
diff --git a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/ResponseHeaderPluginIT.java b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/ResponseHeaderPluginIT.java
index ac2503f2c52..d73566c8038 100644
--- a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/ResponseHeaderPluginIT.java
+++ b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/ResponseHeaderPluginIT.java
@@ -19,6 +19,7 @@
package org.elasticsearch.http;
import org.elasticsearch.client.Request;
+import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.plugins.Plugin;
@@ -61,7 +62,9 @@ public class ResponseHeaderPluginIT extends HttpSmokeTestCase {
}
Request request = new Request("GET", "/_protected");
- request.addHeader("Secret", "password");
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader("Secret", "password");
+ request.setOptions(options);
Response authResponse = getRestClient().performRequest(request);
assertThat(authResponse.getStatusLine().getStatusCode(), equalTo(200));
assertThat(authResponse.getHeader("Secret"), equalTo("granted"));
diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ESClientYamlSuiteTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ESClientYamlSuiteTestCase.java
index 30ac94e3432..a9f64b3f78b 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ESClientYamlSuiteTestCase.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/rest/yaml/ESClientYamlSuiteTestCase.java
@@ -322,8 +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.addHeader("Content-Type", XContentType.JSON.mediaTypeWithoutParameters());
- request.setEntity(new StringEntity("{\"index_patterns\":[\"*\"],\"settings\":{\"index.number_of_shards\":2}}"));
+ request.setJsonEntity("{\"index_patterns\":[\"*\"],\"settings\":{\"index.number_of_shards\":2}}");
adminClient().performRequest(request);
}
diff --git a/x-pack/qa/sql/security/src/test/java/org/elasticsearch/xpack/qa/sql/security/RestSqlSecurityIT.java b/x-pack/qa/sql/security/src/test/java/org/elasticsearch/xpack/qa/sql/security/RestSqlSecurityIT.java
index bdbb75491ca..cb8afc876a4 100644
--- a/x-pack/qa/sql/security/src/test/java/org/elasticsearch/xpack/qa/sql/security/RestSqlSecurityIT.java
+++ b/x-pack/qa/sql/security/src/test/java/org/elasticsearch/xpack/qa/sql/security/RestSqlSecurityIT.java
@@ -9,6 +9,7 @@ import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.elasticsearch.client.Request;
+import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.common.Nullable;
@@ -177,7 +178,9 @@ public class RestSqlSecurityIT extends SqlSecurityTestCase {
request.addParameter("mode", mode);
}
if (asUser != null) {
- request.addHeader("es-security-runas-user", asUser);
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader("es-security-runas-user", asUser);
+ request.setOptions(options);
}
request.setEntity(entity);
return toMap(client().performRequest(request));
diff --git a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java
index 80dd09d3c47..7403bee5448 100644
--- a/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java
+++ b/x-pack/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java
@@ -10,6 +10,7 @@ import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.elasticsearch.client.Request;
+import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.common.CheckedSupplier;
@@ -319,7 +320,10 @@ public abstract class RestSqlTestCase extends ESRestTestCase implements ErrorsTe
request.addParameter("mode", mode); // JDBC or PLAIN mode
}
if (randomBoolean()) {
- request.addHeader("Accept", randomFrom("*/*", "application/json"));
+ // JSON is the default but randomly set it sometime for extra coverage
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader("Accept", randomFrom("*/*", "application/json"));
+ request.setOptions(options);
}
request.setEntity(sql);
Response response = client().performRequest(request);
@@ -536,7 +540,9 @@ 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.addHeader("Accept", accept);
+ RequestOptions.Builder options = request.getOptions().toBuilder();
+ options.addHeader("Accept", accept);
+ request.setOptions(options);
Response response = client().performRequest(request);
return new Tuple<>(
Streams.copyToString(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)),