Skip to content

Commit

Permalink
Added validations for route and listener search using parameters
Browse files Browse the repository at this point in the history
Fix route search with parameters
Update readme with more information about search with query parameters
create a hookIdentify to get a requestUrl when search using parameters
Add more unit and integrate testes
improve code implementations
  • Loading branch information
steniobhz committed Nov 13, 2024
1 parent 8e3d799 commit 4a4fbff
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 188 deletions.
24 changes: 21 additions & 3 deletions gateleen-hook/README_hook.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,11 +244,13 @@ hookHandler.enableResourceLogging(true);

Gateleen allows searching for listeners and routes using the query parameter `q`. This simplifies filtering the registered hooks based on query parameters.

The search will be based on the value registered of the destination property

### Listener Search with `q`
Search for listeners based on a query parameter like this:

```
GET http://myserver:7012/playground/server/hooks/v1/registrations/listeners?q=test
GET http://myserver:7012/playground/server/hooks/v1/registrations/listeners?q=mylistener
```

The response will contain the matching listeners. If no match is found, an empty list is returned:
Expand All @@ -257,7 +259,7 @@ The response will contain the matching listeners. If no match is found, an empty
```json
{
"listeners": [
"first+playground+server+test+nemo+origin+b"
"first+playground+server+test+nemo+origin+mylistener"
]
}
```
Expand All @@ -273,7 +275,23 @@ The response will contain the matching listeners. If no match is found, an empty
Similarly, you can search for routes using a query parameter:

```
GET http://myserver:7012/playground/server/hooks/v1/registrations/routes/?q=test
GET http://myserver:7012/playground/server/hooks/v1/registrations/routes/?q=myroute
```

The response contains the matching routes, or an empty list if no match is found.

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

```
**Example response with no matches:**
```json
{
"routes": []
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ public class HookHandler implements LoggableResource {
private final QueueSplitter queueSplitter;
private final String routeBase;
private final String listenerBase;
private final String normalizedRouteBase;
private final String normalizedListenerBase;

/**
* Creates a new HookHandler.
Expand Down Expand Up @@ -293,6 +295,9 @@ public HookHandler(Vertx vertx, HttpClient selfClient, final ResourceStorage use
jsonSchemaHook = JsonSchemaFactory.getInstance().getSchema(hookSchema);
this.listenerBase = hookRootUri + HOOK_LISTENER_STORAGE_PATH;
this.routeBase = hookRootUri + HOOK_ROUTE_STORAGE_PATH;
this.normalizedListenerBase = this.listenerBase.replaceAll("/+$", "");
this.normalizedRouteBase = this.routeBase.replaceAll("/+$", "");

}

public void init() {
Expand Down Expand Up @@ -544,7 +549,7 @@ public void registerListenerRegistrationHandler(Handler<Void> readyHandler) {
public boolean handle(final RoutingContext ctx) {
HttpServerRequest request = ctx.request();
boolean consumed = false;
var requestUri = request.uri();
var requestUri = request.uri().replaceAll("/+$", "");;
/*
* 1) Un- / Register Listener / Routes
*/
Expand Down Expand Up @@ -572,11 +577,15 @@ public boolean handle(final RoutingContext ctx) {

if (requestMethod == GET && !request.params().isEmpty()) {
String queryParam = request.getParam("q");
String normalizedRequestUri = requestUri.replaceAll("/$", "");
if (normalizedRequestUri.contains(listenerBase.replaceAll("/$", ""))) {
if (request.params().size() > 1 || (queryParam == null) || (queryParam.isEmpty())) {
request.response().setStatusCode(StatusCode.BAD_REQUEST.getStatusCode())
.end("Bad Request: Only the 'q' parameter is allowed and can't be empty or null");
return true;
}
if (requestUri.contains(normalizedListenerBase)) {
handleListenerSearch(queryParam, request.response());
return true;
} else if (normalizedRequestUri.contains(routeBase.replaceAll("/$", ""))) {
} else if (requestUri.contains(normalizedRouteBase)) {
handleRouteSearch(queryParam, request.response());
return true;
}
Expand Down Expand Up @@ -617,7 +626,7 @@ private void handleListenerSearch(String queryParam, HttpServerResponse response

private void handleRouteSearch(String queryParam, HttpServerResponse response) {
handleSearch(
routeRepository.getRoutes(),
routeRepository.getRoutes().entrySet().stream().collect(Collectors.toMap(entry -> entry.getValue().getHookIdentify(), Map.Entry::getValue)),
route -> route.getHook().getDestination(),
queryParam,
ROUTES_KEY,
Expand All @@ -637,18 +646,12 @@ private void handleRouteSearch(String queryParam, HttpServerResponse 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 (queryParam == null || queryParam.isEmpty()) {
response.setStatusCode(StatusCode.BAD_REQUEST.getStatusCode()).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);
matchingResults.add(convertToStoragePattern(key));
}
});

Expand Down Expand Up @@ -1490,7 +1493,7 @@ private void registerListener(Buffer buffer) {
target = hook.getDestination();
} else {
String urlPattern = hookRootUri + LISTENER_HOOK_TARGET_PATH + target;
routeRepository.addRoute(urlPattern, createRoute(urlPattern, hook));
routeRepository.addRoute(urlPattern, createRoute(urlPattern, hook, requestUrl));

Check warning on line 1496 in gateleen-hook/src/main/java/org/swisspush/gateleen/hook/HookHandler.java

View check run for this annotation

Codecov / codecov/patch

gateleen-hook/src/main/java/org/swisspush/gateleen/hook/HookHandler.java#L1496

Added line #L1496 was not covered by tests

if (log.isTraceEnabled()) {
log.trace("external target, add route for urlPattern: {}", urlPattern);
Expand Down Expand Up @@ -1672,12 +1675,14 @@ private void registerRoute(Buffer buffer) {
}

boolean mustCreateNewRoute = true;


Route existingRoute = routeRepository.getRoutes().get(routedUrl);
if (existingRoute != null) {
mustCreateNewRoute = mustCreateNewRouteForHook(existingRoute, hook);
}
if (mustCreateNewRoute) {
routeRepository.addRoute(routedUrl, createRoute(routedUrl, hook));
routeRepository.addRoute(routedUrl, createRoute(routedUrl , hook, requestUrl));
} else {
// see comment in #mustCreateNewRouteForHook()
existingRoute.getRule().setHeaderFunction(hook.getHeaderFunction());
Expand All @@ -1686,6 +1691,25 @@ private void registerRoute(Buffer buffer) {
monitoringHandler.updateRoutesCount(routeRepository.getRoutes().size());
}

/**
* Extracts the route name segment from the given request URL after the HOOKS_ROUTE_URI_PART.
* Returns an empty string if there is no route segment to extract.
*
* @param requestUrl the full URL of the request
* @return the extracted route name or an empty string if no route name is present
*/
private String extractRouteName(String requestUrl) {
int startIdx = requestUrl.indexOf(HOOKS_ROUTE_URI_PART);

Check warning on line 1702 in gateleen-hook/src/main/java/org/swisspush/gateleen/hook/HookHandler.java

View check run for this annotation

Codecov / codecov/patch

gateleen-hook/src/main/java/org/swisspush/gateleen/hook/HookHandler.java#L1702

Added line #L1702 was not covered by tests
if (requestUrl.isEmpty() || startIdx == -1) {
return "";

Check warning on line 1704 in gateleen-hook/src/main/java/org/swisspush/gateleen/hook/HookHandler.java

View check run for this annotation

Codecov / codecov/patch

gateleen-hook/src/main/java/org/swisspush/gateleen/hook/HookHandler.java#L1704

Added line #L1704 was not covered by tests
}
startIdx += HOOKS_ROUTE_URI_PART.length();

Check warning on line 1706 in gateleen-hook/src/main/java/org/swisspush/gateleen/hook/HookHandler.java

View check run for this annotation

Codecov / codecov/patch

gateleen-hook/src/main/java/org/swisspush/gateleen/hook/HookHandler.java#L1706

Added line #L1706 was not covered by tests
if (startIdx < requestUrl.length()) {
return requestUrl.substring(startIdx);

Check warning on line 1708 in gateleen-hook/src/main/java/org/swisspush/gateleen/hook/HookHandler.java

View check run for this annotation

Codecov / codecov/patch

gateleen-hook/src/main/java/org/swisspush/gateleen/hook/HookHandler.java#L1708

Added line #L1708 was not covered by tests
}
return "";

Check warning on line 1710 in gateleen-hook/src/main/java/org/swisspush/gateleen/hook/HookHandler.java

View check run for this annotation

Codecov / codecov/patch

gateleen-hook/src/main/java/org/swisspush/gateleen/hook/HookHandler.java#L1710

Added line #L1710 was not covered by tests
}

/**
* check if an existing route must be thrown away because the new Hook does not match the config of the existing Route
*
Expand Down Expand Up @@ -1730,9 +1754,9 @@ private boolean headersFilterPatternEquals(Pattern headersFilterPatternLeft, Pat
* @param hook hook
* @return Route
*/
private Route createRoute(String urlPattern, HttpHook hook) {
private Route createRoute(String urlPattern, HttpHook hook, String hookIdentify) {
return new Route(vertx, userProfileStorage, loggingResourceManager, logAppenderRepository, monitoringHandler,
userProfilePath, hook, urlPattern, selfClient);
userProfilePath, hook, urlPattern, selfClient,hookIdentify);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class Route {
private MonitoringHandler monitoringHandler;
private String userProfilePath;
private ResourceStorage storage;
private String hookIdentify;

private String urlPattern;
private HttpHook httpHook;
Expand Down Expand Up @@ -79,7 +80,7 @@ public class Route {
* @param urlPattern - this can be a listener or a normal urlPattern (eg. for a route)
*/
public Route(Vertx vertx, ResourceStorage storage, LoggingResourceManager loggingResourceManager, LogAppenderRepository logAppenderRepository,
MonitoringHandler monitoringHandler, String userProfilePath, HttpHook httpHook, String urlPattern, HttpClient selfClient) {
MonitoringHandler monitoringHandler, String userProfilePath, HttpHook httpHook, String urlPattern, HttpClient selfClient, String hookIdentify) {
this.vertx = vertx;
this.storage = storage;
this.loggingResourceManager = loggingResourceManager;
Expand All @@ -89,6 +90,7 @@ public Route(Vertx vertx, ResourceStorage storage, LoggingResourceManager loggin
this.httpHook = httpHook;
this.urlPattern = urlPattern;
this.selfClient = selfClient;
this.hookIdentify = hookIdentify;

createRule();

Expand Down Expand Up @@ -273,4 +275,8 @@ public void cleanup() {
public HttpHook getHook() {
return httpHook;
}

public String getHookIdentify() {
return hookIdentify;
}
}
Loading

0 comments on commit 4a4fbff

Please sign in to comment.