Skip to content

Commit 85ed910

Browse files
authored
[Rest Api Compatibility] Typed endpoints for search and related endpoints (#72155)
Implements a V7 compatible typed endpoints for REST for search related apis retrofits the REST layer change removed in #41640 relates main meta issue #51816 relates types removal issue #54160
1 parent b3a1977 commit 85ed910

File tree

27 files changed

+688
-48
lines changed

27 files changed

+688
-48
lines changed

client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.elasticsearch.client.core.TermVectorsRequest;
4848
import org.elasticsearch.client.indices.AnalyzeRequest;
4949
import org.elasticsearch.common.CheckedBiConsumer;
50+
import org.elasticsearch.common.RestApiVersion;
5051
import org.elasticsearch.common.Strings;
5152
import org.elasticsearch.common.bytes.BytesArray;
5253
import org.elasticsearch.common.bytes.BytesReference;
@@ -1227,7 +1228,7 @@ public void testMultiSearch() throws IOException {
12271228
};
12281229
MultiSearchRequest.readMultiLineFormat(new BytesArray(EntityUtils.toByteArray(request.getEntity())),
12291230
REQUEST_BODY_CONTENT_TYPE.xContent(), consumer, null, multiSearchRequest.indicesOptions(), null, null, null,
1230-
xContentRegistry(), true);
1231+
xContentRegistry(), true, RestApiVersion.current());
12311232
assertEquals(requests, multiSearchRequest.requests());
12321233
}
12331234

modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestMultiSearchTemplateAction.java

+14-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
package org.elasticsearch.script.mustache;
1010

1111
import org.elasticsearch.client.node.NodeClient;
12+
import org.elasticsearch.common.RestApiVersion;
1213
import org.elasticsearch.common.settings.Settings;
1314
import org.elasticsearch.rest.BaseRestHandler;
1415
import org.elasticsearch.rest.RestRequest;
@@ -27,7 +28,8 @@
2728
import static org.elasticsearch.rest.RestRequest.Method.POST;
2829

2930
public class RestMultiSearchTemplateAction extends BaseRestHandler {
30-
31+
static final String TYPES_DEPRECATION_MESSAGE = "[types removal]"
32+
+ " Specifying types in multi search template requests is deprecated.";
3133
private static final Set<String> RESPONSE_PARAMS;
3234

3335
static {
@@ -50,7 +52,13 @@ public List<Route> routes() {
5052
new Route(GET, "/_msearch/template"),
5153
new Route(POST, "/_msearch/template"),
5254
new Route(GET, "/{index}/_msearch/template"),
53-
new Route(POST, "/{index}/_msearch/template"));
55+
new Route(POST, "/{index}/_msearch/template"),
56+
Route.builder(GET, "/{index}/{type}/_msearch/template")
57+
.deprecated(TYPES_DEPRECATION_MESSAGE, RestApiVersion.V_7)
58+
.build(),
59+
Route.builder(POST, "/{index}/{type}/_msearch/template")
60+
.deprecated(TYPES_DEPRECATION_MESSAGE, RestApiVersion.V_7)
61+
.build());
5462
}
5563

5664
@Override
@@ -68,6 +76,10 @@ public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client
6876
* Parses a {@link RestRequest} body and returns a {@link MultiSearchTemplateRequest}
6977
*/
7078
public static MultiSearchTemplateRequest parseRequest(RestRequest restRequest, boolean allowExplicitIndex) throws IOException {
79+
if (restRequest.getRestApiVersion() == RestApiVersion.V_7 && restRequest.hasParam("type")) {
80+
restRequest.param("type");
81+
}
82+
7183
MultiSearchTemplateRequest multiRequest = new MultiSearchTemplateRequest();
7284
if (restRequest.hasParam("max_concurrent_searches")) {
7385
multiRequest.maxConcurrentSearchRequests(restRequest.paramAsInt("max_concurrent_searches", 0));

modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestSearchTemplateAction.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import org.elasticsearch.action.search.SearchRequest;
1212
import org.elasticsearch.client.node.NodeClient;
13+
import org.elasticsearch.common.RestApiVersion;
1314
import org.elasticsearch.common.xcontent.XContentParser;
1415
import org.elasticsearch.rest.BaseRestHandler;
1516
import org.elasticsearch.rest.RestRequest;
@@ -27,6 +28,7 @@
2728
import static org.elasticsearch.rest.RestRequest.Method.POST;
2829

2930
public class RestSearchTemplateAction extends BaseRestHandler {
31+
3032
public static final String TYPED_KEYS_PARAM = "typed_keys";
3133
private static final Set<String> RESPONSE_PARAMS;
3234

@@ -41,7 +43,13 @@ public List<Route> routes() {
4143
new Route(GET, "/_search/template"),
4244
new Route(POST, "/_search/template"),
4345
new Route(GET, "/{index}/_search/template"),
44-
new Route(POST, "/{index}/_search/template"));
46+
new Route(POST, "/{index}/_search/template"),
47+
Route.builder(GET, "/{index}/{type}/_search/template")
48+
.deprecated(RestSearchAction.TYPES_DEPRECATION_MESSAGE, RestApiVersion.V_7)
49+
.build(),
50+
Route.builder(POST, "/{index}/{type}/_search/template")
51+
.deprecated(RestSearchAction.TYPES_DEPRECATION_MESSAGE, RestApiVersion.V_7)
52+
.build());
4553
}
4654

4755
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.script.mustache;
10+
11+
import org.elasticsearch.common.RestApiVersion;
12+
import org.elasticsearch.common.bytes.BytesArray;
13+
import org.elasticsearch.common.settings.Settings;
14+
import org.elasticsearch.common.xcontent.XContentType;
15+
import org.elasticsearch.rest.RestRequest;
16+
import org.elasticsearch.test.rest.FakeRestRequest;
17+
import org.elasticsearch.test.rest.RestActionTestCase;
18+
import org.junit.Before;
19+
import org.mockito.Mockito;
20+
21+
import java.nio.charset.StandardCharsets;
22+
import java.util.Collections;
23+
import java.util.List;
24+
import java.util.Map;
25+
26+
public class RestMultiSearchTemplateActionTests extends RestActionTestCase {
27+
final List<String> contentTypeHeader = Collections.singletonList(compatibleMediaType(XContentType.VND_JSON, RestApiVersion.V_7));
28+
29+
@Before
30+
public void setUpAction() {
31+
controller().registerHandler(new RestMultiSearchTemplateAction(Settings.EMPTY));
32+
//todo how to workaround this? we get AssertionError without this
33+
verifyingClient.setExecuteVerifier((actionType, request) -> Mockito.mock(MultiSearchTemplateResponse.class));
34+
verifyingClient.setExecuteLocallyVerifier((actionType, request) -> Mockito.mock(MultiSearchTemplateResponse.class));
35+
}
36+
37+
public void testTypeInPath() {
38+
String content = "{ \"index\": \"some_index\" } \n" +
39+
"{\"source\": {\"query\" : {\"match_all\" :{}}}} \n";
40+
BytesArray bytesContent = new BytesArray(content.getBytes(StandardCharsets.UTF_8));
41+
42+
RestRequest request = new FakeRestRequest.Builder(xContentRegistry())
43+
.withHeaders(Map.of("Content-Type", contentTypeHeader, "Accept", contentTypeHeader))
44+
.withMethod(RestRequest.Method.GET)
45+
.withPath("/some_index/some_type/_msearch/template")
46+
.withContent(bytesContent, null)
47+
.build();
48+
49+
dispatchRequest(request);
50+
assertWarnings(RestMultiSearchTemplateAction.TYPES_DEPRECATION_MESSAGE);
51+
}
52+
53+
public void testTypeInBody() {
54+
String content = "{ \"index\": \"some_index\", \"type\": \"some_type\" } \n" +
55+
"{\"source\": {\"query\" : {\"match_all\" :{}}}} \n";
56+
BytesArray bytesContent = new BytesArray(content.getBytes(StandardCharsets.UTF_8));
57+
58+
RestRequest request = new FakeRestRequest.Builder(xContentRegistry())
59+
.withHeaders(Map.of("Content-Type", contentTypeHeader, "Accept", contentTypeHeader))
60+
.withPath("/some_index/_msearch/template")
61+
.withContent(bytesContent, null)
62+
.build();
63+
64+
dispatchRequest(request);
65+
assertWarnings(RestMultiSearchTemplateAction.TYPES_DEPRECATION_MESSAGE);
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.script.mustache;
10+
11+
import org.elasticsearch.common.RestApiVersion;
12+
import org.elasticsearch.rest.RestRequest;
13+
import org.elasticsearch.rest.action.search.RestSearchAction;
14+
import org.elasticsearch.test.rest.FakeRestRequest;
15+
import org.elasticsearch.test.rest.RestActionTestCase;
16+
import org.junit.Before;
17+
import org.mockito.Mockito;
18+
19+
import java.util.Collections;
20+
import java.util.HashMap;
21+
import java.util.List;
22+
import java.util.Map;
23+
24+
public class RestSearchTemplateActionTests extends RestActionTestCase {
25+
final List<String> contentTypeHeader = Collections.singletonList(randomCompatibleMediaType(RestApiVersion.V_7));
26+
27+
@Before
28+
public void setUpAction() {
29+
controller().registerHandler(new RestSearchTemplateAction());
30+
verifyingClient.setExecuteVerifier((actionType, request) -> Mockito.mock(SearchTemplateResponse.class));
31+
verifyingClient.setExecuteLocallyVerifier((actionType, request) -> Mockito.mock(SearchTemplateResponse.class));
32+
}
33+
34+
public void testTypeInPath() {
35+
RestRequest request = new FakeRestRequest.Builder(xContentRegistry())
36+
.withHeaders(Map.of("Content-Type", contentTypeHeader, "Accept", contentTypeHeader))
37+
.withMethod(RestRequest.Method.GET)
38+
.withPath("/some_index/some_type/_search/template")
39+
.build();
40+
41+
dispatchRequest(request);
42+
assertWarnings(RestSearchAction.TYPES_DEPRECATION_MESSAGE);
43+
}
44+
45+
public void testTypeParameter() {
46+
Map<String, String> params = new HashMap<>();
47+
params.put("type", "some_type");
48+
49+
RestRequest request = new FakeRestRequest.Builder(xContentRegistry())
50+
.withHeaders(Map.of("Content-Type", contentTypeHeader, "Accept", contentTypeHeader))
51+
.withMethod(RestRequest.Method.GET)
52+
.withPath("/some_index/_search/template")
53+
.withParams(params)
54+
.build();
55+
56+
dispatchRequest(request);
57+
assertWarnings(RestSearchAction.TYPES_DEPRECATION_MESSAGE);
58+
}
59+
}

modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestDeleteByQueryAction.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
package org.elasticsearch.index.reindex;
1010

1111
import org.elasticsearch.client.node.NodeClient;
12+
import org.elasticsearch.common.RestApiVersion;
1213
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
1314
import org.elasticsearch.rest.RestRequest;
15+
import org.elasticsearch.rest.action.search.RestSearchAction;
1416

1517
import java.io.IOException;
1618
import java.util.HashMap;
@@ -28,7 +30,12 @@ public RestDeleteByQueryAction() {
2830

2931
@Override
3032
public List<Route> routes() {
31-
return List.of(new Route(POST, "/{index}/_delete_by_query"));
33+
return List.of(new Route(POST, "/{index}/_delete_by_query"),
34+
Route.builder(POST, "/{index}/{type}/_delete_by_query")
35+
.deprecated(RestSearchAction.TYPES_DEPRECATION_MESSAGE, RestApiVersion.V_7)
36+
.build()
37+
);
38+
3239
}
3340

3441
@Override

modules/reindex/src/main/java/org/elasticsearch/index/reindex/RestUpdateByQueryAction.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
package org.elasticsearch.index.reindex;
1010

1111
import org.elasticsearch.client.node.NodeClient;
12+
import org.elasticsearch.common.RestApiVersion;
1213
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
1314
import org.elasticsearch.rest.RestRequest;
15+
import org.elasticsearch.rest.action.search.RestSearchAction;
1416
import org.elasticsearch.script.Script;
1517

1618
import java.io.IOException;
@@ -29,7 +31,12 @@ public RestUpdateByQueryAction() {
2931

3032
@Override
3133
public List<Route> routes() {
32-
return List.of(new Route(POST, "/{index}/_update_by_query"));
34+
return List.of(
35+
new Route(POST, "/{index}/_update_by_query"),
36+
Route.builder(POST, "/{index}/{type}/_update_by_query")
37+
.deprecated(RestSearchAction.TYPES_DEPRECATION_MESSAGE, RestApiVersion.V_7)
38+
.build()
39+
);
3340
}
3441

3542
@Override
@@ -44,6 +51,9 @@ public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client
4451

4552
@Override
4653
protected UpdateByQueryRequest buildRequest(RestRequest request, NamedWriteableRegistry namedWriteableRegistry) throws IOException {
54+
if (request.getRestApiVersion() == RestApiVersion.V_7 && request.hasParam("type")) {
55+
request.param("type");
56+
}
4757
/*
4858
* Passing the search request through UpdateByQueryRequest first allows
4959
* it to set its own defaults which differ from SearchRequest's
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.index.reindex;
10+
11+
import org.elasticsearch.common.RestApiVersion;
12+
import org.elasticsearch.common.xcontent.XContentType;
13+
import org.elasticsearch.rest.RestRequest;
14+
import org.elasticsearch.rest.action.search.RestSearchAction;
15+
import org.elasticsearch.test.rest.FakeRestRequest;
16+
import org.elasticsearch.test.rest.RestActionTestCase;
17+
import org.junit.Before;
18+
import org.mockito.Mockito;
19+
20+
import java.io.IOException;
21+
import java.util.Collections;
22+
import java.util.List;
23+
import java.util.Map;
24+
25+
public class RestDeleteByQueryActionTests extends RestActionTestCase {
26+
27+
final List<String> contentTypeHeader = Collections.singletonList(compatibleMediaType(XContentType.VND_JSON, RestApiVersion.V_7));
28+
29+
@Before
30+
public void setUpAction() {
31+
controller().registerHandler(new RestDeleteByQueryAction());
32+
verifyingClient.setExecuteVerifier((actionType, request) -> Mockito.mock(BulkByScrollResponse.class));
33+
verifyingClient.setExecuteLocallyVerifier((actionType, request) -> Mockito.mock(BulkByScrollResponse.class));
34+
}
35+
36+
public void testTypeInPath() throws IOException {
37+
RestRequest request = new FakeRestRequest.Builder(xContentRegistry())
38+
.withHeaders(Map.of("Content-Type", contentTypeHeader, "Accept", contentTypeHeader))
39+
.withMethod(RestRequest.Method.POST)
40+
.withPath("/some_index/some_type/_delete_by_query")
41+
.build();
42+
43+
// checks the type in the URL is propagated correctly to the request object
44+
// only works after the request is dispatched, so its params are filled from url.
45+
dispatchRequest(request);
46+
47+
48+
// RestDeleteByQueryAction itself doesn't check for a deprecated type usage
49+
// checking here for a deprecation from its internal search request
50+
assertWarnings(RestSearchAction.TYPES_DEPRECATION_MESSAGE);
51+
}
52+
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.index.reindex;
10+
11+
import org.elasticsearch.common.RestApiVersion;
12+
import org.elasticsearch.common.xcontent.XContentType;
13+
import org.elasticsearch.rest.RestRequest;
14+
import org.elasticsearch.rest.action.search.RestSearchAction;
15+
import org.elasticsearch.test.rest.FakeRestRequest;
16+
import org.elasticsearch.test.rest.RestActionTestCase;
17+
import org.junit.Before;
18+
import org.mockito.Mockito;
19+
20+
import java.io.IOException;
21+
import java.util.Collections;
22+
import java.util.List;
23+
import java.util.Map;
24+
25+
public class RestUpdateByQueryActionTests extends RestActionTestCase {
26+
27+
final List<String> contentTypeHeader = Collections.singletonList(compatibleMediaType(XContentType.VND_JSON, RestApiVersion.V_7));
28+
29+
@Before
30+
public void setUpAction() {
31+
controller().registerHandler(new RestUpdateByQueryAction());
32+
verifyingClient.setExecuteVerifier((actionType, request) -> Mockito.mock(BulkByScrollResponse.class));
33+
verifyingClient.setExecuteLocallyVerifier((actionType, request) -> Mockito.mock(BulkByScrollResponse.class));
34+
}
35+
36+
public void testTypeInPath() throws IOException {
37+
RestRequest request = new FakeRestRequest.Builder(xContentRegistry())
38+
.withHeaders(Map.of("Content-Type", contentTypeHeader, "Accept", contentTypeHeader))
39+
.withMethod(RestRequest.Method.POST)
40+
.withPath("/some_index/some_type/_update_by_query")
41+
.build();
42+
43+
// checks the type in the URL is propagated correctly to the request object
44+
// only works after the request is dispatched, so its params are filled from url.
45+
dispatchRequest(request);
46+
47+
// RestUpdateByQueryAction itself doesn't check for a deprecated type usage
48+
// checking here for a deprecation from its internal search request
49+
assertWarnings(RestSearchAction.TYPES_DEPRECATION_MESSAGE);
50+
}
51+
}

0 commit comments

Comments
 (0)