Skip to content

Commit

Permalink
Match Rest Path registry with RestController using SDKMethodHandlers (#…
Browse files Browse the repository at this point in the history
…658)

Signed-off-by: Daniel Widdis <[email protected]>
  • Loading branch information
dbwiddis authored Apr 7, 2023
1 parent a7a8164 commit 94618e0
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 13 deletions.
1 change: 1 addition & 0 deletions src/main/java/org/opensearch/sdk/ExtensionsRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.opensearch.sdk.handlers.ExtensionsInitRequestHandler;
import org.opensearch.sdk.handlers.ExtensionsRestRequestHandler;
import org.opensearch.sdk.handlers.UpdateSettingsRequestHandler;
import org.opensearch.sdk.rest.ExtensionRestPathRegistry;
import org.opensearch.tasks.TaskManager;
import org.opensearch.threadpool.ExecutorBuilder;
import org.opensearch.threadpool.RunnableTaskExecutionListener;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@
import org.opensearch.sdk.ExtensionRestHandler;
import org.opensearch.sdk.ExtensionsRunner;
import org.opensearch.sdk.SDKNamedXContentRegistry;
import org.opensearch.sdk.rest.ExtensionRestPathRegistry;
import org.opensearch.sdk.rest.SDKHttpRequest;
import org.opensearch.sdk.rest.SDKRestRequest;

import org.opensearch.sdk.ExtensionRestPathRegistry;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptyList;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,24 @@
* compatible open source license.
*/

package org.opensearch.sdk;
package org.opensearch.sdk.rest;

import java.util.ArrayList;
import java.util.List;

import org.opensearch.common.Nullable;
import org.opensearch.common.path.PathTrie;
import org.opensearch.rest.RestUtils;
import org.opensearch.rest.RestRequest.Method;
import org.opensearch.sdk.ExtensionRestHandler;

/**
* This class registers REST paths from extension Rest Handlers.
*/
public class ExtensionRestPathRegistry {

// PathTrie to match paths to handlers
private PathTrie<ExtensionRestHandler> pathTrie = new PathTrie<>(RestUtils.REST_DECODER);
private PathTrie<SDKMethodHandlers> pathTrie = new PathTrie<>(RestUtils.REST_DECODER);
// List to return registered handlers
private List<String> registeredPaths = new ArrayList<>();

Expand All @@ -34,20 +36,25 @@ public class ExtensionRestPathRegistry {
* @param extensionRestHandler The RestHandler to handle this route
*/
public void registerHandler(Method method, String path, ExtensionRestHandler extensionRestHandler) {
String restPath = restPathToString(method, path);
pathTrie.insert(restPath, extensionRestHandler);
registeredPaths.add(restPath);
pathTrie.insertOrUpdate(
path,
new SDKMethodHandlers(path, extensionRestHandler, method),
(mHandlers, newMHandler) -> mHandlers.addMethods(extensionRestHandler, method)
);
registeredPaths.add(restPathToString(method, path));
}

/**
* Get the registered REST handler for the specified method and URI.
* Get the registered REST handler for the specified method and path.
*
* @param method the registered method.
* @param path the registered path.
* @return The REST handler registered to handle this method and URI combination if found, null otherwise.
* @return The REST handler registered to handle this method and path combination if found, null otherwise.
*/
@Nullable
public ExtensionRestHandler getHandler(Method method, String path) {
return pathTrie.retrieve(restPathToString(method, path));
SDKMethodHandlers mHandlers = pathTrie.retrieve(path);
return mHandlers == null ? null : mHandlers.getHandler(method);
}

/**
Expand All @@ -60,7 +67,9 @@ public List<String> getRegisteredPaths() {
}

/**
* Converts a REST method and path to a space delimited string to be used as a map lookup key.
* Converts a REST method and path to a space delimited string.
* <p>
* This provides convenience for logging and serialization over transport.
*
* @param method the method.
* @param path the path.
Expand Down
67 changes: 67 additions & 0 deletions src/main/java/org/opensearch/sdk/rest/SDKMethodHandlers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright OpenSearch Contributors
* 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.sdk.rest;

import org.opensearch.common.Nullable;
import org.opensearch.sdk.ExtensionRestHandler;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import static org.opensearch.rest.RestRequest.Method;

/**
* Encapsulate multiple handlers for the same path, allowing different handlers for different HTTP verbs.
* <p>
* Used in SDK to provide identical path-matching functionality as OpenSearch, with Extension-based classes.
*/
final class SDKMethodHandlers {

private final String path;
private final Map<Method, ExtensionRestHandler> methodHandlers;

SDKMethodHandlers(String path, ExtensionRestHandler handler, Method... methods) {
this.path = path;
this.methodHandlers = new HashMap<>(methods.length);
for (Method method : methods) {
methodHandlers.put(method, handler);
}
}

/**
* Add a handler for an additional array of methods. Note that {@code SDKMethodHandlers}
* does not allow replacing the handler for an already existing method.
*/
SDKMethodHandlers addMethods(ExtensionRestHandler handler, Method... methods) {
for (Method method : methods) {
ExtensionRestHandler existing = methodHandlers.putIfAbsent(method, handler);
if (existing != null) {
throw new IllegalArgumentException("Cannot replace existing handler for [" + path + "] for method: " + method);
}
}
return this;
}

/**
* Returns the handler for the given method or {@code null} if none exists.
*/
@Nullable
ExtensionRestHandler getHandler(Method method) {
return methodHandlers.get(method);
}

/**
* Return a set of all valid HTTP methods for the particular path
*/
Set<Method> getValidMethods() {
return methodHandlers.keySet();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.opensearch.rest.RestHandler.Route;
import org.opensearch.rest.RestRequest;
import org.opensearch.rest.RestRequest.Method;
import org.opensearch.sdk.rest.ExtensionRestPathRegistry;
import org.opensearch.test.OpenSearchTestCase;

public class TestExtensionRestPathRegistry extends OpenSearchTestCase {
Expand Down Expand Up @@ -73,10 +74,10 @@ public void setUp() throws Exception {
public void testRegisterConflicts() {
// Can't register same exact name
assertThrows(IllegalArgumentException.class, () -> extensionRestPathRegistry.registerHandler(Method.GET, "/foo", fooHandler));
// Can't register conflicting named wildcards
// Can't register conflicting named wildcards, even if method is different
assertThrows(
IllegalArgumentException.class,
() -> extensionRestPathRegistry.registerHandler(Method.PUT, "/bar/{none}", barHandler)
() -> extensionRestPathRegistry.registerHandler(Method.GET, "/bar/{none}", barHandler)
);
}

Expand Down
1 change: 1 addition & 0 deletions src/test/java/org/opensearch/sdk/TestExtensionsRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import org.opensearch.sdk.handlers.EnvironmentSettingsResponseHandler;
import org.opensearch.sdk.handlers.ExtensionsInitRequestHandler;
import org.opensearch.sdk.handlers.ExtensionsRestRequestHandler;
import org.opensearch.sdk.rest.ExtensionRestPathRegistry;
import org.opensearch.sdk.handlers.AcknowledgedResponseHandler;
import org.opensearch.test.OpenSearchTestCase;
import org.opensearch.transport.Transport;
Expand Down

0 comments on commit 94618e0

Please sign in to comment.