Skip to content

Commit

Permalink
fixes #2247 create router-config module to share with light-lambda-na…
Browse files Browse the repository at this point in the history
…tive (#2248)
  • Loading branch information
stevehu authored May 17, 2024
1 parent b63abf5 commit 39acee5
Show file tree
Hide file tree
Showing 32 changed files with 345 additions and 49 deletions.
4 changes: 4 additions & 0 deletions egress-router/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
<groupId>com.networknt</groupId>
<artifactId>token-config</artifactId>
</dependency>
<dependency>
<groupId>com.networknt</groupId>
<artifactId>router-config</artifactId>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
package com.networknt.router.middleware;

import com.networknt.config.Config;
import com.networknt.handler.AuditAttachmentUtil;
import com.networknt.handler.Handler;
import com.networknt.handler.HandlerUtils;
import com.networknt.handler.config.HandlerUtils;
import com.networknt.handler.MiddlewareHandler;
import com.networknt.httpstring.HttpStringConstants;
import com.networknt.utility.Constants;
Expand Down Expand Up @@ -93,12 +94,12 @@ protected void pathPrefixService(HttpServerExchange exchange) throws Exception {
if (serviceEntry != null) {
if (logger.isTraceEnabled())
logger.trace("serviceEntry found and endpoint is set to = '{}@{}'", serviceEntry[0], exchange.getRequestMethod().toString().toLowerCase());
HandlerUtils.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, serviceEntry[0] + "@" + exchange.getRequestMethod().toString().toLowerCase());
AuditAttachmentUtil.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, serviceEntry[0] + "@" + exchange.getRequestMethod().toString().toLowerCase());
} else {
if (logger.isTraceEnabled())
logger.trace("serviceEntry is null and endpoint is set to = '{}@{}'", Constants.UNKOWN_STRING, exchange.getRequestMethod().toString().toLowerCase());
// at this moment, we don't have a way to reliably determine the endpoint.
HandlerUtils.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, Constants.UNKOWN_STRING + "@" + exchange.getRequestMethod().toString().toLowerCase());
AuditAttachmentUtil.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, Constants.UNKOWN_STRING + "@" + exchange.getRequestMethod().toString().toLowerCase());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.networknt.router.middleware;

import com.networknt.config.Config;
import com.networknt.handler.AuditAttachmentUtil;
import com.networknt.handler.Handler;
import com.networknt.handler.HandlerUtils;
import com.networknt.handler.config.HandlerUtils;
import com.networknt.handler.MiddlewareHandler;
import com.networknt.httpstring.AttachmentConstants;
import com.networknt.httpstring.HttpStringConstants;
import com.networknt.utility.Constants;
import com.networknt.utility.ModuleRegistry;
Expand All @@ -15,9 +15,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
* Find service Ids using a combination of path prefix and request method.
*
Expand Down Expand Up @@ -59,12 +56,12 @@ protected void serviceDict(HttpServerExchange exchange) throws Exception {
if (serviceEntry != null) {
if (logger.isTraceEnabled())
logger.trace("serviceEntry found and endpoint is set to = '{}'", serviceEntry[0]);
HandlerUtils.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, serviceEntry[0]);
AuditAttachmentUtil.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, serviceEntry[0]);
} else {
if (logger.isTraceEnabled())
logger.trace("serviceEntry is null and endpoint is set to = '{}@{}'", Constants.UNKOWN_STRING, exchange.getRequestMethod().toString().toLowerCase());
// at this moment, we don't have a way to reliably determine the endpoint.
HandlerUtils.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, Constants.UNKOWN_STRING + "@" + exchange.getRequestMethod().toString().toLowerCase());
AuditAttachmentUtil.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, Constants.UNKOWN_STRING + "@" + exchange.getRequestMethod().toString().toLowerCase());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package com.networknt.handler;
package com.networknt.handler.config;

import com.networknt.httpstring.AttachmentConstants;
import com.networknt.utility.StringUtils;
import io.undertow.server.HttpServerExchange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

public class HandlerUtils {
private static final Logger logger = LoggerFactory.getLogger(HandlerUtils.class);
public static final String DELIMITOR = "@";
public static final String DELIMITER = "@";
protected static final String INTERNAL_KEY_FORMAT = "%s %s";

/**
Expand Down Expand Up @@ -57,7 +53,7 @@ public static String normalisePath(String requestPath) {
}

public static String toInternalKey(String key) {
String[] tokens = StringUtils.trimToEmpty(key).split(DELIMITOR);
String[] tokens = StringUtils.trimToEmpty(key).split(DELIMITER);

if (tokens.length ==2) {
return toInternalKey(tokens[1], tokens[0]);
Expand All @@ -70,24 +66,4 @@ public static String toInternalKey(String key) {
public static String toInternalKey(String method, String path) {
return String.format(INTERNAL_KEY_FORMAT, method, HandlerUtils.normalisePath(path));
}

public static void populateAuditAttachmentField(final HttpServerExchange exchange, String fieldName, String fieldValue) {
Map<String, Object> auditInfo = exchange.getAttachment(AttachmentConstants.AUDIT_INFO);

if(auditInfo == null) {
logger.trace("AuditInfo is null, creating a new one and inserting the key-value pair '{}:{}'", fieldName, fieldValue);
auditInfo = new HashMap<>();
auditInfo.put(fieldName, fieldValue);

} else {
logger.trace("AuditInfo is not null, inserting the key-value pair '{}:{}'", fieldName, fieldValue);

if (auditInfo.containsKey(fieldName))
logger.debug("AuditInfo already contains the field '{}'! Replacing the value '{}' with '{}'.", fieldName, auditInfo.get(fieldName), fieldValue);

auditInfo.put(fieldName, fieldValue);
}
exchange.putAttachment(AttachmentConstants.AUDIT_INFO, auditInfo);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.networknt.handler;

import com.networknt.httpstring.AttachmentConstants;
import io.undertow.server.HttpServerExchange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

public class AuditAttachmentUtil {
private static final Logger logger = LoggerFactory.getLogger(AuditAttachmentUtil.class);

public static void populateAuditAttachmentField(final HttpServerExchange exchange, String fieldName, String fieldValue) {
Map<String, Object> auditInfo = exchange.getAttachment(AttachmentConstants.AUDIT_INFO);

if(auditInfo == null) {
logger.trace("AuditInfo is null, creating a new one and inserting the key-value pair '{}:{}'", fieldName, fieldValue);
auditInfo = new HashMap<>();
auditInfo.put(fieldName, fieldValue);

} else {
logger.trace("AuditInfo is not null, inserting the key-value pair '{}:{}'", fieldName, fieldValue);

if (auditInfo.containsKey(fieldName))
logger.debug("AuditInfo already contains the field '{}'! Replacing the value '{}' with '{}'.", fieldName, auditInfo.get(fieldName), fieldValue);

auditInfo.put(fieldName, fieldValue);
}
exchange.putAttachment(AttachmentConstants.AUDIT_INFO, auditInfo);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
import com.networknt.client.Http2Client;
import com.networknt.client.ssl.TLSConfig;
import com.networknt.config.Config;
import com.networknt.handler.BuffersUtils;
import com.networknt.handler.Handler;
import com.networknt.handler.HandlerUtils;
import com.networknt.handler.MiddlewareHandler;
import com.networknt.handler.*;
import com.networknt.handler.config.UrlRewriteRule;
import com.networknt.httpstring.AttachmentConstants;
import com.networknt.metrics.AbstractMetricsHandler;
Expand Down Expand Up @@ -119,7 +116,7 @@ public void handleRequest(HttpServerExchange exchange) throws Exception {
requestPath = exchange.getRequestPath();
}

HandlerUtils.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, endpoint);
AuditAttachmentUtil.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, endpoint);
String method = exchange.getRequestMethod().toString();
String requestHost = parts[1];
String queryString = exchange.getQueryString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@
import com.networknt.config.Config;
import com.networknt.config.JsonMapper;
import com.networknt.config.TlsUtil;
import com.networknt.handler.AuditAttachmentUtil;
import com.networknt.handler.Handler;
import com.networknt.handler.HandlerUtils;
import com.networknt.handler.MiddlewareHandler;
import com.networknt.handler.config.UrlRewriteRule;
import com.networknt.httpstring.AttachmentConstants;
import com.networknt.common.ContentType;
import com.networknt.metrics.MetricsConfig;
import com.networknt.metrics.AbstractMetricsHandler;
import com.networknt.monad.Failure;
import com.networknt.monad.Result;
Expand Down Expand Up @@ -177,7 +176,7 @@ public void handleRequest(HttpServerExchange exchange) throws Exception {
}

// Audit log the endpoint info
HandlerUtils.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, endpoint);
AuditAttachmentUtil.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, endpoint);

invokeApi(exchange, (String)config.getAccessToken().get(config.SERVICE_HOST), requestPath, "Bearer " + accessToken, startTime, endpoint);
if(logger.isDebugEnabled()) logger.debug("MrasHandler.handleRequest ends.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
import com.networknt.config.Config;
import com.networknt.config.JsonMapper;
import com.networknt.config.TlsUtil;
import com.networknt.handler.AuditAttachmentUtil;
import com.networknt.handler.Handler;
import com.networknt.handler.HandlerUtils;
import com.networknt.handler.MiddlewareHandler;
import com.networknt.handler.config.UrlRewriteRule;
import com.networknt.httpstring.AttachmentConstants;
import com.networknt.metrics.MetricsConfig;
import com.networknt.metrics.AbstractMetricsHandler;
import com.networknt.monad.Failure;
import com.networknt.monad.Result;
Expand Down Expand Up @@ -377,7 +376,7 @@ private void invokeApi(HttpServerExchange exchange, String authorization, String
HttpRequest request = null;

// Audit log the endpoint info
HandlerUtils.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, endpoint);
AuditAttachmentUtil.populateAuditAttachmentField(exchange, Constants.ENDPOINT_STRING, endpoint);

if(method.equalsIgnoreCase("GET")) {
request = HttpRequest.newBuilder()
Expand Down
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@
<module>logger-handler</module>
<module>http-entity</module>
<module>token-config</module>
<module>router-config</module>
<module>egress-router</module>
<module>ingress-proxy</module>
<module>ruleloader-config</module>
Expand Down Expand Up @@ -501,6 +502,11 @@
<artifactId>token-config</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.networknt</groupId>
<artifactId>router-config</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.networknt</groupId>
<artifactId>egress-router</artifactId>
Expand Down
56 changes: 56 additions & 0 deletions router-config/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>light-4j</artifactId>
<groupId>com.networknt</groupId>
<version>2.1.34-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>router-config</artifactId>
<packaging>jar</packaging>
<description>A config module for egress-router shared with light-lambda-native.</description>

<dependencies>
<dependency>
<groupId>com.networknt</groupId>
<artifactId>config</artifactId>
</dependency>
<dependency>
<groupId>com.networknt</groupId>
<artifactId>utility</artifactId>
</dependency>
<dependency>
<groupId>com.networknt</groupId>
<artifactId>handler-config</artifactId>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>

<dependency>
<groupId>com.networknt</groupId>
<artifactId>service</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.networknt.router.middleware;

import com.networknt.config.Config;
import com.networknt.handler.HandlerUtils;
import com.networknt.handler.config.HandlerUtils;
import com.networknt.utility.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down
80 changes: 80 additions & 0 deletions router-config/src/test/resources/config/router.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
# Light Router Configuration
# As this router is built to support discovery and security for light-4j services,
# the outbound connection is always HTTP 2.0 with TLS enabled.
# If HTTP 2.0 protocol will be accepted from incoming request.
http2Enabled: false

# If TLS is enabled when accepting incoming request. Should be true on test and prod.
httpsEnabled: true

# Max request time in milliseconds before timeout to the server.
maxRequestTime: 1000

# If a particular downstream service has different timeout than the above global definition, you can
# add the path prefix and give it another timeout in millisecond. For downstream APIs not defined here,
# they will use the global timeout defined in router.maxRequestTime.
pathPrefixMaxRequestTime: ${router.pathPrefixMaxRequestTime:}

# Connections per thread.
connectionsPerThread: 10

# The max queue size for the requests if there is no connection to the downstream API in the connection pool.
# The default value is 0 that means there is queued requests. As we have maxConnectionRetries, there is no
# need to use the request queue to increase the memory usage. It should only be used when you see 503 errors
# in the log after maxConnectionRetries to accommodate slow backend API.
maxQueueSize: ${router.maxQueueSize:0}

# Soft max connections per thread.
softMaxConnectionsPerThread: 5

# Rewrite Host Header with the target host and port and write X_FORWARDED_HOST with original host
rewriteHostHeader: true

# Reuse XForwarded for the target XForwarded header
reuseXForwarded: false

# Max Connection Retries
maxConnectionRetries: 3

# allowed host list. Use Regex to do wildcard match
hostWhitelist: ${router.hostWhitelist:}

# support serviceId in the query parameter for routing to overwrite serviceId in header routing.
# by default, it is false and should not be used unless you are dealing with a legacy client that
# does not support header manipulation. Once this flag is true, we are going to overwrite the header
# service_id derived with other handlers from prefix, path, endpoint etc.
serviceIdQueryParameter: ${router.serviceIdQueryParameter:false}

# URL rewrite rules, each line will have two parts: the regex patten and replace string separated
# with a space. The light-router has service discovery for host routing, so whe working on the
# url rewrite rules, we only need to create about the path in the URL.
# Test your rules at https://www.freeformatter.com/java-regex-tester.html
urlRewriteRules: ${router.urlRewriteRules:}

# Method rewrite rules for legacy clients that do not support DELETE, PUT, and PATCH HTTP methods to
# send a request with GET and POST instead. The gateway will rewrite the method from GET to DELETE or
# from POST to PUT or PATCH. This will be set up at the endpoint level to limit the application.
# The format of the rule will be "endpoint-pattern source-method target-method". Please refer to test
# values.yml for examples. The endpoint-pattern is a pattern in OpenAPI specification. The following is
# a list of examples:
# /v1/pets/{petId} PATCH POST
# /v1/pets PUT POST
# Note: you cannot rewrite a method with a body to a method without a body or vice versa.
methodRewriteRules: ${router.methodRewriteRules:}

# Query parameter rewrite rules for client applications that send different query parameter keys or values
# than the target server expecting. When overwriting a value, the key must be specified in order to
# identify the right query parameter. If only the ok and nk are specified, the router will rewrite the
# query parameter key ok with different key nk and keep the value.
# The format of the rule will be a map with the path as the key. Please refer to test values.yml for
# examples.
queryParamRewriteRules: ${router.queryParamRewriteRules:}

# Header rewrite rules for client applications that send different header keys or values than the target
# server expecting. When overwriting a value, the key must be specified in order to identify the right
# header. If only the ok and nk are specified, the router will rewrite the header key ok with different
# key nk and keep the value.
# The format of the rule will be a map with the path as the key. Please refer to test values.yml for
# examples.
headerRewriteRules: ${router.headerRewriteRules:}
Loading

0 comments on commit 39acee5

Please sign in to comment.