Skip to content

Commit 9ccf65e

Browse files
Add support for request body for _resolve/index
1 parent 4cae9b0 commit 9ccf65e

File tree

1 file changed

+62
-9
lines changed

1 file changed

+62
-9
lines changed

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 IOException {
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
}

0 commit comments

Comments
 (0)