Skip to content
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

Open
wants to merge 37 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
ae01c87
create a method to search routes and listeners by parameter "q"
steniobhz Sep 30, 2024
9e39c83
Fix null pointer in HookHandler
steniobhz Oct 3, 2024
d9f1c76
Fix tests and implement more validations.
steniobhz Oct 9, 2024
4a0b791
Add integration tests for handleListenerSearch
steniobhz Oct 10, 2024
922708c
Add an integration test at ListenerTest
steniobhz Oct 11, 2024
2f712c0
Fix return method
steniobhz Oct 11, 2024
a0161a2
Added test for hookHandleSearch to verify behavior when no matching l…
steniobhz Oct 11, 2024
322508f
Add tests for hookHandleSearch with no matching listeners and no list…
steniobhz Oct 11, 2024
55ab41b
Implemented a search mechanism that iterates over the provided reposi…
steniobhz Oct 11, 2024
8feb386
Fix error in mock tests
steniobhz Oct 16, 2024
4004646
- add tests for Route
steniobhz Oct 16, 2024
64e6905
Update README_hook.md
steniobhz Oct 17, 2024
6aeec5c
add validation to return 400 instead 404 search parameter != "q" or null
steniobhz Oct 17, 2024
4f7f4ff
add testes to check if parameter is valid
steniobhz Oct 17, 2024
777b906
Fix RouteListingTest and added more validations.
steniobhz Oct 21, 2024
c392df5
Fix README_hook.md
steniobhz Oct 21, 2024
19bc63d
Recreate and fix tests
steniobhz Oct 22, 2024
13b99c2
Fix Url for listeners search
steniobhz Oct 22, 2024
ad49bda
Add test with more listeners to check if search works as expected
steniobhz Oct 22, 2024
8a2a7cf
Improve tests
steniobhz Oct 22, 2024
ac9c720
Improve unit tests
steniobhz Oct 22, 2024
3609204
improve test url as suggested
steniobhz Oct 22, 2024
76adc34
move integration testes to the right project
steniobhz Oct 24, 2024
8096031
improve integration tests
steniobhz Oct 28, 2024
775704d
Improve and optimize the code
steniobhz Oct 28, 2024
97cbb6e
Create new unit tests
steniobhz Oct 28, 2024
db98244
improve and implement new unit testes to cover new hookHandlerSearch
steniobhz Oct 29, 2024
f921c3b
improve the implementation and remove unused methods
steniobhz Oct 30, 2024
0f1c5e7
improve code
steniobhz Oct 31, 2024
8e3d799
Add integration tests to compare results between current routes searc…
steniobhz Nov 4, 2024
4a4fbff
Added validations for route and listener search using parameters
steniobhz Nov 13, 2024
27f561f
Add validation to check if is valid parameters for search request
steniobhz Nov 14, 2024
044ca92
Move specific validations
steniobhz Nov 14, 2024
9956eba
improve code
steniobhz Nov 14, 2024
4fb6453
Fix comments
steniobhz Nov 14, 2024
12f4d78
optimize testes creating reusable functions
steniobhz Nov 14, 2024
d7272ec
Fix testHandleGETRequestWithTrailingSlash
steniobhz Nov 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions gateleen-hook/README_hook.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,40 @@ 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.
steniobhz marked this conversation as resolved.
Show resolved Hide resolved

### 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
steniobhz marked this conversation as resolved.
Show resolved Hide resolved
```

The response will contain the matching listeners. If no match is found, an empty list is returned:

**Example response with matches:**
```json
{
"listeners": [
"first+playground+server+test+nemo+origin+b"
]
}
```

**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
Expand Up @@ -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;

Expand All @@ -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";
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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");
steniobhz marked this conversation as resolved.
Show resolved Hide resolved
// 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
*/
Expand All @@ -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()));
steniobhz marked this conversation as resolved.
Show resolved Hide resolved
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
Expand Down
Loading
Loading