diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java index 177e33d727010..f3c84db79d65f 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java @@ -48,7 +48,7 @@ public final class ClusterClient { */ public ClusterUpdateSettingsResponse putSettings(ClusterUpdateSettingsRequest clusterUpdateSettingsRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(clusterUpdateSettingsRequest, Request::clusterPutSettings, + return restHighLevelClient.performRequestAndParseEntity(clusterUpdateSettingsRequest, RequestConverters::clusterPutSettings, ClusterUpdateSettingsResponse::fromXContent, emptySet(), headers); } @@ -60,7 +60,7 @@ public ClusterUpdateSettingsResponse putSettings(ClusterUpdateSettingsRequest cl */ public void putSettingsAsync(ClusterUpdateSettingsRequest clusterUpdateSettingsRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(clusterUpdateSettingsRequest, Request::clusterPutSettings, + restHighLevelClient.performRequestAsyncAndParseEntity(clusterUpdateSettingsRequest, RequestConverters::clusterPutSettings, ClusterUpdateSettingsResponse::fromXContent, listener, emptySet(), headers); } } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java index ff9c612e1d475..445fd7c6a99b6 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java @@ -74,8 +74,8 @@ public final class IndicesClient { * Delete Index API on elastic.co */ public DeleteIndexResponse delete(DeleteIndexRequest deleteIndexRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(deleteIndexRequest, Request::deleteIndex, DeleteIndexResponse::fromXContent, - emptySet(), headers); + return restHighLevelClient.performRequestAndParseEntity(deleteIndexRequest, RequestConverters::deleteIndex, + DeleteIndexResponse::fromXContent, emptySet(), headers); } /** @@ -85,8 +85,8 @@ public DeleteIndexResponse delete(DeleteIndexRequest deleteIndexRequest, Header. * Delete Index API on elastic.co */ public void deleteAsync(DeleteIndexRequest deleteIndexRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(deleteIndexRequest, Request::deleteIndex, DeleteIndexResponse::fromXContent, - listener, emptySet(), headers); + restHighLevelClient.performRequestAsyncAndParseEntity(deleteIndexRequest, RequestConverters::deleteIndex, + DeleteIndexResponse::fromXContent, listener, emptySet(), headers); } /** @@ -96,8 +96,8 @@ public void deleteAsync(DeleteIndexRequest deleteIndexRequest, ActionListener */ public CreateIndexResponse create(CreateIndexRequest createIndexRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(createIndexRequest, Request::createIndex, CreateIndexResponse::fromXContent, - emptySet(), headers); + return restHighLevelClient.performRequestAndParseEntity(createIndexRequest, RequestConverters::createIndex, + CreateIndexResponse::fromXContent, emptySet(), headers); } /** @@ -107,8 +107,8 @@ public CreateIndexResponse create(CreateIndexRequest createIndexRequest, Header. * Create Index API on elastic.co */ public void createAsync(CreateIndexRequest createIndexRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(createIndexRequest, Request::createIndex, CreateIndexResponse::fromXContent, - listener, emptySet(), headers); + restHighLevelClient.performRequestAsyncAndParseEntity(createIndexRequest, RequestConverters::createIndex, + CreateIndexResponse::fromXContent, listener, emptySet(), headers); } /** @@ -118,8 +118,8 @@ public void createAsync(CreateIndexRequest createIndexRequest, ActionListener */ public PutMappingResponse putMapping(PutMappingRequest putMappingRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(putMappingRequest, Request::putMapping, PutMappingResponse::fromXContent, - emptySet(), headers); + return restHighLevelClient.performRequestAndParseEntity(putMappingRequest, RequestConverters::putMapping, + PutMappingResponse::fromXContent, emptySet(), headers); } /** @@ -130,8 +130,8 @@ public PutMappingResponse putMapping(PutMappingRequest putMappingRequest, Header */ public void putMappingAsync(PutMappingRequest putMappingRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(putMappingRequest, Request::putMapping, PutMappingResponse::fromXContent, - listener, emptySet(), headers); + restHighLevelClient.performRequestAsyncAndParseEntity(putMappingRequest, RequestConverters::putMapping, + PutMappingResponse::fromXContent, listener, emptySet(), headers); } /** @@ -142,7 +142,7 @@ public void putMappingAsync(PutMappingRequest putMappingRequest, ActionListener< * Index Aliases API on elastic.co */ public IndicesAliasesResponse updateAliases(IndicesAliasesRequest indicesAliasesRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(indicesAliasesRequest, Request::updateAliases, + return restHighLevelClient.performRequestAndParseEntity(indicesAliasesRequest, RequestConverters::updateAliases, IndicesAliasesResponse::fromXContent, emptySet(), headers); } @@ -155,7 +155,7 @@ public IndicesAliasesResponse updateAliases(IndicesAliasesRequest indicesAliases */ public void updateAliasesAsync(IndicesAliasesRequest indicesAliasesRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(indicesAliasesRequest, Request::updateAliases, + restHighLevelClient.performRequestAsyncAndParseEntity(indicesAliasesRequest, RequestConverters::updateAliases, IndicesAliasesResponse::fromXContent, listener, emptySet(), headers); } @@ -166,8 +166,8 @@ public void updateAliasesAsync(IndicesAliasesRequest indicesAliasesRequest, Acti * Open Index API on elastic.co */ public OpenIndexResponse open(OpenIndexRequest openIndexRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(openIndexRequest, Request::openIndex, OpenIndexResponse::fromXContent, - emptySet(), headers); + return restHighLevelClient.performRequestAndParseEntity(openIndexRequest, RequestConverters::openIndex, + OpenIndexResponse::fromXContent, emptySet(), headers); } /** @@ -177,8 +177,8 @@ public OpenIndexResponse open(OpenIndexRequest openIndexRequest, Header... heade * Open Index API on elastic.co */ public void openAsync(OpenIndexRequest openIndexRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(openIndexRequest, Request::openIndex, OpenIndexResponse::fromXContent, - listener, emptySet(), headers); + restHighLevelClient.performRequestAsyncAndParseEntity(openIndexRequest, RequestConverters::openIndex, + OpenIndexResponse::fromXContent, listener, emptySet(), headers); } /** @@ -188,8 +188,8 @@ public void openAsync(OpenIndexRequest openIndexRequest, ActionListener */ public CloseIndexResponse close(CloseIndexRequest closeIndexRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(closeIndexRequest, Request::closeIndex, CloseIndexResponse::fromXContent, - emptySet(), headers); + return restHighLevelClient.performRequestAndParseEntity(closeIndexRequest, RequestConverters::closeIndex, + CloseIndexResponse::fromXContent, emptySet(), headers); } /** @@ -199,8 +199,8 @@ public CloseIndexResponse close(CloseIndexRequest closeIndexRequest, Header... h * Close Index API on elastic.co */ public void closeAsync(CloseIndexRequest closeIndexRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(closeIndexRequest, Request::closeIndex, CloseIndexResponse::fromXContent, - listener, emptySet(), headers); + restHighLevelClient.performRequestAsyncAndParseEntity(closeIndexRequest, RequestConverters::closeIndex, + CloseIndexResponse::fromXContent, listener, emptySet(), headers); } /** @@ -210,8 +210,8 @@ public void closeAsync(CloseIndexRequest closeIndexRequest, ActionListener */ public boolean existsAlias(GetAliasesRequest getAliasesRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequest(getAliasesRequest, Request::existsAlias, RestHighLevelClient::convertExistsResponse, - emptySet(), headers); + return restHighLevelClient.performRequest(getAliasesRequest, RequestConverters::existsAlias, + RestHighLevelClient::convertExistsResponse, emptySet(), headers); } /** @@ -221,8 +221,8 @@ public boolean existsAlias(GetAliasesRequest getAliasesRequest, Header... header * Indices Aliases API on elastic.co */ public void existsAliasAsync(GetAliasesRequest getAliasesRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsync(getAliasesRequest, Request::existsAlias, RestHighLevelClient::convertExistsResponse, - listener, emptySet(), headers); + restHighLevelClient.performRequestAsync(getAliasesRequest, RequestConverters::existsAlias, + RestHighLevelClient::convertExistsResponse, listener, emptySet(), headers); } /** @@ -231,7 +231,7 @@ public void existsAliasAsync(GetAliasesRequest getAliasesRequest, ActionListener * See Refresh API on elastic.co */ public RefreshResponse refresh(RefreshRequest refreshRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(refreshRequest, Request::refresh, RefreshResponse::fromXContent, + return restHighLevelClient.performRequestAndParseEntity(refreshRequest, RequestConverters::refresh, RefreshResponse::fromXContent, emptySet(), headers); } @@ -241,7 +241,7 @@ public RefreshResponse refresh(RefreshRequest refreshRequest, Header... headers) * See Refresh API on elastic.co */ public void refreshAsync(RefreshRequest refreshRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(refreshRequest, Request::refresh, RefreshResponse::fromXContent, + restHighLevelClient.performRequestAsyncAndParseEntity(refreshRequest, RequestConverters::refresh, RefreshResponse::fromXContent, listener, emptySet(), headers); } @@ -251,7 +251,7 @@ public void refreshAsync(RefreshRequest refreshRequest, ActionListener Flush API on elastic.co */ public FlushResponse flush(FlushRequest flushRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(flushRequest, Request::flush, FlushResponse::fromXContent, + return restHighLevelClient.performRequestAndParseEntity(flushRequest, RequestConverters::flush, FlushResponse::fromXContent, emptySet(), headers); } @@ -261,7 +261,7 @@ public FlushResponse flush(FlushRequest flushRequest, Header... headers) throws * See Flush API on elastic.co */ public void flushAsync(FlushRequest flushRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(flushRequest, Request::flush, FlushResponse::fromXContent, + restHighLevelClient.performRequestAsyncAndParseEntity(flushRequest, RequestConverters::flush, FlushResponse::fromXContent, listener, emptySet(), headers); } @@ -272,8 +272,8 @@ public void flushAsync(FlushRequest flushRequest, ActionListener * Force Merge API on elastic.co */ public ForceMergeResponse forceMerge(ForceMergeRequest forceMergeRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(forceMergeRequest, Request::forceMerge, ForceMergeResponse::fromXContent, - emptySet(), headers); + return restHighLevelClient.performRequestAndParseEntity(forceMergeRequest, RequestConverters::forceMerge, + ForceMergeResponse::fromXContent, emptySet(), headers); } /** @@ -283,8 +283,8 @@ public ForceMergeResponse forceMerge(ForceMergeRequest forceMergeRequest, Header * Force Merge API on elastic.co */ public void forceMergeAsync(ForceMergeRequest forceMergeRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(forceMergeRequest, Request::forceMerge, ForceMergeResponse::fromXContent, - listener, emptySet(), headers); + restHighLevelClient.performRequestAsyncAndParseEntity(forceMergeRequest, RequestConverters::forceMerge, + ForceMergeResponse::fromXContent, listener, emptySet(), headers); } /** @@ -294,7 +294,7 @@ public void forceMergeAsync(ForceMergeRequest forceMergeRequest, ActionListener< * Clear Cache API on elastic.co */ public ClearIndicesCacheResponse clearCache(ClearIndicesCacheRequest clearIndicesCacheRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(clearIndicesCacheRequest, Request::clearCache, + return restHighLevelClient.performRequestAndParseEntity(clearIndicesCacheRequest, RequestConverters::clearCache, ClearIndicesCacheResponse::fromXContent, emptySet(), headers); } @@ -306,7 +306,7 @@ public ClearIndicesCacheResponse clearCache(ClearIndicesCacheRequest clearIndice */ public void clearCacheAsync(ClearIndicesCacheRequest clearIndicesCacheRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(clearIndicesCacheRequest, Request::clearCache, + restHighLevelClient.performRequestAsyncAndParseEntity(clearIndicesCacheRequest, RequestConverters::clearCache, ClearIndicesCacheResponse::fromXContent, listener, emptySet(), headers); } @@ -319,7 +319,7 @@ public void clearCacheAsync(ClearIndicesCacheRequest clearIndicesCacheRequest, A public boolean exists(GetIndexRequest request, Header... headers) throws IOException { return restHighLevelClient.performRequest( request, - Request::indicesExist, + RequestConverters::indicesExist, RestHighLevelClient::convertExistsResponse, Collections.emptySet(), headers @@ -335,7 +335,7 @@ public boolean exists(GetIndexRequest request, Header... headers) throws IOExcep public void existsAsync(GetIndexRequest request, ActionListener listener, Header... headers) { restHighLevelClient.performRequestAsync( request, - Request::indicesExist, + RequestConverters::indicesExist, RestHighLevelClient::convertExistsResponse, listener, Collections.emptySet(), @@ -350,7 +350,7 @@ public void existsAsync(GetIndexRequest request, ActionListener listene * Shrink Index API on elastic.co */ public ResizeResponse shrink(ResizeRequest resizeRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(resizeRequest, Request::shrink, ResizeResponse::fromXContent, + return restHighLevelClient.performRequestAndParseEntity(resizeRequest, RequestConverters::shrink, ResizeResponse::fromXContent, emptySet(), headers); } @@ -361,7 +361,7 @@ public ResizeResponse shrink(ResizeRequest resizeRequest, Header... headers) thr * Shrink Index API on elastic.co */ public void shrinkAsync(ResizeRequest resizeRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(resizeRequest, Request::shrink, ResizeResponse::fromXContent, + restHighLevelClient.performRequestAsyncAndParseEntity(resizeRequest, RequestConverters::shrink, ResizeResponse::fromXContent, listener, emptySet(), headers); } @@ -372,7 +372,7 @@ public void shrinkAsync(ResizeRequest resizeRequest, ActionListener */ public ResizeResponse split(ResizeRequest resizeRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(resizeRequest, Request::split, ResizeResponse::fromXContent, + return restHighLevelClient.performRequestAndParseEntity(resizeRequest, RequestConverters::split, ResizeResponse::fromXContent, emptySet(), headers); } @@ -383,7 +383,7 @@ public ResizeResponse split(ResizeRequest resizeRequest, Header... headers) thro * Split Index API on elastic.co */ public void splitAsync(ResizeRequest resizeRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(resizeRequest, Request::split, ResizeResponse::fromXContent, + restHighLevelClient.performRequestAsyncAndParseEntity(resizeRequest, RequestConverters::split, ResizeResponse::fromXContent, listener, emptySet(), headers); } @@ -394,8 +394,8 @@ public void splitAsync(ResizeRequest resizeRequest, ActionListener */ public RolloverResponse rollover(RolloverRequest rolloverRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(rolloverRequest, Request::rollover, RolloverResponse::fromXContent, - emptySet(), headers); + return restHighLevelClient.performRequestAndParseEntity(rolloverRequest, RequestConverters::rollover, + RolloverResponse::fromXContent, emptySet(), headers); } /** @@ -405,7 +405,7 @@ public RolloverResponse rollover(RolloverRequest rolloverRequest, Header... head * Rollover Index API on elastic.co */ public void rolloverAsync(RolloverRequest rolloverRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(rolloverRequest, Request::rollover, RolloverResponse::fromXContent, + restHighLevelClient.performRequestAsyncAndParseEntity(rolloverRequest, RequestConverters::rollover, RolloverResponse::fromXContent, listener, emptySet(), headers); } @@ -416,7 +416,7 @@ public void rolloverAsync(RolloverRequest rolloverRequest, ActionListener */ public UpdateSettingsResponse putSettings(UpdateSettingsRequest updateSettingsRequest, Header... headers) throws IOException { - return restHighLevelClient.performRequestAndParseEntity(updateSettingsRequest, Request::indexPutSettings, + return restHighLevelClient.performRequestAndParseEntity(updateSettingsRequest, RequestConverters::indexPutSettings, UpdateSettingsResponse::fromXContent, emptySet(), headers); } @@ -428,7 +428,7 @@ public UpdateSettingsResponse putSettings(UpdateSettingsRequest updateSettingsRe */ public void putSettingsAsync(UpdateSettingsRequest updateSettingsRequest, ActionListener listener, Header... headers) { - restHighLevelClient.performRequestAsyncAndParseEntity(updateSettingsRequest, Request::indexPutSettings, + restHighLevelClient.performRequestAsyncAndParseEntity(updateSettingsRequest, RequestConverters::indexPutSettings, UpdateSettingsResponse::fromXContent, listener, emptySet(), headers); } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java similarity index 78% rename from client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java rename to client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java index 192da83f8b4f2..d4cac4cc63553 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java @@ -89,117 +89,85 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; -import java.util.Objects; import java.util.StringJoiner; -public final class Request { - +final class RequestConverters { static final XContentType REQUEST_BODY_CONTENT_TYPE = XContentType.JSON; - private final String method; - private final String endpoint; - private final Map parameters; - private final HttpEntity entity; - - public Request(String method, String endpoint, Map parameters, HttpEntity entity) { - this.method = Objects.requireNonNull(method, "method cannot be null"); - this.endpoint = Objects.requireNonNull(endpoint, "endpoint cannot be null"); - this.parameters = Objects.requireNonNull(parameters, "parameters cannot be null"); - this.entity = entity; - } - - public String getMethod() { - return method; - } - - public String getEndpoint() { - return endpoint; - } - - public Map getParameters() { - return parameters; - } - - public HttpEntity getEntity() { - return entity; - } - - @Override - public String toString() { - return "Request{" + - "method='" + method + '\'' + - ", endpoint='" + endpoint + '\'' + - ", params=" + parameters + - ", hasBody=" + (entity != null) + - '}'; + private RequestConverters() { + // Contains only status utility methods } static Request delete(DeleteRequest deleteRequest) { String endpoint = endpoint(deleteRequest.index(), deleteRequest.type(), deleteRequest.id()); + Request request = new Request(HttpDelete.METHOD_NAME, endpoint); - Params parameters = Params.builder(); + Params parameters = new Params(request); parameters.withRouting(deleteRequest.routing()); parameters.withTimeout(deleteRequest.timeout()); parameters.withVersion(deleteRequest.version()); parameters.withVersionType(deleteRequest.versionType()); parameters.withRefreshPolicy(deleteRequest.getRefreshPolicy()); parameters.withWaitForActiveShards(deleteRequest.waitForActiveShards()); - - return new Request(HttpDelete.METHOD_NAME, endpoint, parameters.getParams(), null); + return request; } static Request deleteIndex(DeleteIndexRequest deleteIndexRequest) { String endpoint = endpoint(deleteIndexRequest.indices()); + Request request = new Request(HttpDelete.METHOD_NAME, endpoint); - Params parameters = Params.builder(); + Params parameters = new Params(request); parameters.withTimeout(deleteIndexRequest.timeout()); parameters.withMasterTimeout(deleteIndexRequest.masterNodeTimeout()); parameters.withIndicesOptions(deleteIndexRequest.indicesOptions()); - - return new Request(HttpDelete.METHOD_NAME, endpoint, parameters.getParams(), null); + return request; } static Request openIndex(OpenIndexRequest openIndexRequest) { String endpoint = endpoint(openIndexRequest.indices(), "_open"); + Request request = new Request(HttpPost.METHOD_NAME, endpoint); - Params parameters = Params.builder(); - + Params parameters = new Params(request); parameters.withTimeout(openIndexRequest.timeout()); parameters.withMasterTimeout(openIndexRequest.masterNodeTimeout()); parameters.withWaitForActiveShards(openIndexRequest.waitForActiveShards()); parameters.withIndicesOptions(openIndexRequest.indicesOptions()); - - return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), null); + return request; } static Request closeIndex(CloseIndexRequest closeIndexRequest) { String endpoint = endpoint(closeIndexRequest.indices(), "_close"); - Params parameters = Params.builder(); + Request request = new Request(HttpPost.METHOD_NAME, endpoint); + + Params parameters = new Params(request); parameters.withTimeout(closeIndexRequest.timeout()); parameters.withMasterTimeout(closeIndexRequest.masterNodeTimeout()); parameters.withIndicesOptions(closeIndexRequest.indicesOptions()); - return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), null); + return request; } static Request createIndex(CreateIndexRequest createIndexRequest) throws IOException { String endpoint = endpoint(createIndexRequest.indices()); + Request request = new Request(HttpPut.METHOD_NAME, endpoint); - Params parameters = Params.builder(); + Params parameters = new Params(request); parameters.withTimeout(createIndexRequest.timeout()); parameters.withMasterTimeout(createIndexRequest.masterNodeTimeout()); parameters.withWaitForActiveShards(createIndexRequest.waitForActiveShards()); - HttpEntity entity = createEntity(createIndexRequest, REQUEST_BODY_CONTENT_TYPE); - return new Request(HttpPut.METHOD_NAME, endpoint, parameters.getParams(), entity); + request.setEntity(createEntity(createIndexRequest, REQUEST_BODY_CONTENT_TYPE)); + return request; } static Request updateAliases(IndicesAliasesRequest indicesAliasesRequest) throws IOException { - Params parameters = Params.builder(); + Request request = new Request(HttpPost.METHOD_NAME, "/_aliases"); + + Params parameters = new Params(request); parameters.withTimeout(indicesAliasesRequest.timeout()); parameters.withMasterTimeout(indicesAliasesRequest.masterNodeTimeout()); - HttpEntity entity = createEntity(indicesAliasesRequest, REQUEST_BODY_CONTENT_TYPE); - return new Request(HttpPost.METHOD_NAME, "/_aliases", parameters.getParams(), entity); + request.setEntity(createEntity(indicesAliasesRequest, REQUEST_BODY_CONTENT_TYPE)); + return request; } static Request putMapping(PutMappingRequest putMappingRequest) throws IOException { @@ -208,63 +176,69 @@ static Request putMapping(PutMappingRequest putMappingRequest) throws IOExceptio throw new IllegalArgumentException("concreteIndex cannot be set on PutMapping requests made over the REST API"); } - String endpoint = endpoint(putMappingRequest.indices(), "_mapping", putMappingRequest.type()); + Request request = new Request(HttpPut.METHOD_NAME, endpoint(putMappingRequest.indices(), "_mapping", putMappingRequest.type())); - Params parameters = Params.builder(); + Params parameters = new Params(request); parameters.withTimeout(putMappingRequest.timeout()); parameters.withMasterTimeout(putMappingRequest.masterNodeTimeout()); - HttpEntity entity = createEntity(putMappingRequest, REQUEST_BODY_CONTENT_TYPE); - return new Request(HttpPut.METHOD_NAME, endpoint, parameters.getParams(), entity); + request.setEntity(createEntity(putMappingRequest, REQUEST_BODY_CONTENT_TYPE)); + return request; } static Request refresh(RefreshRequest refreshRequest) { String[] indices = refreshRequest.indices() == null ? Strings.EMPTY_ARRAY : refreshRequest.indices(); - String endpoint = endpoint(indices, "_refresh"); - Params parameters = Params.builder(); + Request request = new Request(HttpPost.METHOD_NAME, endpoint(indices, "_refresh")); + + Params parameters = new Params(request); parameters.withIndicesOptions(refreshRequest.indicesOptions()); - return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), null); + return request; } static Request flush(FlushRequest flushRequest) { String[] indices = flushRequest.indices() == null ? Strings.EMPTY_ARRAY : flushRequest.indices(); - String endpoint = endpoint(indices, "_flush"); - Params parameters = Params.builder(); + Request request = new Request(HttpPost.METHOD_NAME, endpoint(indices, "_flush")); + + Params parameters = new Params(request); parameters.withIndicesOptions(flushRequest.indicesOptions()); parameters.putParam("wait_if_ongoing", Boolean.toString(flushRequest.waitIfOngoing())); parameters.putParam("force", Boolean.toString(flushRequest.force())); - return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), null); + return request; } static Request forceMerge(ForceMergeRequest forceMergeRequest) { String[] indices = forceMergeRequest.indices() == null ? Strings.EMPTY_ARRAY : forceMergeRequest.indices(); - String endpoint = endpoint(indices, "_forcemerge"); - Params parameters = Params.builder(); + Request request = new Request(HttpPost.METHOD_NAME, endpoint(indices, "_forcemerge")); + + Params parameters = new Params(request); parameters.withIndicesOptions(forceMergeRequest.indicesOptions()); parameters.putParam("max_num_segments", Integer.toString(forceMergeRequest.maxNumSegments())); parameters.putParam("only_expunge_deletes", Boolean.toString(forceMergeRequest.onlyExpungeDeletes())); parameters.putParam("flush", Boolean.toString(forceMergeRequest.flush())); - return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), null); + return request; } static Request clearCache(ClearIndicesCacheRequest clearIndicesCacheRequest) { String[] indices = clearIndicesCacheRequest.indices() == null ? Strings.EMPTY_ARRAY :clearIndicesCacheRequest.indices(); - String endpoint = endpoint(indices, "_cache/clear"); - Params parameters = Params.builder(); + Request request = new Request(HttpPost.METHOD_NAME, endpoint(indices, "_cache/clear")); + + Params parameters = new Params(request); parameters.withIndicesOptions(clearIndicesCacheRequest.indicesOptions()); parameters.putParam("query", Boolean.toString(clearIndicesCacheRequest.queryCache())); parameters.putParam("fielddata", Boolean.toString(clearIndicesCacheRequest.fieldDataCache())); parameters.putParam("request", Boolean.toString(clearIndicesCacheRequest.requestCache())); parameters.putParam("fields", String.join(",", clearIndicesCacheRequest.fields())); - return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), null); + return request; } static Request info() { - return new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null); + return new Request(HttpGet.METHOD_NAME, "/"); } static Request bulk(BulkRequest bulkRequest) throws IOException { - Params parameters = Params.builder(); + Request request = new Request(HttpPost.METHOD_NAME, "/_bulk"); + + Params parameters = new Params(request); parameters.withTimeout(bulkRequest.timeout()); parameters.withRefreshPolicy(bulkRequest.getRefreshPolicy()); @@ -273,14 +247,14 @@ static Request bulk(BulkRequest bulkRequest) throws IOException { // and this content-type is supported by the Bulk API. XContentType bulkContentType = null; for (int i = 0; i < bulkRequest.numberOfActions(); i++) { - DocWriteRequest request = bulkRequest.requests().get(i); + DocWriteRequest action = bulkRequest.requests().get(i); - DocWriteRequest.OpType opType = request.opType(); + DocWriteRequest.OpType opType = action.opType(); if (opType == DocWriteRequest.OpType.INDEX || opType == DocWriteRequest.OpType.CREATE) { - bulkContentType = enforceSameContentType((IndexRequest) request, bulkContentType); + bulkContentType = enforceSameContentType((IndexRequest) action, bulkContentType); } else if (opType == DocWriteRequest.OpType.UPDATE) { - UpdateRequest updateRequest = (UpdateRequest) request; + UpdateRequest updateRequest = (UpdateRequest) action; if (updateRequest.doc() != null) { bulkContentType = enforceSameContentType(updateRequest.doc(), bulkContentType); } @@ -298,30 +272,30 @@ static Request bulk(BulkRequest bulkRequest) throws IOException { final ContentType requestContentType = createContentType(bulkContentType); ByteArrayOutputStream content = new ByteArrayOutputStream(); - for (DocWriteRequest request : bulkRequest.requests()) { - DocWriteRequest.OpType opType = request.opType(); + for (DocWriteRequest action : bulkRequest.requests()) { + DocWriteRequest.OpType opType = action.opType(); try (XContentBuilder metadata = XContentBuilder.builder(bulkContentType.xContent())) { metadata.startObject(); { metadata.startObject(opType.getLowercase()); - if (Strings.hasLength(request.index())) { - metadata.field("_index", request.index()); + if (Strings.hasLength(action.index())) { + metadata.field("_index", action.index()); } - if (Strings.hasLength(request.type())) { - metadata.field("_type", request.type()); + if (Strings.hasLength(action.type())) { + metadata.field("_type", action.type()); } - if (Strings.hasLength(request.id())) { - metadata.field("_id", request.id()); + if (Strings.hasLength(action.id())) { + metadata.field("_id", action.id()); } - if (Strings.hasLength(request.routing())) { - metadata.field("routing", request.routing()); + if (Strings.hasLength(action.routing())) { + metadata.field("routing", action.routing()); } - if (request.version() != Versions.MATCH_ANY) { - metadata.field("version", request.version()); + if (action.version() != Versions.MATCH_ANY) { + metadata.field("version", action.version()); } - VersionType versionType = request.versionType(); + VersionType versionType = action.versionType(); if (versionType != VersionType.INTERNAL) { if (versionType == VersionType.EXTERNAL) { metadata.field("version_type", "external"); @@ -333,12 +307,12 @@ static Request bulk(BulkRequest bulkRequest) throws IOException { } if (opType == DocWriteRequest.OpType.INDEX || opType == DocWriteRequest.OpType.CREATE) { - IndexRequest indexRequest = (IndexRequest) request; + IndexRequest indexRequest = (IndexRequest) action; if (Strings.hasLength(indexRequest.getPipeline())) { metadata.field("pipeline", indexRequest.getPipeline()); } } else if (opType == DocWriteRequest.OpType.UPDATE) { - UpdateRequest updateRequest = (UpdateRequest) request; + UpdateRequest updateRequest = (UpdateRequest) action; if (updateRequest.retryOnConflict() > 0) { metadata.field("retry_on_conflict", updateRequest.retryOnConflict()); } @@ -357,7 +331,7 @@ static Request bulk(BulkRequest bulkRequest) throws IOException { BytesRef source = null; if (opType == DocWriteRequest.OpType.INDEX || opType == DocWriteRequest.OpType.CREATE) { - IndexRequest indexRequest = (IndexRequest) request; + IndexRequest indexRequest = (IndexRequest) action; BytesReference indexSource = indexRequest.source(); XContentType indexXContentType = indexRequest.getContentType(); @@ -369,7 +343,7 @@ static Request bulk(BulkRequest bulkRequest) throws IOException { } } } else if (opType == DocWriteRequest.OpType.UPDATE) { - source = XContentHelper.toXContent((UpdateRequest) request, bulkContentType, false).toBytesRef(); + source = XContentHelper.toXContent((UpdateRequest) action, bulkContentType, false).toBytesRef(); } if (source != null) { @@ -377,20 +351,22 @@ static Request bulk(BulkRequest bulkRequest) throws IOException { content.write(separator); } } - - HttpEntity entity = new ByteArrayEntity(content.toByteArray(), 0, content.size(), requestContentType); - return new Request(HttpPost.METHOD_NAME, "/_bulk", parameters.getParams(), entity); + request.setEntity(new ByteArrayEntity(content.toByteArray(), 0, content.size(), requestContentType)); + return request; } static Request exists(GetRequest getRequest) { - Request request = get(getRequest); - return new Request(HttpHead.METHOD_NAME, request.endpoint, request.parameters, null); + return getStyleRequest(HttpHead.METHOD_NAME, getRequest); } static Request get(GetRequest getRequest) { - String endpoint = endpoint(getRequest.index(), getRequest.type(), getRequest.id()); + return getStyleRequest(HttpGet.METHOD_NAME, getRequest); + } - Params parameters = Params.builder(); + private static Request getStyleRequest(String method, GetRequest getRequest) { + Request request = new Request(method, endpoint(getRequest.index(), getRequest.type(), getRequest.id())); + + Params parameters = new Params(request); parameters.withPreference(getRequest.preference()); parameters.withRouting(getRequest.routing()); parameters.withRefresh(getRequest.refresh()); @@ -400,25 +376,28 @@ static Request get(GetRequest getRequest) { parameters.withVersionType(getRequest.versionType()); parameters.withFetchSourceContext(getRequest.fetchSourceContext()); - return new Request(HttpGet.METHOD_NAME, endpoint, parameters.getParams(), null); + return request; } static Request multiGet(MultiGetRequest multiGetRequest) throws IOException { - Params parameters = Params.builder(); + Request request = new Request(HttpPost.METHOD_NAME, "/_mget"); + + Params parameters = new Params(request); parameters.withPreference(multiGetRequest.preference()); parameters.withRealtime(multiGetRequest.realtime()); parameters.withRefresh(multiGetRequest.refresh()); - HttpEntity entity = createEntity(multiGetRequest, REQUEST_BODY_CONTENT_TYPE); - return new Request(HttpPost.METHOD_NAME, "/_mget", parameters.getParams(), entity); + + request.setEntity(createEntity(multiGetRequest, REQUEST_BODY_CONTENT_TYPE)); + return request; } static Request index(IndexRequest indexRequest) { String method = Strings.hasLength(indexRequest.id()) ? HttpPut.METHOD_NAME : HttpPost.METHOD_NAME; - boolean isCreate = (indexRequest.opType() == DocWriteRequest.OpType.CREATE); String endpoint = endpoint(indexRequest.index(), indexRequest.type(), indexRequest.id(), isCreate ? "_create" : null); + Request request = new Request(method, endpoint); - Params parameters = Params.builder(); + Params parameters = new Params(request); parameters.withRouting(indexRequest.routing()); parameters.withTimeout(indexRequest.timeout()); parameters.withVersion(indexRequest.version()); @@ -429,19 +408,19 @@ static Request index(IndexRequest indexRequest) { BytesRef source = indexRequest.source().toBytesRef(); ContentType contentType = createContentType(indexRequest.getContentType()); - HttpEntity entity = new ByteArrayEntity(source.bytes, source.offset, source.length, contentType); - - return new Request(method, endpoint, parameters.getParams(), entity); + request.setEntity(new ByteArrayEntity(source.bytes, source.offset, source.length, contentType)); + return request; } static Request ping() { - return new Request(HttpHead.METHOD_NAME, "/", Collections.emptyMap(), null); + return new Request(HttpHead.METHOD_NAME, "/"); } static Request update(UpdateRequest updateRequest) throws IOException { String endpoint = endpoint(updateRequest.index(), updateRequest.type(), updateRequest.id(), "_update"); + Request request = new Request(HttpPost.METHOD_NAME, endpoint); - Params parameters = Params.builder(); + Params parameters = new Params(request); parameters.withRouting(updateRequest.routing()); parameters.withTimeout(updateRequest.timeout()); parameters.withRefreshPolicy(updateRequest.getRefreshPolicy()); @@ -472,14 +451,14 @@ static Request update(UpdateRequest updateRequest) throws IOException { if (xContentType == null) { xContentType = Requests.INDEX_CONTENT_TYPE; } - - HttpEntity entity = createEntity(updateRequest, xContentType); - return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), entity); + request.setEntity(createEntity(updateRequest, xContentType)); + return request; } static Request search(SearchRequest searchRequest) throws IOException { - String endpoint = endpoint(searchRequest.indices(), searchRequest.types(), "_search"); - Params params = Params.builder(); + Request request = new Request(HttpPost.METHOD_NAME, endpoint(searchRequest.indices(), searchRequest.types(), "_search")); + + Params params = new Params(request); params.putParam(RestSearchAction.TYPED_KEYS_PARAM, "true"); params.withRouting(searchRequest.routing()); params.withPreference(searchRequest.preference()); @@ -495,65 +474,73 @@ static Request search(SearchRequest searchRequest) throws IOException { if (searchRequest.scroll() != null) { params.putParam("scroll", searchRequest.scroll().keepAlive()); } - HttpEntity entity = null; + if (searchRequest.source() != null) { - entity = createEntity(searchRequest.source(), REQUEST_BODY_CONTENT_TYPE); + request.setEntity(createEntity(searchRequest.source(), REQUEST_BODY_CONTENT_TYPE)); } - return new Request(HttpPost.METHOD_NAME, endpoint, params.getParams(), entity); + return request; } static Request searchScroll(SearchScrollRequest searchScrollRequest) throws IOException { - HttpEntity entity = createEntity(searchScrollRequest, REQUEST_BODY_CONTENT_TYPE); - return new Request(HttpPost.METHOD_NAME, "/_search/scroll", Collections.emptyMap(), entity); + Request request = new Request(HttpPost.METHOD_NAME, "/_search/scroll"); + request.setEntity(createEntity(searchScrollRequest, REQUEST_BODY_CONTENT_TYPE)); + return request; } static Request clearScroll(ClearScrollRequest clearScrollRequest) throws IOException { - HttpEntity entity = createEntity(clearScrollRequest, REQUEST_BODY_CONTENT_TYPE); - return new Request(HttpDelete.METHOD_NAME, "/_search/scroll", Collections.emptyMap(), entity); + Request request = new Request(HttpDelete.METHOD_NAME, "/_search/scroll"); + request.setEntity(createEntity(clearScrollRequest, REQUEST_BODY_CONTENT_TYPE)); + return request; } static Request multiSearch(MultiSearchRequest multiSearchRequest) throws IOException { - Params params = Params.builder(); + Request request = new Request(HttpPost.METHOD_NAME, "/_msearch"); + + Params params = new Params(request); params.putParam(RestSearchAction.TYPED_KEYS_PARAM, "true"); if (multiSearchRequest.maxConcurrentSearchRequests() != MultiSearchRequest.MAX_CONCURRENT_SEARCH_REQUESTS_DEFAULT) { params.putParam("max_concurrent_searches", Integer.toString(multiSearchRequest.maxConcurrentSearchRequests())); } + XContent xContent = REQUEST_BODY_CONTENT_TYPE.xContent(); byte[] source = MultiSearchRequest.writeMultiLineFormat(multiSearchRequest, xContent); - HttpEntity entity = new ByteArrayEntity(source, createContentType(xContent.type())); - return new Request(HttpPost.METHOD_NAME, "/_msearch", params.getParams(), entity); + request.setEntity(new ByteArrayEntity(source, createContentType(xContent.type()))); + return request; } static Request existsAlias(GetAliasesRequest getAliasesRequest) { - Params params = Params.builder(); - params.withIndicesOptions(getAliasesRequest.indicesOptions()); - params.withLocal(getAliasesRequest.local()); if ((getAliasesRequest.indices() == null || getAliasesRequest.indices().length == 0) && (getAliasesRequest.aliases() == null || getAliasesRequest.aliases().length == 0)) { throw new IllegalArgumentException("existsAlias requires at least an alias or an index"); } String[] indices = getAliasesRequest.indices() == null ? Strings.EMPTY_ARRAY : getAliasesRequest.indices(); String[] aliases = getAliasesRequest.aliases() == null ? Strings.EMPTY_ARRAY : getAliasesRequest.aliases(); - String endpoint = endpoint(indices, "_alias", aliases); - return new Request(HttpHead.METHOD_NAME, endpoint, params.getParams(), null); + + Request request = new Request(HttpHead.METHOD_NAME, endpoint(indices, "_alias", aliases)); + + Params params = new Params(request); + params.withIndicesOptions(getAliasesRequest.indicesOptions()); + params.withLocal(getAliasesRequest.local()); + return request; } static Request fieldCaps(FieldCapabilitiesRequest fieldCapabilitiesRequest) { - Params params = Params.builder(); + Request request = new Request(HttpGet.METHOD_NAME, endpoint(fieldCapabilitiesRequest.indices(), "_field_caps")); + + Params params = new Params(request); params.withFields(fieldCapabilitiesRequest.fields()); params.withIndicesOptions(fieldCapabilitiesRequest.indicesOptions()); - - String[] indices = fieldCapabilitiesRequest.indices(); - String endpoint = endpoint(indices, "_field_caps"); - return new Request(HttpGet.METHOD_NAME, endpoint, params.getParams(), null); + return request; } static Request rankEval(RankEvalRequest rankEvalRequest) throws IOException { - String endpoint = endpoint(rankEvalRequest.indices(), Strings.EMPTY_ARRAY, "_rank_eval"); - Params params = Params.builder(); + Request request = new Request(HttpGet.METHOD_NAME, endpoint(rankEvalRequest.indices(), Strings.EMPTY_ARRAY, "_rank_eval")); + + Params params = new Params(request); params.withIndicesOptions(rankEvalRequest.indicesOptions()); - HttpEntity entity = createEntity(rankEvalRequest.getRankEvalSpec(), REQUEST_BODY_CONTENT_TYPE); - return new Request(HttpGet.METHOD_NAME, endpoint, params.getParams(), entity); + + request.setEntity(createEntity(rankEvalRequest.getRankEvalSpec(), REQUEST_BODY_CONTENT_TYPE)); + return request; } static Request split(ResizeRequest resizeRequest) throws IOException { @@ -571,64 +558,76 @@ static Request shrink(ResizeRequest resizeRequest) throws IOException { } private static Request resize(ResizeRequest resizeRequest) throws IOException { - Params params = Params.builder(); - params.withTimeout(resizeRequest.timeout()); - params.withMasterTimeout(resizeRequest.masterNodeTimeout()); - params.withWaitForActiveShards(resizeRequest.getTargetIndexRequest().waitForActiveShards()); String endpoint = new EndpointBuilder().addPathPart(resizeRequest.getSourceIndex()) .addPathPartAsIs("_" + resizeRequest.getResizeType().name().toLowerCase(Locale.ROOT)) .addPathPart(resizeRequest.getTargetIndexRequest().index()).build(); - HttpEntity entity = createEntity(resizeRequest, REQUEST_BODY_CONTENT_TYPE); - return new Request(HttpPut.METHOD_NAME, endpoint, params.getParams(), entity); + Request request = new Request(HttpPut.METHOD_NAME, endpoint); + + Params params = new Params(request); + params.withTimeout(resizeRequest.timeout()); + params.withMasterTimeout(resizeRequest.masterNodeTimeout()); + params.withWaitForActiveShards(resizeRequest.getTargetIndexRequest().waitForActiveShards()); + + request.setEntity(createEntity(resizeRequest, REQUEST_BODY_CONTENT_TYPE)); + return request; } static Request clusterPutSettings(ClusterUpdateSettingsRequest clusterUpdateSettingsRequest) throws IOException { - Params parameters = Params.builder(); + Request request = new Request(HttpPut.METHOD_NAME, "/_cluster/settings"); + + Params parameters = new Params(request); parameters.withTimeout(clusterUpdateSettingsRequest.timeout()); parameters.withMasterTimeout(clusterUpdateSettingsRequest.masterNodeTimeout()); - HttpEntity entity = createEntity(clusterUpdateSettingsRequest, REQUEST_BODY_CONTENT_TYPE); - return new Request(HttpPut.METHOD_NAME, "/_cluster/settings", parameters.getParams(), entity); + + request.setEntity(createEntity(clusterUpdateSettingsRequest, REQUEST_BODY_CONTENT_TYPE)); + return request; } static Request rollover(RolloverRequest rolloverRequest) throws IOException { - Params params = Params.builder(); + String endpoint = new EndpointBuilder().addPathPart(rolloverRequest.getAlias()).addPathPartAsIs("_rollover") + .addPathPart(rolloverRequest.getNewIndexName()).build(); + Request request = new Request(HttpPost.METHOD_NAME, endpoint); + + Params params = new Params(request); params.withTimeout(rolloverRequest.timeout()); params.withMasterTimeout(rolloverRequest.masterNodeTimeout()); params.withWaitForActiveShards(rolloverRequest.getCreateIndexRequest().waitForActiveShards()); if (rolloverRequest.isDryRun()) { params.putParam("dry_run", Boolean.TRUE.toString()); } - String endpoint = new EndpointBuilder().addPathPart(rolloverRequest.getAlias()).addPathPartAsIs("_rollover") - .addPathPart(rolloverRequest.getNewIndexName()).build(); - HttpEntity entity = createEntity(rolloverRequest, REQUEST_BODY_CONTENT_TYPE); - return new Request(HttpPost.METHOD_NAME, endpoint, params.getParams(), entity); + + request.setEntity(createEntity(rolloverRequest, REQUEST_BODY_CONTENT_TYPE)); + return request; } - static Request indicesExist(GetIndexRequest request) { + static Request indicesExist(GetIndexRequest getIndexRequest) { // this can be called with no indices as argument by transport client, not via REST though - if (request.indices() == null || request.indices().length == 0) { + if (getIndexRequest.indices() == null || getIndexRequest.indices().length == 0) { throw new IllegalArgumentException("indices are mandatory"); } - String endpoint = endpoint(request.indices(), ""); - Params params = Params.builder(); - params.withLocal(request.local()); - params.withHuman(request.humanReadable()); - params.withIndicesOptions(request.indicesOptions()); - params.withIncludeDefaults(request.includeDefaults()); - return new Request(HttpHead.METHOD_NAME, endpoint, params.getParams(), null); + String endpoint = endpoint(getIndexRequest.indices(), ""); + Request request = new Request(HttpHead.METHOD_NAME, endpoint); + + Params params = new Params(request); + params.withLocal(getIndexRequest.local()); + params.withHuman(getIndexRequest.humanReadable()); + params.withIndicesOptions(getIndexRequest.indicesOptions()); + params.withIncludeDefaults(getIndexRequest.includeDefaults()); + return request; } static Request indexPutSettings(UpdateSettingsRequest updateSettingsRequest) throws IOException { - Params parameters = Params.builder(); + String[] indices = updateSettingsRequest.indices() == null ? Strings.EMPTY_ARRAY : updateSettingsRequest.indices(); + Request request = new Request(HttpPut.METHOD_NAME, endpoint(indices, "_settings")); + + Params parameters = new Params(request); parameters.withTimeout(updateSettingsRequest.timeout()); parameters.withMasterTimeout(updateSettingsRequest.masterNodeTimeout()); parameters.withIndicesOptions(updateSettingsRequest.indicesOptions()); parameters.withPreserveExisting(updateSettingsRequest.isPreserveExisting()); - String[] indices = updateSettingsRequest.indices() == null ? Strings.EMPTY_ARRAY : updateSettingsRequest.indices(); - String endpoint = endpoint(indices, "_settings"); - HttpEntity entity = createEntity(updateSettingsRequest, REQUEST_BODY_CONTENT_TYPE); - return new Request(HttpPut.METHOD_NAME, endpoint, parameters.getParams(), entity); + request.setEntity(createEntity(updateSettingsRequest, REQUEST_BODY_CONTENT_TYPE)); + return request; } private static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) throws IOException { @@ -678,19 +677,19 @@ public static ContentType createContentType(final XContentType xContentType) { } /** - * Utility class to build request's parameters map and centralize all parameter names. + * Utility class to help with common parameter names and patterns. Wraps + * a {@link Request} and adds the parameters to it directly. */ static class Params { - private final Map params = new HashMap<>(); + private final Request request; - private Params() { + Params(Request request) { + this.request = request; } - Params putParam(String key, String value) { + Params putParam(String name, String value) { if (Strings.hasLength(value)) { - if (params.putIfAbsent(key, value) != null) { - throw new IllegalArgumentException("Request parameter [" + key + "] is already registered"); - } + request.addParameter(name, value); } return this; } @@ -854,14 +853,6 @@ Params withPreserveExisting(boolean preserveExisting) { } return this; } - - Map getParams() { - return Collections.unmodifiableMap(params); - } - - static Params builder() { - return new Params(); - } } /** 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 c6d5e947f2c62..9de8a748dadca 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 @@ -258,7 +258,7 @@ public final ClusterClient cluster() { * See Bulk API on elastic.co */ public final BulkResponse bulk(BulkRequest bulkRequest, Header... headers) throws IOException { - return performRequestAndParseEntity(bulkRequest, Request::bulk, BulkResponse::fromXContent, emptySet(), headers); + return performRequestAndParseEntity(bulkRequest, RequestConverters::bulk, BulkResponse::fromXContent, emptySet(), headers); } /** @@ -267,14 +267,14 @@ public final BulkResponse bulk(BulkRequest bulkRequest, Header... headers) throw * See Bulk API on elastic.co */ public final void bulkAsync(BulkRequest bulkRequest, ActionListener listener, Header... headers) { - performRequestAsyncAndParseEntity(bulkRequest, Request::bulk, BulkResponse::fromXContent, listener, emptySet(), headers); + performRequestAsyncAndParseEntity(bulkRequest, RequestConverters::bulk, BulkResponse::fromXContent, listener, emptySet(), headers); } /** * Pings the remote Elasticsearch cluster and returns true if the ping succeeded, false otherwise */ public final boolean ping(Header... headers) throws IOException { - return performRequest(new MainRequest(), (request) -> Request.ping(), RestHighLevelClient::convertExistsResponse, + return performRequest(new MainRequest(), (request) -> RequestConverters.ping(), RestHighLevelClient::convertExistsResponse, emptySet(), headers); } @@ -282,8 +282,8 @@ public final boolean ping(Header... headers) throws IOException { * Get the cluster info otherwise provided when sending an HTTP request to port 9200 */ public final MainResponse info(Header... headers) throws IOException { - return performRequestAndParseEntity(new MainRequest(), (request) -> Request.info(), MainResponse::fromXContent, emptySet(), - headers); + return performRequestAndParseEntity(new MainRequest(), (request) -> RequestConverters.info(), + MainResponse::fromXContent, emptySet(), headers); } /** @@ -292,7 +292,7 @@ public final MainResponse info(Header... headers) throws IOException { * See Get API on elastic.co */ public final GetResponse get(GetRequest getRequest, Header... headers) throws IOException { - return performRequestAndParseEntity(getRequest, Request::get, GetResponse::fromXContent, singleton(404), headers); + return performRequestAndParseEntity(getRequest, RequestConverters::get, GetResponse::fromXContent, singleton(404), headers); } /** @@ -301,7 +301,8 @@ public final GetResponse get(GetRequest getRequest, Header... headers) throws IO * See Get API on elastic.co */ public final void getAsync(GetRequest getRequest, ActionListener listener, Header... headers) { - performRequestAsyncAndParseEntity(getRequest, Request::get, GetResponse::fromXContent, listener, singleton(404), headers); + performRequestAsyncAndParseEntity(getRequest, RequestConverters::get, GetResponse::fromXContent, listener, + singleton(404), headers); } /** @@ -310,7 +311,8 @@ public final void getAsync(GetRequest getRequest, ActionListener li * See Multi Get API on elastic.co */ public final MultiGetResponse multiGet(MultiGetRequest multiGetRequest, Header... headers) throws IOException { - return performRequestAndParseEntity(multiGetRequest, Request::multiGet, MultiGetResponse::fromXContent, singleton(404), headers); + return performRequestAndParseEntity(multiGetRequest, RequestConverters::multiGet, MultiGetResponse::fromXContent, + singleton(404), headers); } /** @@ -319,7 +321,7 @@ public final MultiGetResponse multiGet(MultiGetRequest multiGetRequest, Header.. * See Multi Get API on elastic.co */ public final void multiGetAsync(MultiGetRequest multiGetRequest, ActionListener listener, Header... headers) { - performRequestAsyncAndParseEntity(multiGetRequest, Request::multiGet, MultiGetResponse::fromXContent, listener, + performRequestAsyncAndParseEntity(multiGetRequest, RequestConverters::multiGet, MultiGetResponse::fromXContent, listener, singleton(404), headers); } @@ -329,7 +331,7 @@ public final void multiGetAsync(MultiGetRequest multiGetRequest, ActionListener< * See Get API on elastic.co */ public final boolean exists(GetRequest getRequest, Header... headers) throws IOException { - return performRequest(getRequest, Request::exists, RestHighLevelClient::convertExistsResponse, emptySet(), headers); + return performRequest(getRequest, RequestConverters::exists, RestHighLevelClient::convertExistsResponse, emptySet(), headers); } /** @@ -338,7 +340,8 @@ public final boolean exists(GetRequest getRequest, Header... headers) throws IOE * See Get API on elastic.co */ public final void existsAsync(GetRequest getRequest, ActionListener listener, Header... headers) { - performRequestAsync(getRequest, Request::exists, RestHighLevelClient::convertExistsResponse, listener, emptySet(), headers); + performRequestAsync(getRequest, RequestConverters::exists, RestHighLevelClient::convertExistsResponse, listener, + emptySet(), headers); } /** @@ -347,7 +350,7 @@ public final void existsAsync(GetRequest getRequest, ActionListener lis * See Index API on elastic.co */ public final IndexResponse index(IndexRequest indexRequest, Header... headers) throws IOException { - return performRequestAndParseEntity(indexRequest, Request::index, IndexResponse::fromXContent, emptySet(), headers); + return performRequestAndParseEntity(indexRequest, RequestConverters::index, IndexResponse::fromXContent, emptySet(), headers); } /** @@ -356,7 +359,8 @@ public final IndexResponse index(IndexRequest indexRequest, Header... headers) t * See Index API on elastic.co */ public final void indexAsync(IndexRequest indexRequest, ActionListener listener, Header... headers) { - performRequestAsyncAndParseEntity(indexRequest, Request::index, IndexResponse::fromXContent, listener, emptySet(), headers); + performRequestAsyncAndParseEntity(indexRequest, RequestConverters::index, IndexResponse::fromXContent, listener, + emptySet(), headers); } /** @@ -365,7 +369,7 @@ public final void indexAsync(IndexRequest indexRequest, ActionListenerUpdate API on elastic.co */ public final UpdateResponse update(UpdateRequest updateRequest, Header... headers) throws IOException { - return performRequestAndParseEntity(updateRequest, Request::update, UpdateResponse::fromXContent, emptySet(), headers); + return performRequestAndParseEntity(updateRequest, RequestConverters::update, UpdateResponse::fromXContent, emptySet(), headers); } /** @@ -374,7 +378,8 @@ public final UpdateResponse update(UpdateRequest updateRequest, Header... header * See Update API on elastic.co */ public final void updateAsync(UpdateRequest updateRequest, ActionListener listener, Header... headers) { - performRequestAsyncAndParseEntity(updateRequest, Request::update, UpdateResponse::fromXContent, listener, emptySet(), headers); + performRequestAsyncAndParseEntity(updateRequest, RequestConverters::update, UpdateResponse::fromXContent, listener, + emptySet(), headers); } /** @@ -383,8 +388,8 @@ public final void updateAsync(UpdateRequest updateRequest, ActionListenerDelete API on elastic.co */ public final DeleteResponse delete(DeleteRequest deleteRequest, Header... headers) throws IOException { - return performRequestAndParseEntity(deleteRequest, Request::delete, DeleteResponse::fromXContent, Collections.singleton(404), - headers); + return performRequestAndParseEntity(deleteRequest, RequestConverters::delete, DeleteResponse::fromXContent, + singleton(404), headers); } /** @@ -393,7 +398,7 @@ public final DeleteResponse delete(DeleteRequest deleteRequest, Header... header * See Delete API on elastic.co */ public final void deleteAsync(DeleteRequest deleteRequest, ActionListener listener, Header... headers) { - performRequestAsyncAndParseEntity(deleteRequest, Request::delete, DeleteResponse::fromXContent, listener, + performRequestAsyncAndParseEntity(deleteRequest, RequestConverters::delete, DeleteResponse::fromXContent, listener, Collections.singleton(404), headers); } @@ -403,7 +408,7 @@ public final void deleteAsync(DeleteRequest deleteRequest, ActionListenerSearch API on elastic.co */ public final SearchResponse search(SearchRequest searchRequest, Header... headers) throws IOException { - return performRequestAndParseEntity(searchRequest, Request::search, SearchResponse::fromXContent, emptySet(), headers); + return performRequestAndParseEntity(searchRequest, RequestConverters::search, SearchResponse::fromXContent, emptySet(), headers); } /** @@ -412,7 +417,8 @@ public final SearchResponse search(SearchRequest searchRequest, Header... header * See Search API on elastic.co */ public final void searchAsync(SearchRequest searchRequest, ActionListener listener, Header... headers) { - performRequestAsyncAndParseEntity(searchRequest, Request::search, SearchResponse::fromXContent, listener, emptySet(), headers); + performRequestAsyncAndParseEntity(searchRequest, RequestConverters::search, SearchResponse::fromXContent, listener, + emptySet(), headers); } /** @@ -422,7 +428,7 @@ public final void searchAsync(SearchRequest searchRequest, ActionListener */ public final MultiSearchResponse multiSearch(MultiSearchRequest multiSearchRequest, Header... headers) throws IOException { - return performRequestAndParseEntity(multiSearchRequest, Request::multiSearch, MultiSearchResponse::fromXContext, + return performRequestAndParseEntity(multiSearchRequest, RequestConverters::multiSearch, MultiSearchResponse::fromXContext, emptySet(), headers); } @@ -433,7 +439,7 @@ public final MultiSearchResponse multiSearch(MultiSearchRequest multiSearchReque * elastic.co */ public final void multiSearchAsync(MultiSearchRequest searchRequest, ActionListener listener, Header... headers) { - performRequestAsyncAndParseEntity(searchRequest, Request::multiSearch, MultiSearchResponse::fromXContext, listener, + performRequestAsyncAndParseEntity(searchRequest, RequestConverters::multiSearch, MultiSearchResponse::fromXContext, listener, emptySet(), headers); } @@ -444,7 +450,8 @@ public final void multiSearchAsync(MultiSearchRequest searchRequest, ActionListe * API on elastic.co */ public final SearchResponse searchScroll(SearchScrollRequest searchScrollRequest, Header... headers) throws IOException { - return performRequestAndParseEntity(searchScrollRequest, Request::searchScroll, SearchResponse::fromXContent, emptySet(), headers); + return performRequestAndParseEntity(searchScrollRequest, RequestConverters::searchScroll, SearchResponse::fromXContent, + emptySet(), headers); } /** @@ -455,7 +462,7 @@ public final SearchResponse searchScroll(SearchScrollRequest searchScrollRequest */ public final void searchScrollAsync(SearchScrollRequest searchScrollRequest, ActionListener listener, Header... headers) { - performRequestAsyncAndParseEntity(searchScrollRequest, Request::searchScroll, SearchResponse::fromXContent, + performRequestAsyncAndParseEntity(searchScrollRequest, RequestConverters::searchScroll, SearchResponse::fromXContent, listener, emptySet(), headers); } @@ -466,7 +473,7 @@ public final void searchScrollAsync(SearchScrollRequest searchScrollRequest, * Clear Scroll API on elastic.co */ public final ClearScrollResponse clearScroll(ClearScrollRequest clearScrollRequest, Header... headers) throws IOException { - return performRequestAndParseEntity(clearScrollRequest, Request::clearScroll, ClearScrollResponse::fromXContent, + return performRequestAndParseEntity(clearScrollRequest, RequestConverters::clearScroll, ClearScrollResponse::fromXContent, emptySet(), headers); } @@ -478,7 +485,7 @@ public final ClearScrollResponse clearScroll(ClearScrollRequest clearScrollReque */ public final void clearScrollAsync(ClearScrollRequest clearScrollRequest, ActionListener listener, Header... headers) { - performRequestAsyncAndParseEntity(clearScrollRequest, Request::clearScroll, ClearScrollResponse::fromXContent, + performRequestAsyncAndParseEntity(clearScrollRequest, RequestConverters::clearScroll, ClearScrollResponse::fromXContent, listener, emptySet(), headers); } @@ -489,7 +496,8 @@ public final void clearScrollAsync(ClearScrollRequest clearScrollRequest, * on elastic.co */ public final RankEvalResponse rankEval(RankEvalRequest rankEvalRequest, Header... headers) throws IOException { - return performRequestAndParseEntity(rankEvalRequest, Request::rankEval, RankEvalResponse::fromXContent, emptySet(), headers); + return performRequestAndParseEntity(rankEvalRequest, RequestConverters::rankEval, RankEvalResponse::fromXContent, + emptySet(), headers); } /** @@ -499,8 +507,8 @@ public final RankEvalResponse rankEval(RankEvalRequest rankEvalRequest, Header.. * on elastic.co */ public final void rankEvalAsync(RankEvalRequest rankEvalRequest, ActionListener listener, Header... headers) { - performRequestAsyncAndParseEntity(rankEvalRequest, Request::rankEval, RankEvalResponse::fromXContent, listener, emptySet(), - headers); + performRequestAsyncAndParseEntity(rankEvalRequest, RequestConverters::rankEval, RankEvalResponse::fromXContent, listener, + emptySet(), headers); } /** @@ -511,7 +519,7 @@ public final void rankEvalAsync(RankEvalRequest rankEvalRequest, ActionListener< */ public final FieldCapabilitiesResponse fieldCaps(FieldCapabilitiesRequest fieldCapabilitiesRequest, Header... headers) throws IOException { - return performRequestAndParseEntity(fieldCapabilitiesRequest, Request::fieldCaps, + return performRequestAndParseEntity(fieldCapabilitiesRequest, RequestConverters::fieldCaps, FieldCapabilitiesResponse::fromXContent, emptySet(), headers); } @@ -524,7 +532,7 @@ public final FieldCapabilitiesResponse fieldCaps(FieldCapabilitiesRequest fieldC public final void fieldCapsAsync(FieldCapabilitiesRequest fieldCapabilitiesRequest, ActionListener listener, Header... headers) { - performRequestAsyncAndParseEntity(fieldCapabilitiesRequest, Request::fieldCaps, + performRequestAsyncAndParseEntity(fieldCapabilitiesRequest, RequestConverters::fieldCaps, FieldCapabilitiesResponse::fromXContent, listener, emptySet(), headers); } @@ -544,9 +552,10 @@ protected final Resp performRequest(Req reques throw validationException; } Request req = requestConverter.apply(request); + req.setHeaders(headers); Response response; try { - response = client.performRequest(req.getMethod(), req.getEndpoint(), req.getParameters(), req.getEntity(), headers); + response = client.performRequest(req); } catch (ResponseException e) { if (ignores.contains(e.getResponse().getStatusLine().getStatusCode())) { try { @@ -593,9 +602,10 @@ protected final void performRequestAsync(Req r listener.onFailure(e); return; } + req.setHeaders(headers); ResponseListener responseListener = wrapResponseListener(responseConverter, listener, ignores); - client.performRequestAsync(req.getMethod(), req.getEndpoint(), req.getParameters(), req.getEntity(), responseListener, headers); + client.performRequestAsync(req, responseListener); } final ResponseListener wrapResponseListener(CheckedFunction responseConverter, 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 42496822090fd..617b35c4d40f3 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 @@ -20,7 +20,6 @@ package org.elasticsearch.client; import org.apache.http.Header; -import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.ProtocolVersion; import org.apache.http.RequestLine; @@ -52,14 +51,9 @@ import java.util.List; import java.util.stream.Collectors; -import static java.util.Collections.emptyMap; import static java.util.Collections.emptySet; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyMapOf; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.anyVararg; -import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -79,14 +73,15 @@ public void initClients() throws IOException { final RestClient restClient = mock(RestClient.class); restHighLevelClient = new CustomRestClient(restClient); - doAnswer(mock -> mockPerformRequest((Header) mock.getArguments()[4])) + doAnswer(inv -> mockPerformRequest(((Request) inv.getArguments()[0]).getHeaders()[0])) .when(restClient) - .performRequest(eq(HttpGet.METHOD_NAME), eq(ENDPOINT), anyMapOf(String.class, String.class), anyObject(), anyVararg()); + .performRequest(any(Request.class)); - doAnswer(mock -> mockPerformRequestAsync((Header) mock.getArguments()[5], (ResponseListener) mock.getArguments()[4])) + doAnswer(inv -> mockPerformRequestAsync( + ((Request) inv.getArguments()[0]).getHeaders()[0], + (ResponseListener) inv.getArguments()[1])) .when(restClient) - .performRequestAsync(eq(HttpGet.METHOD_NAME), eq(ENDPOINT), anyMapOf(String.class, String.class), - any(HttpEntity.class), any(ResponseListener.class), anyVararg()); + .performRequestAsync(any(Request.class), any(ResponseListener.class)); } } @@ -193,7 +188,7 @@ void customAndParseAsync(MainRequest mainRequest, ActionListener l } Request toRequest(MainRequest mainRequest) throws IOException { - return new Request(HttpGet.METHOD_NAME, ENDPOINT, emptyMap(), null); + return new Request(HttpGet.METHOD_NAME, ENDPOINT); } MainResponse toResponse(Response response) throws IOException { diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java similarity index 89% rename from client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java rename to client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java index 0fdeb7555a04a..3f9428a3aea0d 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java @@ -82,6 +82,8 @@ import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.client.RequestConverters.EndpointBuilder; +import org.elasticsearch.client.RequestConverters.Params; import org.elasticsearch.index.RandomCreateIndexGenerator; import org.elasticsearch.index.VersionType; import org.elasticsearch.index.query.TermQueryBuilder; @@ -124,8 +126,8 @@ import java.util.function.Supplier; import static java.util.Collections.singletonMap; -import static org.elasticsearch.client.Request.REQUEST_BODY_CONTENT_TYPE; -import static org.elasticsearch.client.Request.enforceSameContentType; +import static org.elasticsearch.client.RequestConverters.REQUEST_BODY_CONTENT_TYPE; +import static org.elasticsearch.client.RequestConverters.enforceSameContentType; import static org.elasticsearch.index.RandomCreateIndexGenerator.randomAliases; import static org.elasticsearch.index.RandomCreateIndexGenerator.randomCreateIndexRequest; import static org.elasticsearch.index.RandomCreateIndexGenerator.randomIndexSettings; @@ -137,40 +139,9 @@ import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.nullValue; -public class RequestTests extends ESTestCase { - - public void testConstructor() { - final String method = randomFrom("GET", "PUT", "POST", "HEAD", "DELETE"); - final String endpoint = randomAlphaOfLengthBetween(1, 10); - final Map parameters = singletonMap(randomAlphaOfLength(5), randomAlphaOfLength(5)); - final HttpEntity entity = randomBoolean() ? new StringEntity(randomAlphaOfLengthBetween(1, 100), ContentType.TEXT_PLAIN) : null; - - NullPointerException e = expectThrows(NullPointerException.class, () -> new Request(null, endpoint, parameters, entity)); - assertEquals("method cannot be null", e.getMessage()); - - e = expectThrows(NullPointerException.class, () -> new Request(method, null, parameters, entity)); - assertEquals("endpoint cannot be null", e.getMessage()); - - e = expectThrows(NullPointerException.class, () -> new Request(method, endpoint, null, entity)); - assertEquals("parameters cannot be null", e.getMessage()); - - final Request request = new Request(method, endpoint, parameters, entity); - assertEquals(method, request.getMethod()); - assertEquals(endpoint, request.getEndpoint()); - assertEquals(parameters, request.getParameters()); - assertEquals(entity, request.getEntity()); - - final Constructor[] constructors = Request.class.getConstructors(); - assertEquals("Expected only 1 constructor", 1, constructors.length); - assertTrue("Request constructor is not public", Modifier.isPublic(constructors[0].getModifiers())); - } - - public void testClassVisibility() { - assertTrue("Request class is not public", Modifier.isPublic(Request.class.getModifiers())); - } - +public class RequestConvertersTests extends ESTestCase { public void testPing() { - Request request = Request.ping(); + Request request = RequestConverters.ping(); assertEquals("/", request.getEndpoint()); assertEquals(0, request.getParameters().size()); assertNull(request.getEntity()); @@ -178,7 +149,7 @@ public void testPing() { } public void testInfo() { - Request request = Request.info(); + Request request = RequestConverters.info(); assertEquals("/", request.getEndpoint()); assertEquals(0, request.getParameters().size()); assertNull(request.getEntity()); @@ -186,7 +157,7 @@ public void testInfo() { } public void testGet() { - getAndExistsTest(Request::get, HttpGet.METHOD_NAME); + getAndExistsTest(RequestConverters::get, HttpGet.METHOD_NAME); } public void testMultiGet() throws IOException { @@ -232,7 +203,7 @@ public void testMultiGet() throws IOException { multiGetRequest.add(item); } - Request request = Request.multiGet(multiGetRequest); + Request request = RequestConverters.multiGet(multiGetRequest); assertEquals(HttpPost.METHOD_NAME, request.getMethod()); assertEquals("/_mget", request.getEndpoint()); assertEquals(expectedParams, request.getParameters()); @@ -260,7 +231,7 @@ public void testDelete() { } } - Request request = Request.delete(deleteRequest); + Request request = RequestConverters.delete(deleteRequest); assertEquals("/" + index + "/" + type + "/" + id, request.getEndpoint()); assertEquals(expectedParams, request.getParameters()); assertEquals(HttpDelete.METHOD_NAME, request.getMethod()); @@ -268,7 +239,7 @@ public void testDelete() { } public void testExists() { - getAndExistsTest(Request::exists, HttpHead.METHOD_NAME); + getAndExistsTest(RequestConverters::exists, HttpHead.METHOD_NAME); } public void testIndicesExist() { @@ -282,7 +253,7 @@ public void testIndicesExist() { setRandomHumanReadable(getIndexRequest, expectedParams); setRandomIncludeDefaults(getIndexRequest, expectedParams); - final Request request = Request.indicesExist(getIndexRequest); + final Request request = RequestConverters.indicesExist(getIndexRequest); assertEquals(HttpHead.METHOD_NAME, request.getMethod()); assertEquals("/" + String.join(",", indices), request.getEndpoint()); @@ -291,8 +262,8 @@ public void testIndicesExist() { } public void testIndicesExistEmptyIndices() { - expectThrows(IllegalArgumentException.class, () -> Request.indicesExist(new GetIndexRequest())); - expectThrows(IllegalArgumentException.class, () -> Request.indicesExist(new GetIndexRequest().indices((String[])null))); + expectThrows(IllegalArgumentException.class, () -> RequestConverters.indicesExist(new GetIndexRequest())); + expectThrows(IllegalArgumentException.class, () -> RequestConverters.indicesExist(new GetIndexRequest().indices((String[])null))); } private static void getAndExistsTest(Function requestConverter, String method) { @@ -361,7 +332,7 @@ public void testCreateIndex() throws IOException { setRandomMasterTimeout(createIndexRequest, expectedParams); setRandomWaitForActiveShards(createIndexRequest::waitForActiveShards, expectedParams); - Request request = Request.createIndex(createIndexRequest); + Request request = RequestConverters.createIndex(createIndexRequest); assertEquals("/" + createIndexRequest.index(), request.getEndpoint()); assertEquals(expectedParams, request.getParameters()); assertEquals(HttpPut.METHOD_NAME, request.getMethod()); @@ -382,7 +353,7 @@ public void testUpdateAliases() throws IOException { setRandomTimeout(indicesAliasesRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams); setRandomMasterTimeout(indicesAliasesRequest, expectedParams); - Request request = Request.updateAliases(indicesAliasesRequest); + Request request = RequestConverters.updateAliases(indicesAliasesRequest); assertEquals("/_aliases", request.getEndpoint()); assertEquals(expectedParams, request.getParameters()); assertToXContentBody(indicesAliasesRequest, request.getEntity()); @@ -402,7 +373,7 @@ public void testPutMapping() throws IOException { setRandomTimeout(putMappingRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams); setRandomMasterTimeout(putMappingRequest, expectedParams); - Request request = Request.putMapping(putMappingRequest); + Request request = RequestConverters.putMapping(putMappingRequest); StringJoiner endpoint = new StringJoiner("/", "/", ""); String index = String.join(",", indices); if (Strings.hasLength(index)) { @@ -427,7 +398,7 @@ public void testDeleteIndex() { setRandomIndicesOptions(deleteIndexRequest::indicesOptions, deleteIndexRequest::indicesOptions, expectedParams); - Request request = Request.deleteIndex(deleteIndexRequest); + Request request = RequestConverters.deleteIndex(deleteIndexRequest); assertEquals("/" + String.join(",", indices), request.getEndpoint()); assertEquals(expectedParams, request.getParameters()); assertEquals(HttpDelete.METHOD_NAME, request.getMethod()); @@ -451,7 +422,7 @@ public void testOpenIndex() { setRandomIndicesOptions(openIndexRequest::indicesOptions, openIndexRequest::indicesOptions, expectedParams); setRandomWaitForActiveShards(openIndexRequest::waitForActiveShards, expectedParams); - Request request = Request.openIndex(openIndexRequest); + Request request = RequestConverters.openIndex(openIndexRequest); StringJoiner endpoint = new StringJoiner("/", "/", "").add(String.join(",", indices)).add("_open"); assertThat(endpoint.toString(), equalTo(request.getEndpoint())); assertThat(expectedParams, equalTo(request.getParameters())); @@ -474,7 +445,7 @@ public void testCloseIndex() { setRandomMasterTimeout(closeIndexRequest, expectedParams); setRandomIndicesOptions(closeIndexRequest::indicesOptions, closeIndexRequest::indicesOptions, expectedParams); - Request request = Request.closeIndex(closeIndexRequest); + Request request = RequestConverters.closeIndex(closeIndexRequest); StringJoiner endpoint = new StringJoiner("/", "/", "").add(String.join(",", indices)).add("_close"); assertThat(endpoint.toString(), equalTo(request.getEndpoint())); assertThat(expectedParams, equalTo(request.getParameters())); @@ -542,7 +513,7 @@ public void testIndex() throws IOException { indexRequest.source(builder); } - Request request = Request.index(indexRequest); + Request request = RequestConverters.index(indexRequest); if (indexRequest.opType() == DocWriteRequest.OpType.CREATE) { assertEquals("/" + index + "/" + type + "/" + id + "/_create", request.getEndpoint()); } else if (id != null) { @@ -572,7 +543,7 @@ public void testRefresh() { } Map expectedParams = new HashMap<>(); setRandomIndicesOptions(refreshRequest::indicesOptions, refreshRequest::indicesOptions, expectedParams); - Request request = Request.refresh(refreshRequest); + Request request = RequestConverters.refresh(refreshRequest); StringJoiner endpoint = new StringJoiner("/", "/", ""); if (indices != null && indices.length > 0) { endpoint.add(String.join(",", indices)); @@ -604,7 +575,7 @@ public void testFlush() { } expectedParams.put("wait_if_ongoing", Boolean.toString(flushRequest.waitIfOngoing())); - Request request = Request.flush(flushRequest); + Request request = RequestConverters.flush(flushRequest); StringJoiner endpoint = new StringJoiner("/", "/", ""); if (indices != null && indices.length > 0) { endpoint.add(String.join(",", indices)); @@ -641,7 +612,7 @@ public void testForceMerge() { } expectedParams.put("flush", Boolean.toString(forceMergeRequest.flush())); - Request request = Request.forceMerge(forceMergeRequest); + Request request = RequestConverters.forceMerge(forceMergeRequest); StringJoiner endpoint = new StringJoiner("/", "/", ""); if (indices != null && indices.length > 0) { endpoint.add(String.join(",", indices)); @@ -681,7 +652,7 @@ public void testClearCache() { expectedParams.put("fields", String.join(",", clearIndicesCacheRequest.fields())); } - Request request = Request.clearCache(clearIndicesCacheRequest); + Request request = RequestConverters.clearCache(clearIndicesCacheRequest); StringJoiner endpoint = new StringJoiner("/", "/", ""); if (indices != null && indices.length > 0) { endpoint.add(String.join(",", indices)); @@ -754,7 +725,7 @@ public void testUpdate() throws IOException { randomizeFetchSourceContextParams(updateRequest::fetchSource, expectedParams); } - Request request = Request.update(updateRequest); + Request request = RequestConverters.update(updateRequest); assertEquals("/" + index + "/" + type + "/" + id + "/_update", request.getEndpoint()); assertEquals(expectedParams, request.getParameters()); assertEquals(HttpPost.METHOD_NAME, request.getMethod()); @@ -791,7 +762,7 @@ public void testUpdateWithDifferentContentTypes() { UpdateRequest updateRequest = new UpdateRequest(); updateRequest.doc(new IndexRequest().source(singletonMap("field", "doc"), XContentType.JSON)); updateRequest.upsert(new IndexRequest().source(singletonMap("field", "upsert"), XContentType.YAML)); - Request.update(updateRequest); + RequestConverters.update(updateRequest); }); assertEquals("Update request cannot have different content types for doc [JSON] and upsert [YAML] documents", exception.getMessage()); @@ -859,7 +830,7 @@ public void testBulk() throws IOException { bulkRequest.add(docWriteRequest); } - Request request = Request.bulk(bulkRequest); + Request request = RequestConverters.bulk(bulkRequest); assertEquals("/_bulk", request.getEndpoint()); assertEquals(expectedParams, request.getParameters()); assertEquals(HttpPost.METHOD_NAME, request.getMethod()); @@ -914,7 +885,7 @@ public void testBulkWithDifferentContentTypes() throws IOException { bulkRequest.add(new UpdateRequest("index", "type", "1").script(mockScript("test"))); bulkRequest.add(new DeleteRequest("index", "type", "2")); - Request request = Request.bulk(bulkRequest); + Request request = RequestConverters.bulk(bulkRequest); assertEquals(XContentType.JSON.mediaTypeWithoutParameters(), request.getEntity().getContentType().getValue()); } { @@ -924,7 +895,7 @@ public void testBulkWithDifferentContentTypes() throws IOException { bulkRequest.add(new IndexRequest("index", "type", "0").source(singletonMap("field", "value"), xContentType)); bulkRequest.add(new DeleteRequest("index", "type", "2")); - Request request = Request.bulk(bulkRequest); + Request request = RequestConverters.bulk(bulkRequest); assertEquals(xContentType.mediaTypeWithoutParameters(), request.getEntity().getContentType().getValue()); } { @@ -936,14 +907,14 @@ public void testBulkWithDifferentContentTypes() throws IOException { updateRequest.upsert(new IndexRequest().source(singletonMap("field", "value"), xContentType)); } - Request request = Request.bulk(new BulkRequest().add(updateRequest)); + Request request = RequestConverters.bulk(new BulkRequest().add(updateRequest)); assertEquals(xContentType.mediaTypeWithoutParameters(), request.getEntity().getContentType().getValue()); } { BulkRequest bulkRequest = new BulkRequest(); bulkRequest.add(new IndexRequest("index", "type", "0").source(singletonMap("field", "value"), XContentType.SMILE)); bulkRequest.add(new IndexRequest("index", "type", "1").source(singletonMap("field", "value"), XContentType.JSON)); - IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> Request.bulk(bulkRequest)); + IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> RequestConverters.bulk(bulkRequest)); assertEquals("Mismatching content-type found for request with content-type [JSON], " + "previous requests have content-type [SMILE]", exception.getMessage()); } @@ -957,7 +928,7 @@ public void testBulkWithDifferentContentTypes() throws IOException { .doc(new IndexRequest().source(singletonMap("field", "value"), XContentType.JSON)) .upsert(new IndexRequest().source(singletonMap("field", "value"), XContentType.SMILE)) ); - IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> Request.bulk(bulkRequest)); + IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> RequestConverters.bulk(bulkRequest)); assertEquals("Mismatching content-type found for request with content-type [SMILE], " + "previous requests have content-type [JSON]", exception.getMessage()); } @@ -970,7 +941,7 @@ public void testBulkWithDifferentContentTypes() throws IOException { bulkRequest.add(new DeleteRequest("index", "type", "3")); bulkRequest.add(new IndexRequest("index", "type", "4").source(singletonMap("field", "value"), XContentType.JSON)); bulkRequest.add(new IndexRequest("index", "type", "1").source(singletonMap("field", "value"), xContentType)); - IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> Request.bulk(bulkRequest)); + IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> RequestConverters.bulk(bulkRequest)); assertEquals("Unsupported content-type found for request with content-type [" + xContentType + "], only JSON and SMILE are supported", exception.getMessage()); } @@ -978,7 +949,7 @@ public void testBulkWithDifferentContentTypes() throws IOException { public void testSearchNullSource() throws IOException { SearchRequest searchRequest = new SearchRequest(); - Request request = Request.search(searchRequest); + Request request = RequestConverters.search(searchRequest); assertEquals(HttpPost.METHOD_NAME, request.getMethod()); assertEquals("/_search", request.getEndpoint()); assertNull(request.getEntity()); @@ -1073,7 +1044,7 @@ public void testSearch() throws Exception { searchRequest.source(searchSourceBuilder); } - Request request = Request.search(searchRequest); + Request request = RequestConverters.search(searchRequest); StringJoiner endpoint = new StringJoiner("/", "/", ""); String index = String.join(",", indices); if (Strings.hasLength(index)) { @@ -1127,7 +1098,7 @@ public void testMultiSearch() throws IOException { expectedParams.put("max_concurrent_searches", Integer.toString(multiSearchRequest.maxConcurrentSearchRequests())); } - Request request = Request.multiSearch(multiSearchRequest); + Request request = RequestConverters.multiSearch(multiSearchRequest); assertEquals("/_msearch", request.getEndpoint()); assertEquals(HttpPost.METHOD_NAME, request.getMethod()); assertEquals(expectedParams, request.getParameters()); @@ -1152,7 +1123,7 @@ public void testSearchScroll() throws IOException { if (randomBoolean()) { searchScrollRequest.scroll(randomPositiveTimeValue()); } - Request request = Request.searchScroll(searchScrollRequest); + Request request = RequestConverters.searchScroll(searchScrollRequest); assertEquals(HttpPost.METHOD_NAME, request.getMethod()); assertEquals("/_search/scroll", request.getEndpoint()); assertEquals(0, request.getParameters().size()); @@ -1166,7 +1137,7 @@ public void testClearScroll() throws IOException { for (int i = 0; i < numScrolls; i++) { clearScrollRequest.addScrollId(randomAlphaOfLengthBetween(5, 10)); } - Request request = Request.clearScroll(clearScrollRequest); + Request request = RequestConverters.clearScroll(clearScrollRequest); assertEquals(HttpDelete.METHOD_NAME, request.getMethod()); assertEquals("/_search/scroll", request.getEndpoint()); assertEquals(0, request.getParameters().size()); @@ -1191,7 +1162,7 @@ public void testExistsAlias() { setRandomLocal(getAliasesRequest, expectedParams); setRandomIndicesOptions(getAliasesRequest::indicesOptions, getAliasesRequest::indicesOptions, expectedParams); - Request request = Request.existsAlias(getAliasesRequest); + Request request = RequestConverters.existsAlias(getAliasesRequest); StringJoiner expectedEndpoint = new StringJoiner("/", "/", ""); if (indices != null && indices.length > 0) { expectedEndpoint.add(String.join(",", indices)); @@ -1209,13 +1180,15 @@ public void testExistsAlias() { public void testExistsAliasNoAliasNoIndex() { { GetAliasesRequest getAliasesRequest = new GetAliasesRequest(); - IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> Request.existsAlias(getAliasesRequest)); + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> + RequestConverters.existsAlias(getAliasesRequest)); assertEquals("existsAlias requires at least an alias or an index", iae.getMessage()); } { GetAliasesRequest getAliasesRequest = new GetAliasesRequest((String[])null); getAliasesRequest.indices((String[])null); - IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> Request.existsAlias(getAliasesRequest)); + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> + RequestConverters.existsAlias(getAliasesRequest)); assertEquals("existsAlias requires at least an alias or an index", iae.getMessage()); } } @@ -1234,7 +1207,7 @@ public void testFieldCaps() { fieldCapabilitiesRequest::indicesOptions, indicesOptionsParams); - Request request = Request.fieldCaps(fieldCapabilitiesRequest); + Request request = RequestConverters.fieldCaps(fieldCapabilitiesRequest); // Verify that the resulting REST request looks as expected. StringJoiner endpoint = new StringJoiner("/", "/", ""); @@ -1270,7 +1243,7 @@ public void testRankEval() throws Exception { Map expectedParams = new HashMap<>(); setRandomIndicesOptions(rankEvalRequest::indicesOptions, rankEvalRequest::indicesOptions, expectedParams); - Request request = Request.rankEval(rankEvalRequest); + Request request = RequestConverters.rankEval(rankEvalRequest); StringJoiner endpoint = new StringJoiner("/", "/", ""); String index = String.join(",", indices); if (Strings.hasLength(index)) { @@ -1284,25 +1257,25 @@ public void testRankEval() throws Exception { } public void testSplit() throws IOException { - resizeTest(ResizeType.SPLIT, Request::split); + resizeTest(ResizeType.SPLIT, RequestConverters::split); } public void testSplitWrongResizeType() { ResizeRequest resizeRequest = new ResizeRequest("target", "source"); resizeRequest.setResizeType(ResizeType.SHRINK); - IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> Request.split(resizeRequest)); + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> RequestConverters.split(resizeRequest)); assertEquals("Wrong resize type [SHRINK] for indices split request", iae.getMessage()); } public void testShrinkWrongResizeType() { ResizeRequest resizeRequest = new ResizeRequest("target", "source"); resizeRequest.setResizeType(ResizeType.SPLIT); - IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> Request.shrink(resizeRequest)); + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> RequestConverters.shrink(resizeRequest)); assertEquals("Wrong resize type [SPLIT] for indices shrink request", iae.getMessage()); } public void testShrink() throws IOException { - resizeTest(ResizeType.SHRINK, Request::shrink); + resizeTest(ResizeType.SHRINK, RequestConverters::shrink); } private static void resizeTest(ResizeType resizeType, CheckedFunction function) @@ -1341,7 +1314,7 @@ public void testClusterPutSettings() throws IOException { setRandomMasterTimeout(request, expectedParams); setRandomTimeout(request::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams); - Request expectedRequest = Request.clusterPutSettings(request); + Request expectedRequest = RequestConverters.clusterPutSettings(request); assertEquals("/_cluster/settings", expectedRequest.getEndpoint()); assertEquals(HttpPut.METHOD_NAME, expectedRequest.getMethod()); assertEquals(expectedParams, expectedRequest.getParameters()); @@ -1374,7 +1347,7 @@ public void testRollover() throws IOException { } setRandomWaitForActiveShards(rolloverRequest.getCreateIndexRequest()::waitForActiveShards, expectedParams); - Request request = Request.rollover(rolloverRequest); + Request request = RequestConverters.rollover(rolloverRequest); if (rolloverRequest.getNewIndexName() == null) { assertEquals("/" + rolloverRequest.getAlias() + "/_rollover", request.getEndpoint()); } else { @@ -1399,7 +1372,7 @@ public void testIndexPutSettings() throws IOException { } } - Request request = Request.indexPutSettings(updateSettingsRequest); + Request request = RequestConverters.indexPutSettings(updateSettingsRequest); StringJoiner endpoint = new StringJoiner("/", "/", ""); if (indices != null && indices.length > 0) { endpoint.add(String.join(",", indices)); @@ -1417,143 +1390,115 @@ private static void assertToXContentBody(ToXContent expectedBody, HttpEntity act assertEquals(expectedBytes, new BytesArray(EntityUtils.toByteArray(actualEntity))); } - public void testParams() { - final int nbParams = randomIntBetween(0, 10); - Request.Params params = Request.Params.builder(); - Map expectedParams = new HashMap<>(); - for (int i = 0; i < nbParams; i++) { - String paramName = "p_" + i; - String paramValue = randomAlphaOfLength(5); - params.putParam(paramName, paramValue); - expectedParams.put(paramName, paramValue); - } - - Map requestParams = params.getParams(); - assertEquals(nbParams, requestParams.size()); - assertEquals(expectedParams, requestParams); - } - - public void testParamsNoDuplicates() { - Request.Params params = Request.Params.builder(); - params.putParam("test", "1"); - - IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> params.putParam("test", "2")); - assertEquals("Request parameter [test] is already registered", e.getMessage()); - - Map requestParams = params.getParams(); - assertEquals(1L, requestParams.size()); - assertEquals("1", requestParams.values().iterator().next()); - } - public void testEndpointBuilder() { { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder(); + EndpointBuilder endpointBuilder = new EndpointBuilder(); assertEquals("/", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart(Strings.EMPTY_ARRAY); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart(Strings.EMPTY_ARRAY); assertEquals("/", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart(""); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart(""); assertEquals("/", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("a", "b"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("a", "b"); assertEquals("/a/b", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("a").addPathPart("b") + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("a").addPathPart("b") .addPathPartAsIs("_create"); assertEquals("/a/b/_create", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("a", "b", "c") + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("a", "b", "c") .addPathPartAsIs("_create"); assertEquals("/a/b/c/_create", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("a").addPathPartAsIs("_create"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("a").addPathPartAsIs("_create"); assertEquals("/a/_create", endpointBuilder.build()); } } public void testEndpointBuilderEncodeParts() { { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("-#index1,index#2", "type", "id"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("-#index1,index#2", "type", "id"); assertEquals("/-%23index1,index%232/type/id", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("index", "type#2", "id"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("index", "type#2", "id"); assertEquals("/index/type%232/id", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("index", "type", "this/is/the/id"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("index", "type", "this/is/the/id"); assertEquals("/index/type/this%2Fis%2Fthe%2Fid", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("index", "type", "this|is|the|id"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("index", "type", "this|is|the|id"); assertEquals("/index/type/this%7Cis%7Cthe%7Cid", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("index", "type", "id#1"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("index", "type", "id#1"); assertEquals("/index/type/id%231", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("", "_search"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("", "_search"); assertEquals("/%3Clogstash-%7Bnow%2FM%7D%3E/_search", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("中文"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("中文"); assertEquals("/中文", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("foo bar"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("foo bar"); assertEquals("/foo%20bar", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("foo+bar"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("foo+bar"); assertEquals("/foo+bar", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("foo+bar"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("foo+bar"); assertEquals("/foo+bar", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("foo/bar"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("foo/bar"); assertEquals("/foo%2Fbar", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("foo^bar"); + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("foo^bar"); assertEquals("/foo%5Ebar", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder().addPathPart("cluster1:index1,index2") + EndpointBuilder endpointBuilder = new EndpointBuilder().addPathPart("cluster1:index1,index2") .addPathPartAsIs("_search"); assertEquals("/cluster1:index1,index2/_search", endpointBuilder.build()); } { - Request.EndpointBuilder endpointBuilder = new Request.EndpointBuilder() + EndpointBuilder endpointBuilder = new EndpointBuilder() .addCommaSeparatedPathParts(new String[]{"index1", "index2"}).addPathPartAsIs("cache/clear"); assertEquals("/index1,index2/cache/clear", endpointBuilder.build()); } } public void testEndpoint() { - assertEquals("/index/type/id", Request.endpoint("index", "type", "id")); - assertEquals("/index/type/id/_endpoint", Request.endpoint("index", "type", "id", "_endpoint")); - assertEquals("/index1,index2", Request.endpoint(new String[]{"index1", "index2"})); - assertEquals("/index1,index2/_endpoint", Request.endpoint(new String[]{"index1", "index2"}, "_endpoint")); - assertEquals("/index1,index2/type1,type2/_endpoint", Request.endpoint(new String[]{"index1", "index2"}, + assertEquals("/index/type/id", RequestConverters.endpoint("index", "type", "id")); + assertEquals("/index/type/id/_endpoint", RequestConverters.endpoint("index", "type", "id", "_endpoint")); + assertEquals("/index1,index2", RequestConverters.endpoint(new String[]{"index1", "index2"})); + assertEquals("/index1,index2/_endpoint", RequestConverters.endpoint(new String[]{"index1", "index2"}, "_endpoint")); + assertEquals("/index1,index2/type1,type2/_endpoint", RequestConverters.endpoint(new String[]{"index1", "index2"}, new String[]{"type1", "type2"}, "_endpoint")); - assertEquals("/index1,index2/_endpoint/suffix1,suffix2", Request.endpoint(new String[]{"index1", "index2"}, + assertEquals("/index1,index2/_endpoint/suffix1,suffix2", RequestConverters.endpoint(new String[]{"index1", "index2"}, "_endpoint", new String[]{"suffix1", "suffix2"})); } public void testCreateContentType() { final XContentType xContentType = randomFrom(XContentType.values()); - assertEquals(xContentType.mediaTypeWithoutParameters(), Request.createContentType(xContentType).getMimeType()); + assertEquals(xContentType.mediaTypeWithoutParameters(), RequestConverters.createContentType(xContentType).getMimeType()); } public void testEnforceSameContentType() { diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java index b8315bd59fa43..5ca9b05f73adf 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java @@ -94,14 +94,7 @@ import static org.elasticsearch.client.RestClientTestUtil.randomHeaders; import static org.elasticsearch.common.xcontent.XContentHelper.toXContent; import static org.hamcrest.CoreMatchers.instanceOf; -import static org.mockito.Matchers.anyMapOf; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.anyVararg; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isNotNull; -import static org.mockito.Matchers.isNull; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -134,31 +127,22 @@ public void testPingSuccessful() throws IOException { Header[] headers = randomHeaders(random(), "Header"); Response response = mock(Response.class); when(response.getStatusLine()).thenReturn(newStatusLine(RestStatus.OK)); - when(restClient.performRequest(anyString(), anyString(), anyMapOf(String.class, String.class), - anyObject(), anyVararg())).thenReturn(response); + when(restClient.performRequest(any(Request.class))).thenReturn(response); assertTrue(restHighLevelClient.ping(headers)); - verify(restClient).performRequest(eq(HttpHead.METHOD_NAME), eq("/"), eq(Collections.emptyMap()), - isNull(HttpEntity.class), argThat(new HeadersVarargMatcher(headers))); } public void testPing404NotFound() throws IOException { Header[] headers = randomHeaders(random(), "Header"); Response response = mock(Response.class); when(response.getStatusLine()).thenReturn(newStatusLine(RestStatus.NOT_FOUND)); - when(restClient.performRequest(anyString(), anyString(), anyMapOf(String.class, String.class), - anyObject(), anyVararg())).thenReturn(response); + when(restClient.performRequest(any(Request.class))).thenReturn(response); assertFalse(restHighLevelClient.ping(headers)); - verify(restClient).performRequest(eq(HttpHead.METHOD_NAME), eq("/"), eq(Collections.emptyMap()), - isNull(HttpEntity.class), argThat(new HeadersVarargMatcher(headers))); } public void testPingSocketTimeout() throws IOException { Header[] headers = randomHeaders(random(), "Header"); - when(restClient.performRequest(anyString(), anyString(), anyMapOf(String.class, String.class), - anyObject(), anyVararg())).thenThrow(new SocketTimeoutException()); + when(restClient.performRequest(any(Request.class))).thenThrow(new SocketTimeoutException()); expectThrows(SocketTimeoutException.class, () -> restHighLevelClient.ping(headers)); - verify(restClient).performRequest(eq(HttpHead.METHOD_NAME), eq("/"), eq(Collections.emptyMap()), - isNull(HttpEntity.class), argThat(new HeadersVarargMatcher(headers))); } public void testInfo() throws IOException { @@ -168,8 +152,6 @@ public void testInfo() throws IOException { mockResponse(testInfo); MainResponse receivedInfo = restHighLevelClient.info(headers); assertEquals(testInfo, receivedInfo); - verify(restClient).performRequest(eq(HttpGet.METHOD_NAME), eq("/"), eq(Collections.emptyMap()), - isNull(HttpEntity.class), argThat(new HeadersVarargMatcher(headers))); } public void testSearchScroll() throws IOException { @@ -185,8 +167,6 @@ public void testSearchScroll() throws IOException { assertEquals(5, searchResponse.getTotalShards()); assertEquals(5, searchResponse.getSuccessfulShards()); assertEquals(100, searchResponse.getTook().getMillis()); - verify(restClient).performRequest(eq(HttpPost.METHOD_NAME), eq("/_search/scroll"), eq(Collections.emptyMap()), - isNotNull(HttpEntity.class), argThat(new HeadersVarargMatcher(headers))); } public void testClearScroll() throws IOException { @@ -198,17 +178,14 @@ public void testClearScroll() throws IOException { ClearScrollResponse clearScrollResponse = restHighLevelClient.clearScroll(clearScrollRequest, headers); assertEquals(mockClearScrollResponse.isSucceeded(), clearScrollResponse.isSucceeded()); assertEquals(mockClearScrollResponse.getNumFreed(), clearScrollResponse.getNumFreed()); - verify(restClient).performRequest(eq(HttpDelete.METHOD_NAME), eq("/_search/scroll"), eq(Collections.emptyMap()), - isNotNull(HttpEntity.class), argThat(new HeadersVarargMatcher(headers))); } private void mockResponse(ToXContent toXContent) throws IOException { Response response = mock(Response.class); - ContentType contentType = ContentType.parse(Request.REQUEST_BODY_CONTENT_TYPE.mediaType()); - String requestBody = toXContent(toXContent, Request.REQUEST_BODY_CONTENT_TYPE, false).utf8ToString(); + ContentType contentType = ContentType.parse(RequestConverters.REQUEST_BODY_CONTENT_TYPE.mediaType()); + String requestBody = toXContent(toXContent, RequestConverters.REQUEST_BODY_CONTENT_TYPE, false).utf8ToString(); when(response.getEntity()).thenReturn(new NStringEntity(requestBody, contentType)); - when(restClient.performRequest(anyString(), anyString(), anyMapOf(String.class, String.class), - anyObject(), anyVararg())).thenReturn(response); + when(restClient.performRequest(any(Request.class))).thenReturn(response); } public void testRequestValidation() { @@ -336,13 +313,11 @@ public void testParseResponseException() throws IOException { public void testPerformRequestOnSuccess() throws IOException { MainRequest mainRequest = new MainRequest(); - CheckedFunction requestConverter = request -> - new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null); + CheckedFunction requestConverter = request -> new Request(HttpGet.METHOD_NAME, "/"); RestStatus restStatus = randomFrom(RestStatus.values()); HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus)); Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse); - when(restClient.performRequest(anyString(), anyString(), anyMapOf(String.class, String.class), - anyObject(), anyVararg())).thenReturn(mockResponse); + when(restClient.performRequest(any(Request.class))).thenReturn(mockResponse); { Integer result = restHighLevelClient.performRequest(mainRequest, requestConverter, response -> response.getStatusLine().getStatusCode(), Collections.emptySet()); @@ -358,14 +333,12 @@ public void testPerformRequestOnSuccess() throws IOException { public void testPerformRequestOnResponseExceptionWithoutEntity() throws IOException { MainRequest mainRequest = new MainRequest(); - CheckedFunction requestConverter = request -> - new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null); + CheckedFunction requestConverter = request -> new Request(HttpGet.METHOD_NAME, "/"); RestStatus restStatus = randomFrom(RestStatus.values()); HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus)); Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse); ResponseException responseException = new ResponseException(mockResponse); - when(restClient.performRequest(anyString(), anyString(), anyMapOf(String.class, String.class), - anyObject(), anyVararg())).thenThrow(responseException); + when(restClient.performRequest(any(Request.class))).thenThrow(responseException); ElasticsearchException elasticsearchException = expectThrows(ElasticsearchException.class, () -> restHighLevelClient.performRequest(mainRequest, requestConverter, response -> response.getStatusLine().getStatusCode(), Collections.emptySet())); @@ -376,16 +349,14 @@ public void testPerformRequestOnResponseExceptionWithoutEntity() throws IOExcept public void testPerformRequestOnResponseExceptionWithEntity() throws IOException { MainRequest mainRequest = new MainRequest(); - CheckedFunction requestConverter = request -> - new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null); + CheckedFunction requestConverter = request -> new Request(HttpGet.METHOD_NAME, "/"); RestStatus restStatus = randomFrom(RestStatus.values()); HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus)); httpResponse.setEntity(new StringEntity("{\"error\":\"test error message\",\"status\":" + restStatus.getStatus() + "}", ContentType.APPLICATION_JSON)); Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse); ResponseException responseException = new ResponseException(mockResponse); - when(restClient.performRequest(anyString(), anyString(), anyMapOf(String.class, String.class), - anyObject(), anyVararg())).thenThrow(responseException); + when(restClient.performRequest(any(Request.class))).thenThrow(responseException); ElasticsearchException elasticsearchException = expectThrows(ElasticsearchException.class, () -> restHighLevelClient.performRequest(mainRequest, requestConverter, response -> response.getStatusLine().getStatusCode(), Collections.emptySet())); @@ -396,15 +367,13 @@ public void testPerformRequestOnResponseExceptionWithEntity() throws IOException public void testPerformRequestOnResponseExceptionWithBrokenEntity() throws IOException { MainRequest mainRequest = new MainRequest(); - CheckedFunction requestConverter = request -> - new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null); + CheckedFunction requestConverter = request -> new Request(HttpGet.METHOD_NAME, "/"); RestStatus restStatus = randomFrom(RestStatus.values()); HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus)); httpResponse.setEntity(new StringEntity("{\"error\":", ContentType.APPLICATION_JSON)); Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse); ResponseException responseException = new ResponseException(mockResponse); - when(restClient.performRequest(anyString(), anyString(), anyMapOf(String.class, String.class), - anyObject(), anyVararg())).thenThrow(responseException); + when(restClient.performRequest(any(Request.class))).thenThrow(responseException); ElasticsearchException elasticsearchException = expectThrows(ElasticsearchException.class, () -> restHighLevelClient.performRequest(mainRequest, requestConverter, response -> response.getStatusLine().getStatusCode(), Collections.emptySet())); @@ -416,15 +385,13 @@ public void testPerformRequestOnResponseExceptionWithBrokenEntity() throws IOExc public void testPerformRequestOnResponseExceptionWithBrokenEntity2() throws IOException { MainRequest mainRequest = new MainRequest(); - CheckedFunction requestConverter = request -> - new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null); + CheckedFunction requestConverter = request -> new Request(HttpGet.METHOD_NAME, "/"); RestStatus restStatus = randomFrom(RestStatus.values()); HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus)); httpResponse.setEntity(new StringEntity("{\"status\":" + restStatus.getStatus() + "}", ContentType.APPLICATION_JSON)); Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse); ResponseException responseException = new ResponseException(mockResponse); - when(restClient.performRequest(anyString(), anyString(), anyMapOf(String.class, String.class), - anyObject(), anyVararg())).thenThrow(responseException); + when(restClient.performRequest(any(Request.class))).thenThrow(responseException); ElasticsearchException elasticsearchException = expectThrows(ElasticsearchException.class, () -> restHighLevelClient.performRequest(mainRequest, requestConverter, response -> response.getStatusLine().getStatusCode(), Collections.emptySet())); @@ -436,13 +403,11 @@ public void testPerformRequestOnResponseExceptionWithBrokenEntity2() throws IOEx public void testPerformRequestOnResponseExceptionWithIgnores() throws IOException { MainRequest mainRequest = new MainRequest(); - CheckedFunction requestConverter = request -> - new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null); + CheckedFunction requestConverter = request -> new Request(HttpGet.METHOD_NAME, "/"); HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(RestStatus.NOT_FOUND)); Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse); ResponseException responseException = new ResponseException(mockResponse); - when(restClient.performRequest(anyString(), anyString(), anyMapOf(String.class, String.class), - anyObject(), anyVararg())).thenThrow(responseException); + when(restClient.performRequest(any(Request.class))).thenThrow(responseException); //although we got an exception, we turn it into a successful response because the status code was provided among ignores assertEquals(Integer.valueOf(404), restHighLevelClient.performRequest(mainRequest, requestConverter, response -> response.getStatusLine().getStatusCode(), Collections.singleton(404))); @@ -450,13 +415,11 @@ public void testPerformRequestOnResponseExceptionWithIgnores() throws IOExceptio public void testPerformRequestOnResponseExceptionWithIgnoresErrorNoBody() throws IOException { MainRequest mainRequest = new MainRequest(); - CheckedFunction requestConverter = request -> - new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null); + CheckedFunction requestConverter = request -> new Request(HttpGet.METHOD_NAME, "/"); HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(RestStatus.NOT_FOUND)); Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse); ResponseException responseException = new ResponseException(mockResponse); - when(restClient.performRequest(anyString(), anyString(), anyMapOf(String.class, String.class), - anyObject(), anyVararg())).thenThrow(responseException); + when(restClient.performRequest(any(Request.class))).thenThrow(responseException); ElasticsearchException elasticsearchException = expectThrows(ElasticsearchException.class, () -> restHighLevelClient.performRequest(mainRequest, requestConverter, response -> {throw new IllegalStateException();}, Collections.singleton(404))); @@ -467,15 +430,13 @@ public void testPerformRequestOnResponseExceptionWithIgnoresErrorNoBody() throws public void testPerformRequestOnResponseExceptionWithIgnoresErrorValidBody() throws IOException { MainRequest mainRequest = new MainRequest(); - CheckedFunction requestConverter = request -> - new Request(HttpGet.METHOD_NAME, "/", Collections.emptyMap(), null); + CheckedFunction requestConverter = request -> new Request(HttpGet.METHOD_NAME, "/"); HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(RestStatus.NOT_FOUND)); httpResponse.setEntity(new StringEntity("{\"error\":\"test error message\",\"status\":404}", ContentType.APPLICATION_JSON)); Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse); ResponseException responseException = new ResponseException(mockResponse); - when(restClient.performRequest(anyString(), anyString(), anyMapOf(String.class, String.class), - anyObject(), anyVararg())).thenThrow(responseException); + when(restClient.performRequest(any(Request.class))).thenThrow(responseException); ElasticsearchException elasticsearchException = expectThrows(ElasticsearchException.class, () -> restHighLevelClient.performRequest(mainRequest, requestConverter, response -> {throw new IllegalStateException();}, Collections.singleton(404))); @@ -696,23 +657,6 @@ public void onFailure(Exception e) { } } - private static class HeadersVarargMatcher extends ArgumentMatcher implements VarargMatcher { - private Header[] expectedHeaders; - - HeadersVarargMatcher(Header... expectedHeaders) { - this.expectedHeaders = expectedHeaders; - } - - @Override - public boolean matches(Object varargArgument) { - if (varargArgument instanceof Header[]) { - Header[] actualHeaders = (Header[]) varargArgument; - return new ArrayEquals(expectedHeaders).matches(actualHeaders); - } - return false; - } - } - private static StatusLine newStatusLine(RestStatus restStatus) { return new BasicStatusLine(HTTP_PROTOCOL, restStatus.getStatus(), restStatus.name()); } diff --git a/client/rest/src/main/java/org/elasticsearch/client/Request.java b/client/rest/src/main/java/org/elasticsearch/client/Request.java new file mode 100644 index 0000000000000..bf0012339fb41 --- /dev/null +++ b/client/rest/src/main/java/org/elasticsearch/client/Request.java @@ -0,0 +1,202 @@ +/* + * 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.apache.http.HttpEntity; +import org.apache.http.nio.protocol.HttpAsyncResponseConsumer; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +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 parameters = new HashMap<>(); + + private HttpEntity entity; + private Header[] headers = NO_HEADERS; + private HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory = + HttpAsyncResponseConsumerFactory.DEFAULT; + + /** + * Create the {@linkplain Request}. + * @param method the HTTP method + * @param endpoint the path of the request (without scheme, host, port, or prefix) + */ + public Request(String method, String endpoint) { + this.method = Objects.requireNonNull(method, "method cannot be null"); + this.endpoint = Objects.requireNonNull(endpoint, "endpoint cannot be null"); + } + + /** + * The HTTP method. + */ + public String getMethod() { + return method; + } + + /** + * The path of the request (without scheme, host, port, or prefix). + */ + public String getEndpoint() { + return endpoint; + } + + /** + * Add a query string parameter. + * @param name the name of the url parameter. Must not be null. + * @param value the value of the url url parameter. If {@code null} then + * the parameter is sent as {@code name} rather than {@code name=value} + * @throws IllegalArgumentException if a parameter with that name has + * already been set + */ + public void addParameter(String name, String value) { + Objects.requireNonNull(name, "url parameter name cannot be null"); + // .putIfAbsent(name, value) except we are in Java 7 which doesn't have that. + if (parameters.containsKey(name)) { + throw new IllegalArgumentException("url parameter [" + name + "] has already been set to [" + parameters.get(name) + "]"); + } else { + parameters.put(name, value); + } + } + + /** + * Query string parameters. The returned map is an unmodifiable view of the + * map in the request so calls to {@link #addParameter(String, String)} + * will change it. + */ + public Map getParameters() { + return unmodifiableMap(parameters); + } + + /** + * Set the body of the request. If not set or set to {@code null} then no + * body is sent with the request. + */ + public void setEntity(HttpEntity entity) { + this.entity = entity; + } + + /** + * The body of the request. If {@code null} then no body + * is sent with the request. + */ + public HttpEntity getEntity() { + return entity; + } + + /** + * Set the headers to attach 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; + } + + /** + * Headers to attach to the request. + */ + public Header[] getHeaders() { + return headers; + } + + /** + * 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"); + } + + /** + * 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("Request{"); + b.append("method='").append(method).append('\''); + b.append(", endpoint='").append(endpoint).append('\''); + if (false == parameters.isEmpty()) { + b.append(", params=").append(parameters); + } + if (entity != null) { + b.append(", entity=").append(entity); + } + if (headers.length > 0) { + b.append(", headers="); + for (int h = 0; h < headers.length; h++) { + if (h != 0) { + b.append(','); + } + b.append(headers[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; + } + + Request other = (Request) obj; + return method.equals(other.method) + && endpoint.equals(other.endpoint) + && parameters.equals(other.parameters) + && Objects.equals(entity, other.entity) + && Arrays.equals(headers, other.headers) + && httpAsyncResponseConsumerFactory.equals(other.httpAsyncResponseConsumerFactory); + } + + @Override + public int hashCode() { + return Objects.hash(method, endpoint, parameters, entity, Arrays.hashCode(headers), httpAsyncResponseConsumerFactory); + } +} 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 48349c3858938..1d4036c210308 100644 --- a/client/rest/src/main/java/org/elasticsearch/client/RestClient.java +++ b/client/rest/src/main/java/org/elasticsearch/client/RestClient.java @@ -143,6 +143,61 @@ public synchronized void setHosts(HttpHost... hosts) { this.blacklist.clear(); } + /** + * Sends a request to the Elasticsearch cluster that the client points to. + * Blocks until the request is completed and returns its response or fails + * by throwing an exception. Selects a host out of the provided ones in a + * round-robin fashion. Failing hosts are marked dead and retried after a + * certain amount of time (minimum 1 minute, maximum 30 minutes), depending + * on how many times they previously failed (the more failures, the later + * they will be retried). In case of failures all of the alive nodes (or + * dead nodes that deserve a retry) are retried until one responds or none + * of them does, in which case an {@link IOException} will be thrown. + * + * This method works by performing an asynchronous call and waiting + * for the result. If the asynchronous call throws an exception we wrap + * it and rethrow it so that the stack trace attached to the exception + * contains the call site. While we attempt to preserve the original + * exception this isn't always possible and likely haven't covered all of + * the cases. You can get the original exception from + * {@link Exception#getCause()}. + * + * @param request the request to perform + * @return the response returned by Elasticsearch + * @throws IOException in case of a problem or the connection was aborted + * @throws ClientProtocolException in case of an http protocol error + * @throws ResponseException in case Elasticsearch responded with a status code that indicated an error + */ + public Response performRequest(Request request) throws IOException { + SyncResponseListener listener = new SyncResponseListener(maxRetryTimeoutMillis); + performRequestAsyncNoCatch(request, listener); + return listener.get(); + } + + /** + * Sends a request to the Elasticsearch cluster that the client points to. + * The request is executed asynchronously and the provided + * {@link ResponseListener} gets notified upon request completion or + * failure. Selects a host out of the provided ones in a round-robin + * fashion. Failing hosts are marked dead and retried after a certain + * amount of time (minimum 1 minute, maximum 30 minutes), depending on how + * many times they previously failed (the more failures, the later they + * will be retried). In case of failures all of the alive nodes (or dead + * nodes that deserve a retry) are retried until one responds or none of + * them does, in which case an {@link IOException} will be thrown. + * + * @param request the request to perform + * @param responseListener the {@link ResponseListener} to notify when the + * request is completed or fails + */ + public void performRequestAsync(Request request, ResponseListener responseListener) { + try { + performRequestAsyncNoCatch(request, responseListener); + } catch (Exception e) { + responseListener.onFailure(e); + } + } + /** * Sends a request to the Elasticsearch cluster that the client points to and waits for the corresponding response * to be returned. Shortcut to {@link #performRequest(String, String, Map, HttpEntity, Header...)} but without parameters @@ -157,7 +212,9 @@ public synchronized void setHosts(HttpHost... hosts) { * @throws ResponseException in case Elasticsearch responded with a status code that indicated an error */ public Response performRequest(String method, String endpoint, Header... headers) throws IOException { - return performRequest(method, endpoint, Collections.emptyMap(), null, headers); + Request request = new Request(method, endpoint); + request.setHeaders(headers); + return performRequest(request); } /** @@ -174,7 +231,10 @@ public Response performRequest(String method, String endpoint, Header... headers * @throws ResponseException in case Elasticsearch responded with a status code that indicated an error */ public Response performRequest(String method, String endpoint, Map params, Header... headers) throws IOException { - return performRequest(method, endpoint, params, (HttpEntity)null, headers); + Request request = new Request(method, endpoint); + addParameters(request, params); + request.setHeaders(headers); + return performRequest(request); } /** @@ -195,7 +255,11 @@ public Response performRequest(String method, String endpoint, Map params, HttpEntity entity, Header... headers) throws IOException { - return performRequest(method, endpoint, params, entity, HttpAsyncResponseConsumerFactory.DEFAULT, headers); + Request request = new Request(method, endpoint); + addParameters(request, params); + request.setEntity(entity); + request.setHeaders(headers); + return performRequest(request); } /** @@ -229,10 +293,12 @@ public Response performRequest(String method, String endpoint, Map params, HttpEntity entity, HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory, Header... headers) throws IOException { - SyncResponseListener listener = new SyncResponseListener(maxRetryTimeoutMillis); - performRequestAsyncNoCatch(method, endpoint, params, entity, httpAsyncResponseConsumerFactory, - listener, headers); - return listener.get(); + Request request = new Request(method, endpoint); + addParameters(request, params); + request.setEntity(entity); + request.setHttpAsyncResponseConsumerFactory(httpAsyncResponseConsumerFactory); + request.setHeaders(headers); + return performRequest(request); } /** @@ -246,7 +312,15 @@ public Response performRequest(String method, String endpoint, MapemptyMap(), null, responseListener, headers); + Request request; + try { + request = new Request(method, endpoint); + request.setHeaders(headers); + } catch (Exception e) { + responseListener.onFailure(e); + return; + } + performRequestAsync(request, responseListener); } /** @@ -262,7 +336,16 @@ public void performRequestAsync(String method, String endpoint, ResponseListener */ public void performRequestAsync(String method, String endpoint, Map params, ResponseListener responseListener, Header... headers) { - performRequestAsync(method, endpoint, params, null, responseListener, headers); + Request request; + try { + request = new Request(method, endpoint); + addParameters(request, params); + request.setHeaders(headers); + } catch (Exception e) { + responseListener.onFailure(e); + return; + } + performRequestAsync(request, responseListener); } /** @@ -281,7 +364,17 @@ public void performRequestAsync(String method, String endpoint, Map params, HttpEntity entity, ResponseListener responseListener, Header... headers) { - performRequestAsync(method, endpoint, params, entity, HttpAsyncResponseConsumerFactory.DEFAULT, responseListener, headers); + Request request; + try { + request = new Request(method, endpoint); + addParameters(request, params); + request.setEntity(entity); + request.setHeaders(headers); + } catch (Exception e) { + responseListener.onFailure(e); + return; + } + performRequestAsync(request, responseListener); } /** @@ -305,24 +398,27 @@ public void performRequestAsync(String method, String endpoint, Map params, HttpEntity entity, HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory, ResponseListener responseListener, Header... headers) { + Request request; try { - performRequestAsyncNoCatch(method, endpoint, params, entity, httpAsyncResponseConsumerFactory, - responseListener, headers); + request = new Request(method, endpoint); + addParameters(request, params); + request.setEntity(entity); + request.setHttpAsyncResponseConsumerFactory(httpAsyncResponseConsumerFactory); + request.setHeaders(headers); } catch (Exception e) { responseListener.onFailure(e); + return; } + performRequestAsync(request, responseListener); } - void performRequestAsyncNoCatch(String method, String endpoint, Map params, - HttpEntity entity, HttpAsyncResponseConsumerFactory httpAsyncResponseConsumerFactory, - ResponseListener responseListener, Header... headers) { - Objects.requireNonNull(params, "params must not be null"); - Map requestParams = new HashMap<>(params); + void performRequestAsyncNoCatch(Request request, ResponseListener listener) { + Map requestParams = new HashMap<>(request.getParameters()); //ignore is a special parameter supported by the clients, shouldn't be sent to es String ignoreString = requestParams.remove("ignore"); Set ignoreErrorCodes; if (ignoreString == null) { - if (HttpHead.METHOD_NAME.equals(method)) { + if (HttpHead.METHOD_NAME.equals(request.getMethod())) { //404 never causes error if returned for a HEAD request ignoreErrorCodes = Collections.singleton(404); } else { @@ -331,7 +427,7 @@ void performRequestAsyncNoCatch(String method, String endpoint, Map(); - if (HttpHead.METHOD_NAME.equals(method)) { + if (HttpHead.METHOD_NAME.equals(request.getMethod())) { //404 never causes error if returned for a HEAD request ignoreErrorCodes.add(404); } @@ -343,13 +439,13 @@ void performRequestAsyncNoCatch(String method, String endpoint, Map> hostTuple, final HttpRequestBase request, @@ -428,11 +524,9 @@ public void cancelled() { } private void setHeaders(HttpRequest httpRequest, Header[] requestHeaders) { - Objects.requireNonNull(requestHeaders, "request headers must not be null"); // request headers override default headers, so we don't add default headers if they exist as request headers final Set requestNames = new HashSet<>(requestHeaders.length); for (Header requestHeader : requestHeaders) { - Objects.requireNonNull(requestHeader, "request header must not be null"); httpRequest.addHeader(requestHeader); requestNames.add(requestHeader.getName()); } @@ -766,4 +860,15 @@ private static class HostTuple { this.authCache = authCache; } } + + /** + * Add all parameters from a map to a {@link Request}. This only exists + * to support methods that exist for backwards compatibility. + */ + private static void addParameters(Request request, Map parameters) { + Objects.requireNonNull(parameters, "parameters cannot be null"); + for (Map.Entry entry : parameters.entrySet()) { + request.addParameter(entry.getKey(), entry.getValue()); + } + } } diff --git a/client/rest/src/test/java/org/elasticsearch/client/RequestTests.java b/client/rest/src/test/java/org/elasticsearch/client/RequestTests.java new file mode 100644 index 0000000000000..98fcf8421ae6a --- /dev/null +++ b/client/rest/src/test/java/org/elasticsearch/client/RequestTests.java @@ -0,0 +1,137 @@ +/* + * 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 java.util.HashMap; +import java.util.Map; + +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 static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class RequestTests extends RestClientTestCase { + public void testConstructor() { + final String method = randomFrom(new String[] {"GET", "PUT", "POST", "HEAD", "DELETE"}); + final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); + + try { + new Request(null, endpoint); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("method cannot be null", e.getMessage()); + } + + try { + new Request(method, null); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("endpoint cannot be null", e.getMessage()); + } + + final Request request = new Request(method, endpoint); + assertEquals(method, request.getMethod()); + assertEquals(endpoint, request.getEndpoint()); + } + + public void testAddParameters() { + final String method = randomFrom(new String[] {"GET", "PUT", "POST", "HEAD", "DELETE"}); + final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); + int parametersCount = between(1, 3); + final Map parameters = new HashMap<>(parametersCount); + while (parameters.size() < parametersCount) { + parameters.put(randomAsciiLettersOfLength(5), randomAsciiLettersOfLength(5)); + } + Request request = new Request(method, endpoint); + + try { + request.addParameter(null, "value"); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("url parameter name cannot be null", e.getMessage()); + } + + for (Map.Entry entry : parameters.entrySet()) { + request.addParameter(entry.getKey(), entry.getValue()); + } + assertEquals(parameters, request.getParameters()); + + // Test that adding parameters with a null value is ok. + request.addParameter("is_null", null); + parameters.put("is_null", null); + assertEquals(parameters, request.getParameters()); + + // Test that adding a duplicate parameter fails + String firstValue = randomBoolean() ? null : "value"; + request.addParameter("name", firstValue); + try { + request.addParameter("name", randomBoolean() ? firstValue : "second_value"); + fail("expected failure"); + } catch (IllegalArgumentException e) { + assertEquals("url parameter [name] has already been set to [" + firstValue + "]", e.getMessage()); + } + } + + public void testSetEntity() { + final String method = randomFrom(new String[] {"GET", "PUT", "POST", "HEAD", "DELETE"}); + final String endpoint = randomAsciiLettersOfLengthBetween(1, 10); + final HttpEntity entity = + randomBoolean() ? new StringEntity(randomAsciiLettersOfLengthBetween(1, 100), ContentType.TEXT_PLAIN) : null; + Request request = new Request(method, endpoint); + + request.setEntity(entity); + assertEquals(entity, request.getEntity()); + } + + public void testSetHeaders() { + 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); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("headers cannot be null", e.getMessage()); + } + + try { + request.setHeaders(new Header [] {null}); + fail("expected failure"); + } catch (NullPointerException e) { + assertEquals("header 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)); + } + request.setHeaders(headers); + assertArrayEquals(headers, request.getHeaders()); + } + + // TODO equals and hashcode + +} diff --git a/client/rest/src/test/java/org/elasticsearch/client/RestClientMultipleHostsIntegTests.java b/client/rest/src/test/java/org/elasticsearch/client/RestClientMultipleHostsIntegTests.java index 16c192b3977a8..aa323276404cf 100644 --- a/client/rest/src/test/java/org/elasticsearch/client/RestClientMultipleHostsIntegTests.java +++ b/client/rest/src/test/java/org/elasticsearch/client/RestClientMultipleHostsIntegTests.java @@ -138,7 +138,7 @@ public void testSyncRequests() throws IOException { final int statusCode = randomBoolean() ? randomOkStatusCode(getRandom()) : randomErrorNoRetryStatusCode(getRandom()); Response response; try { - response = restClient.performRequest(method, "/" + statusCode); + response = restClient.performRequest(new Request(method, "/" + statusCode)); } catch(ResponseException responseException) { response = responseException.getResponse(); } @@ -156,7 +156,7 @@ public void testAsyncRequests() throws Exception { final String method = RestClientTestUtil.randomHttpMethod(getRandom()); //we don't test status codes that are subject to retries as they interfere with hosts being stopped final int statusCode = randomBoolean() ? randomOkStatusCode(getRandom()) : randomErrorNoRetryStatusCode(getRandom()); - restClient.performRequestAsync(method, "/" + statusCode, new ResponseListener() { + restClient.performRequestAsync(new Request(method, "/" + statusCode), new ResponseListener() { @Override public void onSuccess(Response response) { responses.add(new TestResponse(method, statusCode, response)); 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 7786eefb97f01..2d419b213d686 100644 --- a/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostTests.java +++ b/client/rest/src/test/java/org/elasticsearch/client/RestClientSingleHostTests.java @@ -62,6 +62,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.TreeMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -280,13 +281,17 @@ public void testBody() throws IOException { StringEntity entity = new StringEntity(body, ContentType.APPLICATION_JSON); for (String method : Arrays.asList("DELETE", "GET", "PATCH", "POST", "PUT")) { for (int okStatusCode : getOkStatusCodes()) { - Response response = restClient.performRequest(method, "/" + okStatusCode, Collections.emptyMap(), entity); + Request request = new Request(method, "/" + okStatusCode); + request.setEntity(entity); + Response response = restClient.performRequest(request); assertThat(response.getStatusLine().getStatusCode(), equalTo(okStatusCode)); assertThat(EntityUtils.toString(response.getEntity()), equalTo(body)); } for (int errorStatusCode : getAllErrorStatusCodes()) { + Request request = new Request(method, "/" + errorStatusCode); + request.setEntity(entity); try { - restClient.performRequest(method, "/" + errorStatusCode, Collections.emptyMap(), entity); + restClient.performRequest(request); fail("request should have failed"); } catch(ResponseException e) { Response response = e.getResponse(); @@ -297,8 +302,10 @@ public void testBody() throws IOException { } } for (String method : Arrays.asList("HEAD", "OPTIONS", "TRACE")) { + Request request = new Request(method, "/" + randomStatusCode(getRandom())); + request.setEntity(entity); try { - restClient.performRequest(method, "/" + randomStatusCode(getRandom()), Collections.emptyMap(), entity); + restClient.performRequest(request); fail("request should have failed"); } catch(UnsupportedOperationException e) { assertThat(e.getMessage(), equalTo(method + " with body is not supported")); @@ -306,7 +313,11 @@ public void testBody() throws IOException { } } - public void testNullHeaders() throws IOException { + /** + * @deprecated will remove method in 7.0 but needs tests until then. Replaced by {@link RequestTests#testSetHeaders()}. + */ + @Deprecated + public void tesPerformRequestOldStyleNullHeaders() throws IOException { String method = randomHttpMethod(getRandom()); int statusCode = randomStatusCode(getRandom()); try { @@ -323,20 +334,24 @@ public void testNullHeaders() throws IOException { } } - public void testNullParams() throws IOException { + /** + * @deprecated will remove method in 7.0 but needs tests until then. Replaced by {@link RequestTests#testSetParameters()}. + */ + @Deprecated + public void testPerformRequestOldStyleWithNullParams() throws IOException { String method = randomHttpMethod(getRandom()); int statusCode = randomStatusCode(getRandom()); try { restClient.performRequest(method, "/" + statusCode, (Map)null); fail("request should have failed"); } catch(NullPointerException e) { - assertEquals("params must not be null", e.getMessage()); + assertEquals("parameters cannot be null", e.getMessage()); } try { restClient.performRequest(method, "/" + statusCode, null, (HttpEntity)null); fail("request should have failed"); } catch(NullPointerException e) { - assertEquals("params must not be null", e.getMessage()); + assertEquals("parameters cannot be null", e.getMessage()); } } @@ -348,9 +363,11 @@ public void testHeaders() throws IOException { for (String method : getHttpMethods()) { final Header[] requestHeaders = RestClientTestUtil.randomHeaders(getRandom(), "Header"); final int statusCode = randomStatusCode(getRandom()); + Request request = new Request(method, "/" + statusCode); + request.setHeaders(requestHeaders); Response esResponse; try { - esResponse = restClient.performRequest(method, "/" + statusCode, requestHeaders); + esResponse = restClient.performRequest(request); } catch(ResponseException e) { esResponse = e.getResponse(); } @@ -361,16 +378,15 @@ public void testHeaders() throws IOException { private HttpUriRequest performRandomRequest(String method) throws Exception { String uriAsString = "/" + randomStatusCode(getRandom()); + Request request = new Request(method, uriAsString); URIBuilder uriBuilder = new URIBuilder(uriAsString); - final Map params = new HashMap<>(); - boolean hasParams = randomBoolean(); - if (hasParams) { + if (randomBoolean()) { int numParams = randomIntBetween(1, 3); for (int i = 0; i < numParams; i++) { - String paramKey = "param-" + i; - String paramValue = randomAsciiOfLengthBetween(3, 10); - params.put(paramKey, paramValue); - uriBuilder.addParameter(paramKey, paramValue); + String name = "param-" + i; + String value = randomAsciiAlphanumOfLengthBetween(3, 10); + request.addParameter(name, value); + uriBuilder.addParameter(name, value); } } if (randomBoolean()) { @@ -379,81 +395,82 @@ private HttpUriRequest performRandomRequest(String method) throws Exception { if (randomBoolean()) { ignore += "," + Integer.toString(randomFrom(RestClientTestUtil.getAllErrorStatusCodes())); } - params.put("ignore", ignore); + request.addParameter("ignore", ignore); } URI uri = uriBuilder.build(); - HttpUriRequest request; + HttpUriRequest expectedRequest; switch(method) { case "DELETE": - request = new HttpDeleteWithEntity(uri); + expectedRequest = new HttpDeleteWithEntity(uri); break; case "GET": - request = new HttpGetWithEntity(uri); + expectedRequest = new HttpGetWithEntity(uri); break; case "HEAD": - request = new HttpHead(uri); + expectedRequest = new HttpHead(uri); break; case "OPTIONS": - request = new HttpOptions(uri); + expectedRequest = new HttpOptions(uri); break; case "PATCH": - request = new HttpPatch(uri); + expectedRequest = new HttpPatch(uri); break; case "POST": - request = new HttpPost(uri); + expectedRequest = new HttpPost(uri); break; case "PUT": - request = new HttpPut(uri); + expectedRequest = new HttpPut(uri); break; case "TRACE": - request = new HttpTrace(uri); + expectedRequest = new HttpTrace(uri); break; default: throw new UnsupportedOperationException("method not supported: " + method); } - HttpEntity entity = null; - boolean hasBody = request instanceof HttpEntityEnclosingRequest && getRandom().nextBoolean(); - if (hasBody) { - entity = new StringEntity(randomAsciiOfLengthBetween(10, 100), ContentType.APPLICATION_JSON); - ((HttpEntityEnclosingRequest) request).setEntity(entity); + if (expectedRequest instanceof HttpEntityEnclosingRequest && getRandom().nextBoolean()) { + HttpEntity entity = new StringEntity(randomAsciiAlphanumOfLengthBetween(10, 100), ContentType.APPLICATION_JSON); + ((HttpEntityEnclosingRequest) expectedRequest).setEntity(entity); + request.setEntity(entity); } - Header[] headers = new Header[0]; final Set uniqueNames = new HashSet<>(); if (randomBoolean()) { - headers = RestClientTestUtil.randomHeaders(getRandom(), "Header"); + Header[] headers = RestClientTestUtil.randomHeaders(getRandom(), "Header"); + request.setHeaders(headers); for (Header header : headers) { - request.addHeader(header); + expectedRequest.addHeader(header); uniqueNames.add(header.getName()); } } for (Header defaultHeader : defaultHeaders) { // request level headers override default headers if (uniqueNames.contains(defaultHeader.getName()) == false) { - request.addHeader(defaultHeader); + expectedRequest.addHeader(defaultHeader); } } try { - if (hasParams == false && hasBody == false && randomBoolean()) { - restClient.performRequest(method, uriAsString, headers); - } else if (hasBody == false && randomBoolean()) { - restClient.performRequest(method, uriAsString, params, headers); - } else { - restClient.performRequest(method, uriAsString, params, entity, headers); - } + restClient.performRequest(request); } catch(ResponseException e) { //all good } - return request; + return expectedRequest; } + /** + * @deprecated prefer {@link RestClient#performRequest(Request)}. + */ + @Deprecated private Response performRequest(String method, String endpoint, Header... headers) throws IOException { return performRequest(method, endpoint, Collections.emptyMap(), headers); } + /** + * @deprecated prefer {@link RestClient#performRequest(Request)}. + */ + @Deprecated private Response performRequest(String method, String endpoint, Map params, Header... headers) throws IOException { int methodSelector; if (params.isEmpty()) { diff --git a/client/rest/src/test/java/org/elasticsearch/client/RestClientTests.java b/client/rest/src/test/java/org/elasticsearch/client/RestClientTests.java index ee6dbf449bd56..872b327954b02 100644 --- a/client/rest/src/test/java/org/elasticsearch/client/RestClientTests.java +++ b/client/rest/src/test/java/org/elasticsearch/client/RestClientTests.java @@ -52,6 +52,30 @@ public void testCloseIsIdempotent() throws IOException { } public void testPerformAsyncWithUnsupportedMethod() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + try (RestClient restClient = createRestClient()) { + restClient.performRequestAsync(new Request("unsupported", randomAsciiLettersOfLength(5)), new ResponseListener() { + @Override + public void onSuccess(Response response) { + fail("should have failed because of unsupported method"); + } + + @Override + public void onFailure(Exception exception) { + assertThat(exception, instanceOf(UnsupportedOperationException.class)); + assertEquals("http method not supported: unsupported", exception.getMessage()); + latch.countDown(); + } + }); + latch.await(); + } + } + + /** + * @deprecated will remove method in 7.0 but needs tests until then. Replaced by {@link #testPerformAsyncWithUnsupportedMethod()}. + */ + @Deprecated + public void testPerformAsyncOldStyleWithUnsupportedMethod() throws Exception { final CountDownLatch latch = new CountDownLatch(1); try (RestClient restClient = createRestClient()) { restClient.performRequestAsync("unsupported", randomAsciiLettersOfLength(5), new ResponseListener() { @@ -71,7 +95,11 @@ public void onFailure(Exception exception) { } } - public void testPerformAsyncWithNullParams() throws Exception { + /** + * @deprecated will remove method in 7.0 but needs tests until then. Replaced by {@link RequestTests#testSetParameters()}. + */ + @Deprecated + public void testPerformOldStyleAsyncWithNullParams() throws Exception { final CountDownLatch latch = new CountDownLatch(1); try (RestClient restClient = createRestClient()) { restClient.performRequestAsync(randomAsciiLettersOfLength(5), randomAsciiLettersOfLength(5), null, new ResponseListener() { @@ -83,7 +111,7 @@ public void onSuccess(Response response) { @Override public void onFailure(Exception exception) { assertThat(exception, instanceOf(NullPointerException.class)); - assertEquals("params must not be null", exception.getMessage()); + assertEquals("parameters cannot be null", exception.getMessage()); latch.countDown(); } }); @@ -91,7 +119,11 @@ public void onFailure(Exception exception) { } } - public void testPerformAsyncWithNullHeaders() throws Exception { + /** + * @deprecated will remove method in 7.0 but needs tests until then. Replaced by {@link RequestTests#testSetHeaders()}. + */ + @Deprecated + public void testPerformOldStyleAsyncWithNullHeaders() throws Exception { final CountDownLatch latch = new CountDownLatch(1); try (RestClient restClient = createRestClient()) { ResponseListener listener = new ResponseListener() { @@ -103,7 +135,7 @@ public void onSuccess(Response response) { @Override public void onFailure(Exception exception) { assertThat(exception, instanceOf(NullPointerException.class)); - assertEquals("request header must not be null", exception.getMessage()); + assertEquals("header cannot be null", exception.getMessage()); latch.countDown(); } }; @@ -113,6 +145,30 @@ public void onFailure(Exception exception) { } public void testPerformAsyncWithWrongEndpoint() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + try (RestClient restClient = createRestClient()) { + restClient.performRequestAsync(new Request("GET", "::http:///"), new ResponseListener() { + @Override + public void onSuccess(Response response) { + fail("should have failed because of wrong endpoint"); + } + + @Override + public void onFailure(Exception exception) { + assertThat(exception, instanceOf(IllegalArgumentException.class)); + assertEquals("Expected scheme name at index 0: ::http:///", exception.getMessage()); + latch.countDown(); + } + }); + latch.await(); + } + } + + /** + * @deprecated will remove method in 7.0 but needs tests until then. Replaced by {@link #testPerformAsyncWithWrongEndpoint()}. + */ + @Deprecated + public void testPerformAsyncOldStyleWithWrongEndpoint() throws Exception { final CountDownLatch latch = new CountDownLatch(1); try (RestClient restClient = createRestClient()) { restClient.performRequestAsync("GET", "::http:///", new ResponseListener() { @@ -175,6 +231,10 @@ public void testSetHostsWrongArguments() throws IOException { } } + /** + * @deprecated will remove method in 7.0 but needs tests until then. Replaced by {@link RequestTests#testConstructor()}. + */ + @Deprecated public void testNullPath() throws IOException { try (RestClient restClient = createRestClient()) { for (String method : getHttpMethods()) { @@ -182,7 +242,7 @@ public void testNullPath() throws IOException { restClient.performRequest(method, null); fail("path set to null should fail!"); } catch (NullPointerException e) { - assertEquals("path must not be null", e.getMessage()); + assertEquals("endpoint cannot be null", e.getMessage()); } } } 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 1bad6b5f6d6fd..aa89a7d76ab26 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 @@ -27,7 +27,9 @@ 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; @@ -37,6 +39,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.Response; import org.elasticsearch.client.ResponseListener; import org.elasticsearch.client.RestClient; @@ -134,107 +137,61 @@ public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpCli } { - //tag::rest-client-verb-endpoint - Response response = restClient.performRequest("GET", "/"); // <1> - //end::rest-client-verb-endpoint + //tag::rest-client-sync + Request request = new Request( + "GET", // <1> + "/"); // <2> + Response response = restClient.performRequest(request); + //end::rest-client-sync } { - //tag::rest-client-headers - Response response = restClient.performRequest("GET", "/", new BasicHeader("header", "value")); - //end::rest-client-headers - } - { - //tag::rest-client-verb-endpoint-params - Map params = Collections.singletonMap("pretty", "true"); - Response response = restClient.performRequest("GET", "/", params); // <1> - //end::rest-client-verb-endpoint-params - } - { - //tag::rest-client-verb-endpoint-params-body - Map params = Collections.emptyMap(); - String jsonString = "{" + - "\"user\":\"kimchy\"," + - "\"postDate\":\"2013-01-30\"," + - "\"message\":\"trying out Elasticsearch\"" + - "}"; - HttpEntity entity = new NStringEntity(jsonString, ContentType.APPLICATION_JSON); - Response response = restClient.performRequest("PUT", "/posts/doc/1", params, entity); // <1> - //end::rest-client-verb-endpoint-params-body - } - { - //tag::rest-client-response-consumer - Map params = Collections.emptyMap(); - HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory consumerFactory = - new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024); - Response response = restClient.performRequest("GET", "/posts/_search", params, null, consumerFactory); // <1> - //end::rest-client-response-consumer - } - { - //tag::rest-client-verb-endpoint-async - ResponseListener responseListener = new ResponseListener() { + //tag::rest-client-async + Request request = new Request( + "GET", // <1> + "/"); // <2> + restClient.performRequestAsync(request, new ResponseListener() { @Override public void onSuccess(Response response) { - // <1> + // <3> } @Override public void onFailure(Exception exception) { - // <2> + // <4> } - }; - restClient.performRequestAsync("GET", "/", responseListener); // <3> - //end::rest-client-verb-endpoint-async - - //tag::rest-client-headers-async - Header[] headers = { - new BasicHeader("header1", "value1"), - new BasicHeader("header2", "value2") - }; - restClient.performRequestAsync("GET", "/", responseListener, headers); - //end::rest-client-headers-async - - //tag::rest-client-verb-endpoint-params-async - Map params = Collections.singletonMap("pretty", "true"); - restClient.performRequestAsync("GET", "/", params, responseListener); // <1> - //end::rest-client-verb-endpoint-params-async - - //tag::rest-client-verb-endpoint-params-body-async - String jsonString = "{" + - "\"user\":\"kimchy\"," + - "\"postDate\":\"2013-01-30\"," + - "\"message\":\"trying out Elasticsearch\"" + - "}"; - HttpEntity entity = new NStringEntity(jsonString, ContentType.APPLICATION_JSON); - restClient.performRequestAsync("PUT", "/posts/doc/1", params, entity, responseListener); // <1> - //end::rest-client-verb-endpoint-params-body-async - - //tag::rest-client-response-consumer-async - HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory consumerFactory = - new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024); - restClient.performRequestAsync("GET", "/posts/_search", params, null, consumerFactory, responseListener); // <1> - //end::rest-client-response-consumer-async + }); + //end::rest-client-async } { - //tag::rest-client-response2 - Response response = restClient.performRequest("GET", "/"); - RequestLine requestLine = response.getRequestLine(); // <1> - HttpHost host = response.getHost(); // <2> - int statusCode = response.getStatusLine().getStatusCode(); // <3> - Header[] headers = response.getHeaders(); // <4> - String responseBody = EntityUtils.toString(response.getEntity()); // <5> - //end::rest-client-response2 + Request request = new Request("GET", "/"); + //tag::rest-client-parameters + request.addParameter("pretty", "true"); + //end::rest-client-parameters + //tag::rest-client-body + request.setEntity(new StringEntity( + "{\"json\":\"text\"}", + ContentType.APPLICATION_JSON)); + //end::rest-client-body + //tag::rest-client-headers + request.setHeaders( + new BasicHeader("Accept", "text/plain"), + new BasicHeader("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 } { HttpEntity[] documents = new HttpEntity[10]; //tag::rest-client-async-example final CountDownLatch latch = new CountDownLatch(documents.length); for (int i = 0; i < documents.length; i++) { + Request request = new Request("PUT", "/posts/doc/" + i); + //let's assume that the documents are stored in an HttpEntity array + request.setEntity(documents[i]); restClient.performRequestAsync( - "PUT", - "/posts/doc/" + i, - Collections.emptyMap(), - //let's assume that the documents are stored in an HttpEntity array - documents[i], + request, new ResponseListener() { @Override public void onSuccess(Response response) { @@ -253,7 +210,16 @@ public void onFailure(Exception exception) { latch.await(); //end::rest-client-async-example } - + { + //tag::rest-client-response2 + Response response = restClient.performRequest("GET", "/"); + RequestLine requestLine = response.getRequestLine(); // <1> + HttpHost host = response.getHost(); // <2> + int statusCode = response.getStatusLine().getStatusCode(); // <3> + Header[] headers = response.getHeaders(); // <4> + String responseBody = EntityUtils.toString(response.getEntity()); // <5> + //end::rest-client-response2 + } } @SuppressWarnings("unused") diff --git a/docs/CHANGELOG.asciidoc b/docs/CHANGELOG.asciidoc index c774b0232541a..c35f94949161a 100644 --- a/docs/CHANGELOG.asciidoc +++ b/docs/CHANGELOG.asciidoc @@ -65,11 +65,18 @@ written to by an older Elasticsearch after writing to it with a newer Elasticsea <> ({pull}30255[#30255]) +Added new "Request" object flavored request methods. Prefer these instead of the +multi-argument versions. ({pull}29623[#29623]) + + [float] === Bug Fixes Do not ignore request analysis/similarity settings on index resize operations when the source index already contains such settings ({pull}30216[#30216]) +=== Regressions + +=== Known Issues //[float] //=== Regressions diff --git a/docs/java-rest/low-level/usage.asciidoc b/docs/java-rest/low-level/usage.asciidoc index db27b886b4178..5ffc4332a7681 100644 --- a/docs/java-rest/low-level/usage.asciidoc +++ b/docs/java-rest/low-level/usage.asciidoc @@ -218,93 +218,74 @@ http://hc.apache.org/httpcomponents-asyncclient-dev/httpasyncclient/apidocs/org/ [[java-rest-low-usage-requests]] === Performing requests -Once the `RestClient` has been created, requests can be sent by calling one of -the available `performRequest` or `performRequestAsync` method variants. -The `performRequest` methods are synchronous and return the `Response` directly, -meaning that the client will block and wait for a response to be returned. -The `performRequestAsync` variants return `void` and accept an extra -`ResponseListener` as an argument instead, meaning that they are executed -asynchronously. The provided listener will be notified upon request completion -or failure. +Once the `RestClient` has been created, requests can be sent by calling either +`performRequest` or `performRequestAsync`. `performRequest` is synchronous and +will block the calling thread and return the `Response` when the request is +successful or throw an exception if it fails. `performRequestAsync` is +asynchronous and accepts a `ResponseListener` argument that it calls with a +`Response` when the request is successful or with an `Exception` if it4 fails. -["source","java",subs="attributes,callouts,macros"] --------------------------------------------------- -include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-verb-endpoint] --------------------------------------------------- -<1> Send a request by providing only the verb and the endpoint, minimum set -of required arguments +This is synchronous: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-verb-endpoint-params] +include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-sync] -------------------------------------------------- -<1> Send a request by providing the verb, the endpoint, and some querystring -parameter +<1> The HTTP method (`GET`, `POST`, `HEAD`, etc) +<2> The endpoint on the server + +And this is asynchronous: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-verb-endpoint-params-body] +include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-async] -------------------------------------------------- -<1> Send a request by providing the verb, the endpoint, optional querystring -parameters and the request body enclosed in an `org.apache.http.HttpEntity` -object +<1> The HTTP method (`GET`, `POST`, `HEAD`, etc) +<2> The endpoint on the server +<3> Handle the response +<4> Handle the failure -IMPORTANT: The `ContentType` specified for the `HttpEntity` is important -because it will be used to set the `Content-Type` header so that Elasticsearch -can properly parse the content. +You can add request parameters to the request object: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-response-consumer] +include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-parameters] -------------------------------------------------- -<1> Send a request by providing the verb, the endpoint, optional querystring -parameters, optional request body and the optional factory that is used to -create an http://hc.apache.org/httpcomponents-core-ga/httpcore-nio/apidocs/org/apache/http/nio/protocol/HttpAsyncResponseConsumer.html[`org.apache.http.nio.protocol.HttpAsyncResponseConsumer`] -callback instance per request attempt. Controls how the response body gets -streamed from a non-blocking HTTP connection on the client side. When not -provided, the default implementation is used which buffers the whole response -body in heap memory, up to 100 MB. -["source","java",subs="attributes,callouts,macros"] --------------------------------------------------- -include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-verb-endpoint-async] --------------------------------------------------- -<1> Define what needs to happen when the request is successfully performed -<2> Define what needs to happen when the request fails, meaning whenever -there's a connection error or a response with error status code is returned. -<3> Send an async request by providing only the verb, the endpoint, and the -response listener to be notified once the request is completed, minimum set -of required arguments +You can set the body of the request to any `HttpEntity`: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-verb-endpoint-params-async] +include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-body] -------------------------------------------------- -<1> Send an async request by providing the verb, the endpoint, some querystring -parameter and the response listener to be notified once the request is completed + +IMPORTANT: The `ContentType` specified for the `HttpEntity` is important +because it will be used to set the `Content-Type` header so that Elasticsearch +can properly parse the content. + +And you can set a list of headers to send with the request: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-verb-endpoint-params-body-async] +include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-headers] -------------------------------------------------- -<1> Send an async request by providing the verb, the endpoint, optional -querystring parameters, the request body enclosed in an -`org.apache.http.HttpEntity` object and the response listener to be -notified once the request is completed + +You can also customize the response consumer used to buffer the asynchronous +responses. The default consumer will buffer up to 100MB of response on the +JVM heap. If the response is larger then the request will fail. You could, +for example, lower the maximum size which might be useful if you are running +in a heap constrained environment: ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- -include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-response-consumer-async] +include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-response-consumer] -------------------------------------------------- -<1> Send an async request by providing the verb, the endpoint, optional -querystring parameters, optional request body and the optional factory that is -used to create an http://hc.apache.org/httpcomponents-core-ga/httpcore-nio/apidocs/org/apache/http/nio/protocol/HttpAsyncResponseConsumer.html[`org.apache.http.nio.protocol.HttpAsyncResponseConsumer`] -callback instance per request attempt. Controls how the response body gets -streamed from a non-blocking HTTP connection on the client side. When not -provided, the default implementation is used which buffers the whole response -body in heap memory, up to 100 MB. -The following is a basic example of how async requests can be sent: +==== Multiple parallel asynchronous actions + +The client is quite happy to execute many actions in parallel. The following +example indexes many documents in parallel. In a real world scenario you'd +probably want to use the `_bulk` API instead, but the example is illustative. ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- @@ -314,19 +295,6 @@ include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-async-examp <2> Handle the returned exception, due to communication error or a response with status code that indicates an error -Each of the above listed method supports sending headers along with the -request through a `Header` varargs argument as in the following examples: - -["source","java",subs="attributes,callouts,macros"] --------------------------------------------------- -include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-headers] --------------------------------------------------- - -["source","java",subs="attributes,callouts,macros"] --------------------------------------------------- -include-tagged::{doc-tests}/RestClientDocumentation.java[rest-client-headers-async] --------------------------------------------------- - [[java-rest-low-usage-responses]] === Reading responses @@ -396,4 +364,3 @@ still yields the same response as it did. Enable trace logging for the `tracer` package to have such log lines printed out. Do note that this type of logging is expensive and should not be enabled at all times in production environments, but rather temporarily used only when needed. - diff --git a/modules/reindex/src/main/java/org/elasticsearch/index/reindex/remote/RemoteRequestBuilders.java b/modules/reindex/src/main/java/org/elasticsearch/index/reindex/remote/RemoteRequestBuilders.java index 3f6f4bcbc4fe3..063a0ad31f38e 100644 --- a/modules/reindex/src/main/java/org/elasticsearch/index/reindex/remote/RemoteRequestBuilders.java +++ b/modules/reindex/src/main/java/org/elasticsearch/index/reindex/remote/RemoteRequestBuilders.java @@ -79,7 +79,11 @@ static Map initialSearchParams(SearchRequest searchRequest, Vers } params.put("size", Integer.toString(searchRequest.source().size())); if (searchRequest.source().version() == null || searchRequest.source().version() == true) { - // false is the only value that makes it false. Null defaults to true.... + /* + * Passing `null` here just add the `version` request parameter + * without any value. This way of requesting the version works + * for all supported versions of Elasticsearch. + */ params.put("version", null); } if (searchRequest.source().sorts() != null) {