Skip to content

Commit

Permalink
[ISSUE #4834] Add protocol exclusive fields filter for `/v2/configura…
Browse files Browse the repository at this point in the history
…tion` endpoint (#4835)

* Extract commonConfiguration out of subclasses

* Add configs param

* Unify return position

* Catch more exceptions
  • Loading branch information
Pil0tXia committed Apr 29, 2024
1 parent 86e113f commit 70f9892
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public static <T> T mapToObject(Map<String, Object> map, Class<T> beanClass) {
return null;
}
Object obj = OBJECT_MAPPER.convertValue(map, beanClass);
return (T) obj;
return beanClass.cast(obj);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
import com.alibaba.fastjson2.JSONWriter;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Data
public abstract class AbstractHttpHandler implements HttpHandler {

Expand Down Expand Up @@ -83,6 +85,12 @@ protected void writeUnauthorized(ChannelHandlerContext ctx, String message) {
writeJson(ctx, json, HttpResponseStatus.UNAUTHORIZED);
}

protected void writeInternalServerError(ChannelHandlerContext ctx, String message) {
Result<String> result = new Result<>(message);
String json = JSON.toJSONString(result, JSONWriter.Feature.WriteNulls);
writeJson(ctx, json, HttpResponseStatus.INTERNAL_SERVER_ERROR);
}

/**
* Use {@link HttpResponseUtils#buildHttpResponse} to build {@link HttpResponse} param.
*/
Expand All @@ -92,25 +100,36 @@ protected void write(ChannelHandlerContext ctx, HttpResponse response) {

@Override
public void handle(HttpRequest httpRequest, ChannelHandlerContext ctx) throws Exception {
switch (HttpMethod.valueOf(httpRequest.method().name())) {
case OPTIONS:
preflight(ctx);
break;
case GET:
get(httpRequest, ctx);
break;
case POST:
post(httpRequest, ctx);
break;
case PUT:
put(httpRequest, ctx);
break;
case DELETE:
delete(httpRequest, ctx);
break;
default:
// do nothing
break;
try {
switch (HttpMethod.valueOf(httpRequest.method().name())) {
case OPTIONS:
preflight(ctx);
break;
case GET:
get(httpRequest, ctx);
break;
case POST:
post(httpRequest, ctx);
break;
case PUT:
put(httpRequest, ctx);
break;
case DELETE:
delete(httpRequest, ctx);
break;
default: // do nothing
}
} catch (RuntimeException e) {
StackTraceElement element = e.getStackTrace()[0];
String className = element.getClassName();
String handlerName = className.substring(className.lastIndexOf(".") + 1);
if (e instanceof IllegalArgumentException) {
log.warn("Admin endpoint {}:{} - {}", handlerName, element.getLineNumber(), e.getMessage());
writeBadRequest(ctx, e.getMessage());
} else {
log.error("Admin endpoint {}:{} - {}", handlerName, element.getLineNumber(), e.getMessage(), e);
writeInternalServerError(ctx, e.getMessage());
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@

public class AdminHandlerManager {

private EventMeshServer eventMeshServer;

private EventMeshTCPServer eventMeshTCPServer;

private EventMeshHTTPServer eventMeshHTTPServer;
Expand All @@ -71,9 +73,10 @@ public class AdminHandlerManager {
private final Map<String, HttpHandler> httpHandlerMap = new ConcurrentHashMap<>();

public AdminHandlerManager(EventMeshServer eventMeshServer) {
this.eventMeshServer = eventMeshServer;
this.eventMeshTCPServer = eventMeshServer.getEventMeshTCPServer();
this.eventMeshGrpcServer = eventMeshServer.getEventMeshGrpcServer();
this.eventMeshHTTPServer = eventMeshServer.getEventMeshHTTPServer();
this.eventMeshTCPServer = eventMeshServer.getEventMeshTCPServer();
this.eventMeshMetaStorage = eventMeshServer.getMetaStorage();
this.adminWebHookConfigOperationManage = eventMeshTCPServer.getAdminWebHookConfigOperationManage();
}
Expand Down Expand Up @@ -112,6 +115,7 @@ public void registerHttpHandler() {

// v2 endpoints
initHandler(new ConfigurationHandler(
eventMeshServer.getConfiguration(),
eventMeshTCPServer.getEventMeshTCPConfiguration(),
eventMeshHTTPServer.getEventMeshHttpConfiguration(),
eventMeshGrpcServer.getEventMeshGrpcConfiguration()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.filter.Filter;
import com.alibaba.fastjson2.filter.NameFilter;
import com.alibaba.fastjson2.filter.PropertyFilter;
import com.alibaba.fastjson2.filter.ValueFilter;

import lombok.extern.slf4j.Slf4j;
Expand All @@ -56,6 +57,7 @@
@EventMeshHttpHandler(path = "/v2/configuration")
public class ConfigurationHandler extends AbstractHttpHandler {

private final CommonConfiguration commonConfiguration;
private final EventMeshTCPConfiguration eventMeshTCPConfiguration;
private final EventMeshHTTPConfiguration eventMeshHTTPConfiguration;
private final EventMeshGrpcConfiguration eventMeshGrpcConfiguration;
Expand All @@ -68,10 +70,12 @@ public class ConfigurationHandler extends AbstractHttpHandler {
* @param eventMeshGrpcConfiguration the gRPC configuration for EventMesh
*/
public ConfigurationHandler(
CommonConfiguration commonConfiguration,
EventMeshTCPConfiguration eventMeshTCPConfiguration,
EventMeshHTTPConfiguration eventMeshHTTPConfiguration,
EventMeshGrpcConfiguration eventMeshGrpcConfiguration) {
super();
this.commonConfiguration = commonConfiguration;
this.eventMeshTCPConfiguration = eventMeshTCPConfiguration;
this.eventMeshHTTPConfiguration = eventMeshHTTPConfiguration;
this.eventMeshGrpcConfiguration = eventMeshGrpcConfiguration;
Expand All @@ -85,34 +89,51 @@ public ConfigurationHandler(
* <p>When {@code properties}, the field names are returned in Properties format;
* <p>When {@code bean}, the field names themselves are used as json keys.
* </li>
* <li>
* {@code configs}: String; Optional, DefaultValue: {@code exclusive}, SelectableValue: {@code all}.
* <p>When {@code exclusive}, protocol-specific configurations will only contain protocol-exclusive fields
* and won't contain any {@link CommonConfiguration} fields;
* <p>When {@code all}, protocol-specific configurations will contain all fields, including those in {@link CommonConfiguration}.
* </li>
* </ul>
*/
@Override
protected void get(HttpRequest httpRequest, ChannelHandlerContext ctx) {
String format = HttpRequestUtil.getQueryParam(httpRequest, "format", "properties");

Filter[] filters;
if (format.equals("properties")) {
filters = new Filter[] {new ConfigFieldFilter(), new IPAddressToStringFilter()};
} else if (format.equals("bean")) {
filters = new Filter[] {new IPAddressToStringFilter()};
} else {
log.warn("Invalid format param: {}", format);
writeBadRequest(ctx, "Invalid format param: " + format);
return;
String configs = HttpRequestUtil.getQueryParam(httpRequest, "configs", "exclusive");

List<Filter> filters = new ArrayList<>();
switch (configs) {
case "exclusive":
filters.add(new SuperClassFieldFilter());
break;
case "all": break;
default:
throw new IllegalArgumentException("Invalid param 'configs': " + configs);
}
switch (format) {
case "properties":
filters.add(new ConfigFieldFilter());
break;
case "bean": break;
default:
throw new IllegalArgumentException("Invalid param 'format': " + format);
}
filters.add(new IPAddressToStringFilter());

GetConfigurationResponse getConfigurationResponse = new GetConfigurationResponse(
commonConfiguration,
eventMeshTCPConfiguration,
eventMeshHTTPConfiguration,
eventMeshGrpcConfiguration
eventMeshGrpcConfiguration,
"v1.10.0-release" // TODO get version number after merging https://github.com/apache/eventmesh/pull/4055
);
String json = JSON.toJSONString(Result.success(getConfigurationResponse), filters);
String json = JSON.toJSONString(Result.success(getConfigurationResponse), filters.toArray(new Filter[0]));
writeJson(ctx, json);
}

/**
* For each member of {@link EventMeshTCPConfiguration}, {@link EventMeshHTTPConfiguration}, and {@link EventMeshGrpcConfiguration},
* For each member of configuration classes,
* the value of the {@link ConfigField} annotation for each field is obtained through reflection,
* and then concatenated with the configuration prefix in the {@link Config} annotation to serve as the JSON key for this field.
* <p>
Expand Down Expand Up @@ -155,6 +176,39 @@ private Field findFieldInClassHierarchy(Class<?> clazz, String fieldName) throws
}
}

/**
* For each member of {@link EventMeshTCPConfiguration}, {@link EventMeshHTTPConfiguration}, and {@link EventMeshGrpcConfiguration},
* if the {@code name} is a member that exists in {@link CommonConfiguration} class, it will be skipped.
*/
static class SuperClassFieldFilter implements PropertyFilter {
@Override
public boolean apply(Object object, String name, Object value) {
try {
Field field = findFieldInClassNonHierarchy(object.getClass(), name);
return field != null;
} catch (NoSuchFieldException e) {
log.error("Failed to get field {} from object {}", name, object, e);
}
return true;
}

/**
* If a field of a subclass exists in the superclass, return null, causing FastJSON to skip this field.
*/
private Field findFieldInClassNonHierarchy(Class<?> clazz, String fieldName) throws NoSuchFieldException {
try {
return clazz.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
Class<?> superclass = clazz.getSuperclass();
if (superclass == null) {
throw e;
} else {
return null;
}
}
}
}

/**
* {@link IPAddress} can't be serialized directly by FastJSON,
* so this filter converts {@link IPAddress} objects to their string representation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package org.apache.eventmesh.runtime.admin.response.v2;

import org.apache.eventmesh.common.config.CommonConfiguration;
import org.apache.eventmesh.runtime.configuration.EventMeshGrpcConfiguration;
import org.apache.eventmesh.runtime.configuration.EventMeshHTTPConfiguration;
import org.apache.eventmesh.runtime.configuration.EventMeshTCPConfiguration;
Expand All @@ -30,7 +31,9 @@
@AllArgsConstructor
public class GetConfigurationResponse {

private CommonConfiguration commonConfiguration;
private EventMeshTCPConfiguration eventMeshTCPConfiguration;
private EventMeshHTTPConfiguration eventMeshHTTPConfiguration;
private EventMeshGrpcConfiguration eventMeshGrpcConfiguration;
private String eventMeshVersion;
}

0 comments on commit 70f9892

Please sign in to comment.