-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue311 improve hook searching #613
base: develop
Are you sure you want to change the base?
Changes from all commits
ae01c87
9e39c83
d9f1c76
4a0b791
922708c
2f712c0
a0161a2
322508f
55ab41b
8feb386
4004646
64e6905
6aeec5c
4f7f4ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -240,10 +240,43 @@ hookHandler.enableResourceLogging(true); | |
``` | ||
|
||
|
||
## Query-Based Listener and Route Search | ||
|
||
Gateleen allows searching for listeners and routes using the query parameter `q`. This simplifies filtering the registered hooks based on query parameters. | ||
|
||
### Listener Search with `q` | ||
Search for listeners based on a query parameter like this: | ||
|
||
``` | ||
GET http://myserver:7012/gateleen/server/listenertest/_hooks/listeners/listener/1?q=testQuery | ||
``` | ||
|
||
The response will contain the matching listeners. If no match is found, an empty list is returned: | ||
|
||
**Example response with matches:** | ||
```json | ||
{ | ||
"listeners": [ | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The content of searching listeners and routes is not an array of objects (with destination, methods properties) but an array containing a list of names (strings). How did you even get this response? |
||
"destination": "/path/to/destination", | ||
"methods": ["GET", "POST"] | ||
} | ||
] | ||
} | ||
``` | ||
|
||
**Example response with no matches:** | ||
```json | ||
{ | ||
"listeners": [] | ||
} | ||
``` | ||
|
||
### Route Search with `q` | ||
Similarly, you can search for routes using a query parameter: | ||
|
||
``` | ||
GET http://myserver:7012/gateleen/server/listenertest/_hooks/routes?q=testRoute | ||
``` | ||
|
||
The response contains the matching routes, or an empty list if no match is found. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -70,6 +70,7 @@ | |
import java.util.Set; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
import java.util.function.Consumer; | ||
import java.util.function.Function; | ||
import java.util.regex.Pattern; | ||
import java.util.stream.Collectors; | ||
|
||
|
@@ -89,7 +90,6 @@ public class HookHandler implements LoggableResource { | |
public static final String HOOKS_LISTENERS_URI_PART = "/_hooks/listeners/"; | ||
public static final String LISTENER_QUEUE_PREFIX = "listener-hook"; | ||
private static final String X_QUEUE = "x-queue"; | ||
private static final String X_EXPIRE_AFTER = "X-Expire-After"; | ||
private static final String LISTENER_HOOK_TARGET_PATH = "listeners/"; | ||
|
||
public static final String HOOKS_ROUTE_URI_PART = "/_hooks/route"; | ||
|
@@ -123,6 +123,12 @@ public class HookHandler implements LoggableResource { | |
public static final String LISTABLE = "listable"; | ||
public static final String COLLECTION = "collection"; | ||
|
||
private static final String CONTENT_TYPE_JSON = "application/json"; | ||
private static final String LISTENERS_KEY = "listeners"; | ||
private static final String ROUTES_KEY = "routes"; | ||
private static final String CONTENT_TYPE_HEADER = "content-type"; | ||
|
||
|
||
private final Comparator<String> collectionContentComparator; | ||
private static final Logger log = LoggerFactory.getLogger(HookHandler.class); | ||
|
||
|
@@ -541,13 +547,12 @@ public void registerListenerRegistrationHandler(Handler<Void> readyHandler) { | |
public boolean handle(final RoutingContext ctx) { | ||
HttpServerRequest request = ctx.request(); | ||
boolean consumed = false; | ||
|
||
var requestUri = request.uri(); | ||
/* | ||
* 1) Un- / Register Listener / Routes | ||
*/ | ||
var requestMethod = request.method(); | ||
if (requestMethod == PUT) { | ||
var requestUri = request.uri(); | ||
if (requestUri.contains(HOOKS_LISTENERS_URI_PART)) { | ||
handleListenerRegistration(request); | ||
return true; | ||
|
@@ -558,7 +563,6 @@ public boolean handle(final RoutingContext ctx) { | |
} | ||
} | ||
if (requestMethod == DELETE) { | ||
var requestUri = request.uri(); | ||
if (requestUri.contains(HOOKS_LISTENERS_URI_PART)) { | ||
handleListenerUnregistration(request); | ||
return true; | ||
|
@@ -569,6 +573,27 @@ public boolean handle(final RoutingContext ctx) { | |
} | ||
} | ||
|
||
// 1. Check if the request method is GET | ||
if (request.method() == HttpMethod.GET) { | ||
String queryParam = request.getParam("q"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using any other query params than |
||
// If the 'q' parameter exists, proceed with search handling | ||
if (queryParam != null) { | ||
// Check if the URI corresponds to listeners or routes | ||
if (requestUri.contains(LISTENERS_KEY)) { | ||
handleListenerSearch(queryParam, request.response()); | ||
return true; | ||
} else if (requestUri.contains(ROUTES_KEY)) { | ||
handleRouteSearch(queryParam, request.response()); | ||
return true; | ||
} | ||
}else{ | ||
if (!request.params().isEmpty()) { | ||
request.response().setStatusCode(400).end("Bad Request: Only the 'q' parameter is allowed"); | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
/* | ||
* 2) Check if we have to queue a request for listeners | ||
*/ | ||
|
@@ -592,6 +617,66 @@ public boolean handle(final RoutingContext ctx) { | |
} | ||
} | ||
|
||
private void handleListenerSearch(String queryParam, HttpServerResponse response) { | ||
handleSearch( | ||
listenerRepository.getListeners().stream().collect(Collectors.toMap(Listener::getListenerId, listener -> listener)), | ||
listener -> listener.getHook().getDestination(), | ||
queryParam, | ||
LISTENERS_KEY, | ||
response | ||
); | ||
} | ||
|
||
private void handleRouteSearch(String queryParam, HttpServerResponse response) { | ||
handleSearch( | ||
routeRepository.getRoutes(), | ||
route -> route.getHook().getDestination(), | ||
queryParam, | ||
ROUTES_KEY, | ||
response | ||
); | ||
} | ||
|
||
/** | ||
* Search the repository for items matching the query parameter. | ||
* Returns a JSON response with the matched results. | ||
* If any essential parameter (repository, response, getDestination) is null, | ||
* a 400 Bad Request is returned. | ||
* | ||
* @param repository The items to search. | ||
* @param getDestination Function to extract destinations. | ||
* @param queryParam The query string to match. | ||
* @param resultKey The key for the result in the response. | ||
* @param response The HTTP response to return the results. Must not be null. | ||
*/ | ||
private <T> void handleSearch(Map<String, T> repository, Function<T, String> getDestination, String queryParam, String resultKey, HttpServerResponse response) { | ||
|
||
if (repository == null || getDestination == null || resultKey == null || queryParam.isEmpty()) { | ||
response.setStatusCode(400).end("Bad Request: One or more required parameters are missing or null"); | ||
return; | ||
} | ||
|
||
JsonArray matchingResults = new JsonArray(); | ||
|
||
repository.forEach((key, value) -> { | ||
String destination = getDestination.apply(value); | ||
if (destination != null && destination.contains(queryParam)) { | ||
matchingResults.add(key); | ||
} | ||
}); | ||
|
||
JsonObject result = new JsonObject(); | ||
result.put(resultKey, matchingResults); | ||
|
||
String encodedResult = result.encode(); | ||
|
||
response.putHeader(CONTENT_TYPE_HEADER, CONTENT_TYPE_JSON); | ||
response.putHeader("Content-Length", String.valueOf(encodedResult.length())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The two lines are not needed:
use |
||
response.write(encodedResult); | ||
response.end(); | ||
} | ||
|
||
|
||
/** | ||
* Create a listing of routes in the given parent. This happens | ||
* only if we have a GET request, the routes are listable and | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not how listener hooks are searched. The URL does not contain the listener-ID.