io.convergence_platform.services.infrastructure.InfrastructureDiscoveryHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of service-lib Show documentation
Show all versions of service-lib Show documentation
Holds the common functionality needed by all Convergence Platform-based services written in Java.
The newest version!
package io.convergence_platform.services.infrastructure;
import io.convergence_platform.common.annotations.ConvergenceEndpointInfo;
import io.convergence_platform.common.annotations.HideFromApiGateway;
import io.convergence_platform.services.dto.ConvergenceEndpointRateLimitPolicy;
import io.convergence_platform.services.dto.ServiceEndpointDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Pattern;
@Component
public class InfrastructureDiscoveryHelper {
private static Map intervalUnits = null;
static {
intervalUnits = new HashMap<>();
intervalUnits.put("s", 1);
intervalUnits.put("m", 60);
intervalUnits.put("h", 3600);
}
@Autowired
private RequestMappingHandlerMapping mapper;
@Value("${application.convergence_core_service_url}")
private String discoveryServerUrl;
public List loadServiceExposedURLs() {
Map urls = mapper.getHandlerMethods();
List endpoints = new ArrayList<>();
for (RequestMappingInfo url : urls.keySet()) {
HandlerMethod method = urls.get(url);
if (method.getBeanType().getPackageName().startsWith("org.springframework.")) {
continue;
}
Method methodInfo = method.getMethod();
HideFromApiGateway externalAnnotation = methodInfo.getAnnotation(HideFromApiGateway.class);
ConvergenceEndpointInfo epInfoAnnotation = methodInfo.getAnnotation(ConvergenceEndpointInfo.class);
PreAuthorize authorizationAnnotation = methodInfo.getAnnotation(PreAuthorize.class);
Set methods = url.getMethodsCondition().getMethods();
List patterns = getMappingPatterns(url);
for (String pattern : patterns) {
for (RequestMethod requestMethod : methods) {
ServiceEndpointDTO ep = new ServiceEndpointDTO();
ep.setUrl(pattern);
ep.setMethod(requestMethod.name().toUpperCase());
ep.setExposedThroughGateway(externalAnnotation == null);
String authExpression = "@acl.allowAll()";
if (authorizationAnnotation != null) {
authExpression = authorizationAnnotation.value();
}
if (authExpression.equals("@acl.allowAll()")) {
ep.setExpectedAuthorization("@allow_all");
} else if (authExpression.equals("@acl.isSignedIn()")) {
ep.setExpectedAuthorization("@signed_in");
} else if (authExpression.equals("@acl.notSignedIn()")) {
ep.setExpectedAuthorization("@not_signed_in");
} else if (authExpression.equals("@acl.isService()")) {
ep.setExpectedAuthorization("@service_call");
} else {
String authority = authExpression.substring("@acl.hasAuthority(".length() + 1);
authority = authority.substring(0, authority.length() - 2);
if (authority.contains("(")) {
ep.setExpectedAuthorization("");
} else {
ep.setExpectedAuthorization(authority);
}
}
if (epInfoAnnotation == null) {
ep.setMaxPayloadSize(parsePayloadSize("200KB"));
ep.setTimeout(parseTimeout("10s"));
ep.setMaintenanceMode("restrict");
ep.setRateLimitingPolicy(List.of());
ep.setAccepts(new String[]{"application/json"});
} else {
ep.setMaxPayloadSize(parsePayloadSize(epInfoAnnotation.maxPayloadSize()));
ep.setTimeout(parseTimeout(epInfoAnnotation.timeout()));
ep.setMaintenanceMode(validateMaintenanceMode(epInfoAnnotation.maintenanceMode()));
ep.setRateLimitingPolicy(parseRateLimitingPolicies(epInfoAnnotation.rateLimitingPolicies()));
ep.setAccepts(epInfoAnnotation.accepts());
}
endpoints.add(ep);
}
}
}
return endpoints;
}
private List parseRateLimitingPolicies(String[] policies) {
if (policies == null) {
return List.of();
}
List result = new ArrayList<>();
for (int i = 0; i < policies.length; i++) {
String p = policies[i];
String[] parts = p.split(Pattern.quote(":"));
if (parts.length != 3) {
throw new RuntimeException(String.format("The value %s is not a valid rate limiting policy.", p));
}
if (!Objects.equals(parts[0], "max_globally") &&
!Objects.equals(parts[0], "max_per_session") &&
!Objects.equals(parts[0], "max_per_ip")) {
throw new RuntimeException(String.format("The value %s is not a valid rate limiting policy.", p));
}
ConvergenceEndpointRateLimitPolicy c = new ConvergenceEndpointRateLimitPolicy();
result.add(c);
c.setPolicy(parts[0]);
c.setCount(Integer.parseInt(parts[1]));
int coeff = 0;
boolean validUnit = false;
for (String unit : intervalUnits.keySet()) {
if (parts[2].endsWith(unit)) {
validUnit = true;
coeff = intervalUnits.get(unit);
break;
}
}
if (!validUnit) {
throw new RuntimeException(String.format("The value %s is not a valid rate limiting policy.", p));
}
int value = Integer.parseInt(parts[2].substring(0, parts[2].length() - 1));
c.setDuration(value * coeff);
}
return result;
}
private String validateMaintenanceMode(String s) {
if (!s.equals("allow") && !s.equals("restrict")) {
throw new RuntimeException(String.format("The value %s is not valid.", s));
}
return s;
}
private int parseTimeout(String s) {
int coeff = 0;
int length = 0;
if (s.endsWith("ms")) {
coeff = 1;
length = 2;
} else if (s.endsWith("s")) {
coeff = 1000;
length = 1;
} else {
throw new RuntimeException(String.format("The value %s is not valid.", s));
}
int value = Integer.parseInt(s.substring(0, s.length() - length));
return value * coeff;
}
private int parsePayloadSize(String s) {
int coeff = 0;
if (s.endsWith("KB")) {
coeff = 1024;
} else if (s.endsWith("MB")) {
coeff = 1024 * 1024;
} else if (s.endsWith("GB")) {
coeff = 1024 * 1024 * 1024;
} else {
throw new RuntimeException(String.format("The value %s is not valid.", s));
}
int value = Integer.parseInt(s.substring(0, s.length() - 2));
return value * coeff;
}
private List getMappingPatterns(RequestMappingInfo url) {
Set result = new HashSet<>();
if (url.getPathPatternsCondition() != null) {
result.addAll(url.getPathPatternsCondition().getPatternValues());
}
result.addAll(url.getDirectPaths());
return result.stream().toList();
}
}