-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Ryan Bogan <[email protected]>
- Loading branch information
Showing
13 changed files
with
898 additions
and
303 deletions.
There are no files selected for viewing
41 changes: 0 additions & 41 deletions
41
server/src/main/java/org/opensearch/extensions/ExtensionStringResponse.java
This file was deleted.
Oops, something went wrong.
292 changes: 292 additions & 0 deletions
292
server/src/main/java/org/opensearch/extensions/rest/ExtensionRestRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,292 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* The OpenSearch Contributors require contributions made to | ||
* this file be licensed under the Apache-2.0 license or a | ||
* compatible open source license. | ||
*/ | ||
|
||
package org.opensearch.extensions.rest; | ||
|
||
import org.opensearch.OpenSearchParseException; | ||
import org.opensearch.common.bytes.BytesReference; | ||
import org.opensearch.common.io.stream.StreamInput; | ||
import org.opensearch.common.io.stream.StreamOutput; | ||
import org.opensearch.common.xcontent.LoggingDeprecationHandler; | ||
import org.opensearch.common.xcontent.NamedXContentRegistry; | ||
import org.opensearch.common.xcontent.XContentParser; | ||
import org.opensearch.common.xcontent.XContentType; | ||
import org.opensearch.rest.RestRequest; | ||
import org.opensearch.rest.RestRequest.Method; | ||
import org.opensearch.transport.TransportRequest; | ||
|
||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
import java.util.Set; | ||
|
||
/** | ||
* Request to execute REST actions on extension node. | ||
* This contains necessary portions of a {@link RestRequest} object, but does not pass the full request for security concerns. | ||
* | ||
* @opensearch.api | ||
*/ | ||
public class ExtensionRestRequest extends TransportRequest { | ||
|
||
private Method method; | ||
private String path; | ||
private Map<String, String> params; | ||
private XContentType xContentType = null; | ||
private BytesReference content; | ||
// The owner of this request object | ||
// Will be replaced with PrincipalIdentifierToken class from feature/identity | ||
private String principalIdentifierToken; | ||
|
||
// Tracks consumed parameters and content | ||
private final Set<String> consumedParams = new HashSet<>(); | ||
private boolean contentConsumed = false; | ||
|
||
/** | ||
* This object can be instantiated given method, uri, params, content and identifier | ||
* | ||
* @param method of type {@link Method} | ||
* @param path the REST path string (excluding the query) | ||
* @param params the REST params | ||
* @param xContentType the content type, or null for plain text or no content | ||
* @param content the REST request content | ||
* @param principalIdentifier the owner of this request | ||
*/ | ||
public ExtensionRestRequest( | ||
Method method, | ||
String path, | ||
Map<String, String> params, | ||
XContentType xContentType, | ||
BytesReference content, | ||
String principalIdentifier | ||
) { | ||
this.method = method; | ||
this.path = path; | ||
this.params = params; | ||
this.xContentType = xContentType; | ||
this.content = content; | ||
this.principalIdentifierToken = principalIdentifier; | ||
} | ||
|
||
/** | ||
* Instantiate this request from input stream | ||
* | ||
* @param in Input stream | ||
* @throws IOException on failure to read the stream | ||
*/ | ||
public ExtensionRestRequest(StreamInput in) throws IOException { | ||
super(in); | ||
method = in.readEnum(RestRequest.Method.class); | ||
path = in.readString(); | ||
params = in.readMap(StreamInput::readString, StreamInput::readString); | ||
if (in.readBoolean()) { | ||
xContentType = in.readEnum(XContentType.class); | ||
} | ||
content = in.readBytesReference(); | ||
principalIdentifierToken = in.readString(); | ||
} | ||
|
||
@Override | ||
public void writeTo(StreamOutput out) throws IOException { | ||
super.writeTo(out); | ||
out.writeEnum(method); | ||
out.writeString(path); | ||
out.writeMap(params, StreamOutput::writeString, StreamOutput::writeString); | ||
out.writeBoolean(xContentType != null); | ||
if (xContentType != null) { | ||
out.writeEnum(xContentType); | ||
} | ||
out.writeBytesReference(content); | ||
out.writeString(principalIdentifierToken); | ||
} | ||
|
||
/** | ||
* Gets the REST method | ||
* | ||
* @return This REST request {@link Method} type | ||
*/ | ||
public Method method() { | ||
return method; | ||
} | ||
|
||
/** | ||
* Gets the REST path | ||
* | ||
* @return This REST request's path | ||
*/ | ||
public String path() { | ||
return path; | ||
} | ||
|
||
/** | ||
* Gets the full map of params without consuming them. Rest Handlers should use {@link #param(String)} or {@link #param(String, String)} | ||
* to get parameter values. | ||
* | ||
* @return This REST request's params | ||
*/ | ||
public Map<String, String> params() { | ||
return params; | ||
} | ||
|
||
/** | ||
* Tests whether a parameter named {@code key} exists. | ||
* | ||
* @param key The parameter to test. | ||
* @return True if there is a value for this parameter. | ||
*/ | ||
public boolean hasParam(String key) { | ||
return params.containsKey(key); | ||
} | ||
|
||
/** | ||
* Gets the value of a parameter, consuming it in the process. | ||
* | ||
* @param key The parameter key | ||
* @return The parameter value if it exists, or null. | ||
*/ | ||
public String param(String key) { | ||
consumedParams.add(key); | ||
return params.get(key); | ||
} | ||
|
||
/** | ||
* Gets the value of a parameter, consuming it in the process. | ||
* | ||
* @param key The parameter key | ||
* @param defaultValue A value to return if the parameter value doesn't exist. | ||
* @return The parameter value if it exists, or the default value. | ||
*/ | ||
public String param(String key, String defaultValue) { | ||
consumedParams.add(key); | ||
return params.getOrDefault(key, defaultValue); | ||
} | ||
|
||
/** | ||
* Gets the value of a parameter as a long, consuming it in the process. | ||
* | ||
* @param key The parameter key | ||
* @param defaultValue A value to return if the parameter value doesn't exist. | ||
* @return The parameter value if it exists, or the default value. | ||
*/ | ||
public long paramAsLong(String key, long defaultValue) { | ||
String value = param(key); | ||
if (value == null) { | ||
return defaultValue; | ||
} | ||
try { | ||
return Long.parseLong(value); | ||
} catch (NumberFormatException e) { | ||
throw new IllegalArgumentException("Unable to parse param '" + key + "' value '" + value + "' to a long.", e); | ||
} | ||
} | ||
|
||
/** | ||
* Returns parameters consumed by {@link #param(String)} or {@link #param(String, String)}. | ||
* | ||
* @return a list of consumed parameters. | ||
*/ | ||
public List<String> consumedParams() { | ||
return new ArrayList<>(consumedParams); | ||
} | ||
|
||
/** | ||
* Gets the content type, if any. | ||
* | ||
* @return the content type of the {@link #content()}, or null if the context is plain text or if there is no content. | ||
*/ | ||
public XContentType getXContentType() { | ||
return xContentType; | ||
} | ||
|
||
/** | ||
* Gets the content. | ||
* | ||
* @return This REST request's content | ||
*/ | ||
public BytesReference content() { | ||
contentConsumed = true; | ||
return content; | ||
} | ||
|
||
/** | ||
* Tests whether content exists. | ||
* | ||
* @return True if there is non-empty content. | ||
*/ | ||
public boolean hasContent() { | ||
return content.length() > 0; | ||
} | ||
|
||
/** | ||
* Tests whether content has been consumed. | ||
* | ||
* @return True if the content was consumed. | ||
*/ | ||
public boolean isContentConsumed() { | ||
return contentConsumed; | ||
} | ||
|
||
/** | ||
* Gets a parser for the contents of this request if there is content and an xContentType. | ||
* | ||
* @param xContentRegistry The extension's xContentRegistry | ||
* @return A parser for the given content and content type. | ||
* @throws OpenSearchParseException on missing body or xContentType. | ||
* @throws IOException on a failure creating the parser. | ||
*/ | ||
public final XContentParser contentParser(NamedXContentRegistry xContentRegistry) throws IOException { | ||
if (!hasContent() || getXContentType() == null) { | ||
throw new OpenSearchParseException("There is no request body or the ContentType is invalid."); | ||
} | ||
return getXContentType().xContent().createParser(xContentRegistry, LoggingDeprecationHandler.INSTANCE, content.streamInput()); | ||
} | ||
|
||
/** | ||
* @return This REST request issuer's identity token | ||
*/ | ||
public String getRequestIssuerIdentity() { | ||
return principalIdentifierToken; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "ExtensionRestRequest{method=" | ||
+ method | ||
+ ", path=" | ||
+ path | ||
+ ", params=" | ||
+ params | ||
+ ", xContentType=" | ||
+ xContentType | ||
+ ", contentLength=" | ||
+ content.length() | ||
+ ", requester=" | ||
+ principalIdentifierToken | ||
+ "}"; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) return true; | ||
if (obj == null || getClass() != obj.getClass()) return false; | ||
ExtensionRestRequest that = (ExtensionRestRequest) obj; | ||
return Objects.equals(method, that.method) | ||
&& Objects.equals(path, that.path) | ||
&& Objects.equals(params, that.params) | ||
&& Objects.equals(xContentType, that.xContentType) | ||
&& Objects.equals(content, that.content) | ||
&& Objects.equals(principalIdentifierToken, that.principalIdentifierToken); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(method, path, params, xContentType, content, principalIdentifierToken); | ||
} | ||
} |
Oops, something went wrong.