Skip to content

Commit c08cd83

Browse files
Do not allow project_routing as a query param (elastic#139206)
ES-13725: We previously had plans to allow `project_routing` as a query param and also in the request body. However, after the recent discussions with Kibana and the clients team, we will now restrict it to the request body.
1 parent 9f49b33 commit c08cd83

File tree

7 files changed

+62
-25
lines changed

7 files changed

+62
-25
lines changed

server/src/main/java/org/elasticsearch/action/search/RestOpenPointInTimeAction.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
5555
final OpenPointInTimeRequest openRequest = new OpenPointInTimeRequest(indices);
5656
final boolean crossProjectEnabled = crossProjectModeDecider.crossProjectEnabled();
5757
if (crossProjectEnabled) {
58-
openRequest.projectRouting(request.param("project_routing", null));
5958
openRequest.indicesOptions(IndicesOptions.fromRequest(request, OpenPointInTimeRequest.DEFAULT_CPS_INDICES_OPTIONS));
6059
} else {
6160
openRequest.indicesOptions(IndicesOptions.fromRequest(request, OpenPointInTimeRequest.DEFAULT_INDICES_OPTIONS));

server/src/main/java/org/elasticsearch/rest/action/RestFieldCapabilitiesAction.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
6262

6363
final boolean crossProjectEnabled = crossProjectModeDecider.crossProjectEnabled();
6464
if (crossProjectEnabled) {
65-
fieldRequest.projectRouting(request.param("project_routing", null));
6665
// Setting includeResolvedTo to always include index resolution data structure in the linked project responses,
6766
// in order to allow the coordinating node to call CrossProjectIndexResolutionValidator#validate
6867
fieldRequest.includeResolvedTo(true);

server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestResolveIndexAction.java

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99

1010
package org.elasticsearch.rest.action.admin.indices;
1111

12+
import org.elasticsearch.ElasticsearchException;
1213
import org.elasticsearch.action.admin.indices.resolve.ResolveIndexAction;
1314
import org.elasticsearch.action.support.IndicesOptions;
1415
import org.elasticsearch.client.internal.node.NodeClient;
16+
import org.elasticsearch.common.ParsingException;
1517
import org.elasticsearch.common.Strings;
1618
import org.elasticsearch.common.settings.Settings;
1719
import org.elasticsearch.index.IndexMode;
@@ -20,22 +22,26 @@
2022
import org.elasticsearch.rest.Scope;
2123
import org.elasticsearch.rest.ServerlessScope;
2224
import org.elasticsearch.rest.action.RestToXContentListener;
25+
import org.elasticsearch.search.crossproject.CrossProjectModeDecider;
26+
import org.elasticsearch.xcontent.XContentParser;
2327

2428
import java.io.IOException;
2529
import java.util.Arrays;
2630
import java.util.EnumSet;
2731
import java.util.List;
2832
import java.util.Set;
33+
import java.util.concurrent.atomic.AtomicReference;
2934

3035
import static org.elasticsearch.rest.RestRequest.Method.GET;
36+
import static org.elasticsearch.rest.RestRequest.Method.POST;
3137

3238
@ServerlessScope(Scope.PUBLIC)
3339
public class RestResolveIndexAction extends BaseRestHandler {
3440
private static final Set<String> CAPABILITIES = Set.of("mode_filter");
35-
private final Settings settings;
41+
private final CrossProjectModeDecider crossProjectModeDecider;
3642

3743
public RestResolveIndexAction(Settings settings) {
38-
this.settings = settings;
44+
this.crossProjectModeDecider = new CrossProjectModeDecider(settings);
3945
}
4046

4147
@Override
@@ -45,7 +51,7 @@ public String getName() {
4551

4652
@Override
4753
public List<Route> routes() {
48-
return List.of(new Route(GET, "/_resolve/index/{name}"));
54+
return List.of(new Route(GET, "/_resolve/index/{name}"), new Route(POST, "/_resolve/index/{name}"));
4955
}
5056

5157
@Override
@@ -57,17 +63,28 @@ public Set<String> supportedCapabilities() {
5763
protected BaseRestHandler.RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException {
5864
String[] indices = Strings.splitStringByCommaToArray(request.param("name"));
5965
String modeParam = request.param("mode");
60-
final boolean crossProjectEnabled = settings != null && settings.getAsBoolean("serverless.cross_project.enabled", false);
61-
String projectRouting = null;
62-
if (crossProjectEnabled) {
63-
projectRouting = request.param("project_routing");
64-
}
66+
67+
final boolean crossProjectEnabled = crossProjectModeDecider.crossProjectEnabled();
68+
AtomicReference<String> projectRouting = new AtomicReference<>();
6569
IndicesOptions indicesOptions = IndicesOptions.fromRequest(request, ResolveIndexAction.Request.DEFAULT_INDICES_OPTIONS);
70+
6671
if (crossProjectEnabled) {
72+
request.withContentOrSourceParamParserOrNull(parser -> {
73+
try {
74+
// If parser is null, there's no request body. projectRouting will then yield `null`.
75+
if (parser != null) {
76+
projectRouting.set(parseProjectRouting(parser));
77+
}
78+
} catch (Exception e) {
79+
throw new ElasticsearchException("Couldn't parse request body", e);
80+
}
81+
});
82+
6783
indicesOptions = IndicesOptions.builder(indicesOptions)
6884
.crossProjectModeOptions(new IndicesOptions.CrossProjectModeOptions(true))
6985
.build();
7086
}
87+
7188
ResolveIndexAction.Request resolveRequest = new ResolveIndexAction.Request(
7289
indices,
7390
indicesOptions,
@@ -76,8 +93,44 @@ protected BaseRestHandler.RestChannelConsumer prepareRequest(RestRequest request
7693
: Arrays.stream(modeParam.split(","))
7794
.map(IndexMode::fromString)
7895
.collect(() -> EnumSet.noneOf(IndexMode.class), EnumSet::add, EnumSet::addAll),
79-
projectRouting
96+
projectRouting.get()
8097
);
8198
return channel -> client.admin().indices().resolveIndex(resolveRequest, new RestToXContentListener<>(channel));
8299
}
100+
101+
private static String parseProjectRouting(XContentParser parser) throws ParsingException {
102+
try {
103+
XContentParser.Token first = parser.nextToken();
104+
if (first == null) {
105+
return null;
106+
}
107+
108+
if (first != XContentParser.Token.START_OBJECT) {
109+
throw new ParsingException(
110+
parser.getTokenLocation(),
111+
"Expected [" + XContentParser.Token.START_OBJECT + "] but found [" + first + "]",
112+
parser.getTokenLocation()
113+
);
114+
}
115+
116+
String projectRouting = null;
117+
for (XContentParser.Token token = parser.nextToken(); token != XContentParser.Token.END_OBJECT; token = parser.nextToken()) {
118+
if (token == XContentParser.Token.FIELD_NAME) {
119+
String currentName = parser.currentName();
120+
if ("project_routing".equals(currentName)) {
121+
parser.nextToken();
122+
projectRouting = parser.text();
123+
} else {
124+
throw new ParsingException(parser.getTokenLocation(), "request does not support [" + parser.currentName() + "]");
125+
}
126+
}
127+
}
128+
129+
return projectRouting;
130+
} catch (ParsingException e) {
131+
throw e;
132+
} catch (Exception e) {
133+
throw new ParsingException(parser == null ? null : parser.getTokenLocation(), "Failed to parse", e);
134+
}
135+
}
83136
}

server/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,6 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
108108
request.param("min_compatible_shard_node");
109109

110110
final boolean crossProjectEnabled = crossProjectModeDecider.crossProjectEnabled();
111-
if (crossProjectEnabled) {
112-
searchRequest.setProjectRouting(request.param("project_routing"));
113-
}
114111

115112
/*
116113
* We have to pull out the call to `source().size(size)` because

x-pack/plugin/async-search/src/main/java/org/elasticsearch/xpack/search/RestSubmitAsyncSearchAction.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli
7272
boolean crossProjectEnabled = crossProjectModeDecider.crossProjectEnabled();
7373
if (crossProjectEnabled) {
7474
submit.getSearchRequest().setCcsMinimizeRoundtrips(true);
75-
submit.getSearchRequest().setProjectRouting(request.param("project_routing"));
7675
}
7776

7877
IntConsumer setSize = size -> submit.getSearchRequest().source().size(size);

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlQueryAction.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,6 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli
5656
sqlRequest = SqlQueryRequest.fromXContent(parser);
5757
}
5858

59-
String routingParam = request.param("project_routing");
60-
if (routingParam != null) {
61-
// takes precedence on the parameter in the body
62-
sqlRequest.projectRouting(routingParam);
63-
}
6459
if (sqlRequest.projectRouting() != null && crossProjectModeDecider.crossProjectEnabled() == false) {
6560
throw new InvalidArgumentException("[project_routing] is only allowed when cross-project search is enabled");
6661
}

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlTranslateAction.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,6 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli
4949
try (XContentParser parser = request.contentOrSourceParamParser()) {
5050
sqlRequest = SqlTranslateRequest.fromXContent(parser);
5151
}
52-
String routingParam = request.param("project_routing");
53-
if (routingParam != null) {
54-
// takes precedence on the parameter in the body
55-
sqlRequest.projectRouting(routingParam);
56-
}
5752
if (sqlRequest.projectRouting() != null && crossProjectModeDecider.crossProjectEnabled() == false) {
5853
throw new InvalidArgumentException("[project_routing] is only allowed when cross-project search is enabled");
5954
}

0 commit comments

Comments
 (0)