88
99package org .opensearch .extensions .rest ;
1010
11+ import org .opensearch .common .bytes .BytesReference ;
1112import org .opensearch .common .io .stream .StreamInput ;
1213import org .opensearch .common .io .stream .StreamOutput ;
14+ import org .opensearch .common .xcontent .XContentType ;
1315import org .opensearch .identity .PrincipalIdentifierToken ;
1416import org .opensearch .rest .RestRequest ;
1517import 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}
0 commit comments