Skip to content

Commit fe3d26c

Browse files
committed
Add content and expand param getters
Signed-off-by: Daniel Widdis <widdis@gmail.com>
1 parent 63f611b commit fe3d26c

File tree

4 files changed

+259
-27
lines changed

4 files changed

+259
-27
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
104104
- Adding create component extension point support for AD ([#4517](https://github.com/opensearch-project/OpenSearch/pull/4517))
105105
- Add getSettings support for AD([#4519](https://github.com/opensearch-project/OpenSearch/pull/4519))
106106
- Fixed javadoc warning for build failure([#4581](https://github.com/opensearch-project/OpenSearch/pull/4581))
107-
- Pass REST params to extensions ([#4633](https://github.com/opensearch-project/OpenSearch/pull/4633))
107+
- Pass REST params and content to extensions ([#4633](https://github.com/opensearch-project/OpenSearch/pull/4633))
108108

109109
## [2.x]
110110
### Added

server/src/main/java/org/opensearch/extensions/rest/ExtensionRestRequest.java

Lines changed: 116 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88

99
package org.opensearch.extensions.rest;
1010

11+
import org.opensearch.common.bytes.BytesReference;
1112
import org.opensearch.common.io.stream.StreamInput;
1213
import org.opensearch.common.io.stream.StreamOutput;
14+
import org.opensearch.common.xcontent.XContentType;
1315
import org.opensearch.identity.PrincipalIdentifierToken;
1416
import org.opensearch.rest.RestRequest;
1517
import org.opensearch.rest.RestRequest.Method;
@@ -33,27 +35,44 @@ public class ExtensionRestRequest extends TransportRequest {
3335
private Method method;
3436
private String uri;
3537
private Map<String, String> params;
38+
private XContentType xContentType = null;
39+
private BytesReference content;
3640
// The owner of this request object
3741
private PrincipalIdentifierToken principalIdentifierToken;
38-
// Tracks consumed parameters
42+
43+
// Tracks consumed parameters and content
3944
private final Set<String> consumedParams = new HashSet<>();
45+
private boolean contentConsumed = false;
4046

4147
/**
42-
* This object can be instantiated given method, uri, params and identifier
48+
* This object can be instantiated given method, uri, params, content and identifier
49+
*
4350
* @param method of type {@link Method}
4451
* @param uri url string
4552
* @param params the REST params
53+
* @param xContentType the content type, or null for plain text or no content
54+
* @param content the REST request content
4655
* @param principalIdentifier the owner of this request
4756
*/
48-
public ExtensionRestRequest(Method method, String uri, Map<String, String> params, PrincipalIdentifierToken principalIdentifier) {
57+
public ExtensionRestRequest(
58+
Method method,
59+
String uri,
60+
Map<String, String> params,
61+
XContentType xContentType,
62+
BytesReference content,
63+
PrincipalIdentifierToken principalIdentifier
64+
) {
4965
this.method = method;
5066
this.uri = uri;
5167
this.params = params;
68+
this.xContentType = xContentType;
69+
this.content = content;
5270
this.principalIdentifierToken = principalIdentifier;
5371
}
5472

5573
/**
5674
* Instantiate this request from input stream
75+
*
5776
* @param in Input stream
5877
* @throws IOException on failure to read the stream
5978
*/
@@ -62,6 +81,10 @@ public ExtensionRestRequest(StreamInput in) throws IOException {
6281
method = in.readEnum(RestRequest.Method.class);
6382
uri = in.readString();
6483
params = in.readMap(StreamInput::readString, StreamInput::readString);
84+
if (in.readBoolean()) {
85+
xContentType = in.readEnum(XContentType.class);
86+
}
87+
content = in.readBytesReference();
6588
principalIdentifierToken = in.readNamedWriteable(PrincipalIdentifierToken.class);
6689
}
6790

@@ -71,25 +94,55 @@ public void writeTo(StreamOutput out) throws IOException {
7194
out.writeEnum(method);
7295
out.writeString(uri);
7396
out.writeMap(params, StreamOutput::writeString, StreamOutput::writeString);
97+
out.writeBoolean(xContentType != null);
98+
if (xContentType != null) {
99+
out.writeEnum(xContentType);
100+
}
101+
out.writeBytesReference(content);
74102
out.writeNamedWriteable(principalIdentifierToken);
75103
}
76104

77105
/**
106+
* Gets the REST method
107+
*
78108
* @return This REST request {@link Method} type
79109
*/
80110
public Method method() {
81111
return method;
82112
}
83113

84114
/**
115+
* Gets the REST uri
116+
*
85117
* @return This REST request's uri
86118
*/
87119
public String uri() {
88120
return uri;
89121
}
90122

123+
/**
124+
* Gets the full map of params without consuming them. Rest Handlers should use {@link #param(String)} or {@link #param(String, String)}
125+
* to get parameter values.
126+
*
127+
* @return This REST request's params
128+
*/
129+
public Map<String, String> params() {
130+
return params;
131+
}
132+
133+
/**
134+
* Tests whether a parameter named {@code key} exists.
135+
*
136+
* @param key The parameter to test.
137+
* @return True if there is a value for this parameter.
138+
*/
139+
public boolean hasParam(String key) {
140+
return params.containsKey(key);
141+
}
142+
91143
/**
92144
* Gets the value of a parameter, consuming it in the process.
145+
*
93146
* @param key The parameter key
94147
* @return The parameter value if it exists, or null.
95148
*/
@@ -100,8 +153,9 @@ public String param(String key) {
100153

101154
/**
102155
* Gets the value of a parameter, consuming it in the process.
156+
*
103157
* @param key The parameter key
104-
* @param defaultValue A value to return if the parameter value doesn't exist.
158+
* @param defaultValue A value to return if the parameter value doesn't exist.
105159
* @return The parameter value if it exists, or the default value.
106160
*/
107161
public String param(String key, String defaultValue) {
@@ -110,13 +164,22 @@ public String param(String key, String defaultValue) {
110164
}
111165

112166
/**
113-
* Gets the full map of params without consuming them.
114-
* Rest Handlers should use {@link #param(String)} or {@link #param(String, String)} to get parameter values.
167+
* Gets the value of a parameter as a long, consuming it in the process.
115168
*
116-
* @return This REST request's params
169+
* @param key The parameter key
170+
* @param defaultValue A value to return if the parameter value doesn't exist.
171+
* @return The parameter value if it exists, or the default value.
117172
*/
118-
public Map<String, String> params() {
119-
return params;
173+
public long paramAsLong(String key, long defaultValue) {
174+
String value = param(key);
175+
if (value == null) {
176+
return defaultValue;
177+
}
178+
try {
179+
return Long.parseLong(value);
180+
} catch (NumberFormatException e) {
181+
throw new IllegalArgumentException("Unable to parse param '" + key + "' value '" + value + "' to a long.", e);
182+
}
120183
}
121184

122185
/**
@@ -128,6 +191,43 @@ public List<String> consumedParams() {
128191
return new ArrayList<>(consumedParams);
129192
}
130193

194+
/**
195+
* Gets the content type, if any.
196+
*
197+
* @return the content type of the {@link #content()}, or null if the context is plain text or if there is no content.
198+
*/
199+
public XContentType getXContentType() {
200+
return xContentType;
201+
}
202+
203+
/**
204+
* Gets the content.
205+
*
206+
* @return This REST request's content
207+
*/
208+
public BytesReference content() {
209+
contentConsumed = true;
210+
return content;
211+
}
212+
213+
/**
214+
* Tests whether content exists.
215+
*
216+
* @return True if there is non-empty content.
217+
*/
218+
public boolean hasContent() {
219+
return content.length() > 0;
220+
}
221+
222+
/**
223+
* Tests whether content has been consumed.
224+
*
225+
* @return True if the content was consumed.
226+
*/
227+
public boolean isContentConsumed() {
228+
return contentConsumed;
229+
}
230+
131231
/**
132232
* @return This REST request issuer's identity token
133233
*/
@@ -143,6 +243,10 @@ public String toString() {
143243
+ uri
144244
+ ", params="
145245
+ params
246+
+ ", xContentType="
247+
+ xContentType
248+
+ ", contentLength="
249+
+ content.length()
146250
+ ", requester="
147251
+ principalIdentifierToken.getToken()
148252
+ "}";
@@ -156,11 +260,13 @@ public boolean equals(Object obj) {
156260
return Objects.equals(method, that.method)
157261
&& Objects.equals(uri, that.uri)
158262
&& Objects.equals(params, that.params)
263+
&& Objects.equals(xContentType, that.xContentType)
264+
&& Objects.equals(content, that.content)
159265
&& Objects.equals(principalIdentifierToken, that.principalIdentifierToken);
160266
}
161267

162268
@Override
163269
public int hashCode() {
164-
return Objects.hash(method, uri, params, principalIdentifierToken);
270+
return Objects.hash(method, uri, params, xContentType, content, principalIdentifierToken);
165271
}
166272
}

server/src/main/java/org/opensearch/extensions/rest/RestSendToExtensionAction.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
import org.apache.logging.log4j.LogManager;
1212
import org.apache.logging.log4j.Logger;
1313
import org.opensearch.client.node.NodeClient;
14+
import org.opensearch.common.bytes.BytesReference;
1415
import org.opensearch.common.io.stream.StreamInput;
16+
import org.opensearch.common.xcontent.XContentType;
1517
import org.opensearch.extensions.DiscoveryExtension;
1618
import org.opensearch.extensions.ExtensionsOrchestrator;
1719
import org.opensearch.identity.ExtensionTokenProcessor;
@@ -48,6 +50,7 @@ public class RestSendToExtensionAction extends BaseRestHandler {
4850
private static final String SEND_TO_EXTENSION_ACTION = "send_to_extension_action";
4951
private static final Logger logger = LogManager.getLogger(RestSendToExtensionAction.class);
5052
private static final String CONSUMED_PARAMS_KEY = "extension.consumed.parameters";
53+
private static final String CONSUMED_CONTENT_KEY = "extension.consumed.content";
5154
// To replace with user identity see https://github.com/opensearch-project/OpenSearch/pull/4247
5255
private static final Principal DEFAULT_PRINCIPAL = new Principal() {
5356
@Override
@@ -108,6 +111,8 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
108111
Method method = request.method();
109112
String uri = request.uri();
110113
Map<String, String> params = request.params();
114+
XContentType contentType = request.getXContentType();
115+
BytesReference content = request.content();
111116

112117
if (uri.startsWith(uriPrefix)) {
113118
uri = uri.substring(uriPrefix.length());
@@ -136,12 +141,20 @@ public void handleResponse(RestExecuteOnExtensionResponse response) {
136141
restExecuteOnExtensionResponse.setStatus(response.getStatus());
137142
restExecuteOnExtensionResponse.setContentType(response.getContentType());
138143
restExecuteOnExtensionResponse.setContent(response.getContent());
139-
// Extract the consumed parameters from the header
144+
// Extract the consumed parameters and content from the header
140145
Map<String, List<String>> headers = response.getHeaders();
141146
List<String> consumedParams = headers.get(CONSUMED_PARAMS_KEY);
142147
if (consumedParams != null) {
148+
// consume each param
143149
consumedParams.stream().forEach(p -> request.param(p));
144150
}
151+
List<String> consumedContent = headers.get(CONSUMED_CONTENT_KEY);
152+
if (consumedContent != null) {
153+
// conditionally consume content
154+
if (consumedParams.stream().filter(c -> Boolean.parseBoolean(c)).count() > 0) {
155+
request.content();
156+
}
157+
}
145158
Map<String, List<String>> headersWithoutConsumedParams = headers.entrySet()
146159
.stream()
147160
.filter(e -> !e.getKey().equals(CONSUMED_PARAMS_KEY))
@@ -173,7 +186,7 @@ public String executor() {
173186
ExtensionsOrchestrator.REQUEST_REST_EXECUTE_ON_EXTENSION_ACTION,
174187
// HERE BE DRAGONS - DO NOT INCLUDE HEADERS
175188
// SEE https://github.com/opensearch-project/OpenSearch/issues/4429
176-
new ExtensionRestRequest(method, uri, params, requestIssuerIdentity),
189+
new ExtensionRestRequest(method, uri, params, contentType, content, requestIssuerIdentity),
177190
restExecuteOnExtensionResponseHandler
178191
);
179192
try {

0 commit comments

Comments
 (0)