Skip to content
This repository has been archived by the owner on Dec 1, 2024. It is now read-only.

Commit

Permalink
find service Ids using request path and request method - #29 (#45)
Browse files Browse the repository at this point in the history
  • Loading branch information
dz-1 authored and stevehu committed Apr 11, 2019
1 parent 66ea367 commit 6b36c30
Show file tree
Hide file tree
Showing 8 changed files with 498 additions and 232 deletions.
38 changes: 38 additions & 0 deletions src/main/java/com/networknt/router/middleware/HandlerUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.networknt.router.middleware;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

/**
* Looks up the appropriate serviceId for a given requestPath taken directly from exchange.
* Returns null if the path does not map to a configured service.
*/
public static String findServiceId(String searchKey, Map<String, String> mapping) {
if(logger.isDebugEnabled()) logger.debug("findServiceId for " + searchKey);
String serviceId = null;

for (Map.Entry<String, String> entry : mapping.entrySet()) {
String prefix = entry.getKey();
if(searchKey.startsWith(prefix)) {
if((searchKey.length() == prefix.length() || searchKey.charAt(prefix.length()) == '/')) {
serviceId = entry.getValue();
break;
}
}
}
if(logger.isDebugEnabled()) logger.debug("serviceId = " + serviceId);
return serviceId;
}

public static String normalisePath(String requestPath) {
if(!requestPath.startsWith("/")) {
return "/" + requestPath;
}
return requestPath;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
*
* @author <a href="mailto:[email protected]">Logi Ragnarsson</a>
* @author Steve Hu
* @deprecated Please use {@link ServiceDictHandler}
*/
public class PathPrefixServiceHandler implements MiddlewareHandler {
public static final String CONFIG_NAME = "pathPrefixService";
Expand All @@ -70,7 +71,7 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception {
String serviceId = serviceIdHeader != null ? serviceIdHeader.peekFirst() : null;
if(serviceId == null) {
String requestPath = exchange.getRequestURI();
serviceId = findServiceId(requestPath);
serviceId = HandlerUtils.findServiceId(HandlerUtils.normalisePath(requestPath), mapping);
if(serviceId == null) {
setExchangeStatus(exchange, STATUS_INVALID_REQUEST_PATH, requestPath);
return;
Expand All @@ -80,35 +81,6 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception {
Handler.next(exchange, next);
}

/**
* Looks up the appropriate serviceId for a given requestPath taken directly from exchange.
* Returns null if the path does not map to a configured service.
*/
String findServiceId(String requestPath) {
requestPath = normalisePath(requestPath);
if(logger.isDebugEnabled()) logger.debug("findServiceId for " + requestPath);
String serviceId = null;

for (Map.Entry<String, String> entry : mapping.entrySet()) {
String prefix = entry.getKey();
if(requestPath.startsWith(prefix)) {
if((requestPath.length() == prefix.length() || requestPath.charAt(prefix.length()) == '/')) {
serviceId = entry.getValue();
break;
}
}
}
if(logger.isDebugEnabled()) logger.debug("serviceId = " + serviceId);
return serviceId;
}

private static String normalisePath(String requestPath) {
if(!requestPath.startsWith("/")) {
return "/" + requestPath;
}
return requestPath;
}

@Override
public HttpHandler getNext() {
return next;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
* of each request is saved into auditInfo object which is attached to the exchange for auditing.
*
* @author Steve Hu
*
* @deprecated Please use {@link ServiceDictHandler}
*/
public class PathServiceHandler implements MiddlewareHandler {
public static final String CONFIG_NAME = "pathService";
Expand Down
119 changes: 119 additions & 0 deletions src/main/java/com/networknt/router/middleware/ServiceDictHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package com.networknt.router.middleware;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.networknt.config.Config;
import com.networknt.handler.Handler;
import com.networknt.handler.MiddlewareHandler;
import com.networknt.httpstring.HttpStringConstants;
import com.networknt.utility.ModuleRegistry;
import com.networknt.utility.StringUtils;

import io.undertow.Handlers;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HeaderValues;

/**
* Find service Ids using a combination of path prefix and request method.
*
* @author Daniel Zhao
*
*/

@SuppressWarnings("unchecked")
public class ServiceDictHandler implements MiddlewareHandler {
private static final Logger logger = LoggerFactory.getLogger(ServiceDictHandler.class);
protected static final String INTERNAL_KEY_FORMAT = "%s %s";

public static final String CONFIG_NAME = "serviceDict";
public static final String ENABLED = "enabled";
public static final String MAPPING = "mapping";
public static final String DELIMITOR = "@";

public static Map<String, Object> config = Config.getInstance().getJsonMapConfigNoCache(CONFIG_NAME);
protected static Map<String, String> rawMappings = (Map<String, String>)config.get(MAPPING);
public static Map<String, String> mappings;

static {
mappings = new HashMap<>();

for (Map.Entry<String, String> entry : rawMappings.entrySet()) {
mappings.put(toInternalKey(entry.getKey()), entry.getValue());
}

mappings = Collections.unmodifiableMap(mappings);
}


private volatile HttpHandler next;

static final String STATUS_INVALID_REQUEST_PATH = "ERR10007";

public ServiceDictHandler() {
logger.info("ServiceDictHandler is constructed");
}

@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
HeaderValues serviceIdHeader = exchange.getRequestHeaders().get(HttpStringConstants.SERVICE_ID);
String serviceId = serviceIdHeader != null ? serviceIdHeader.peekFirst() : null;
if(serviceId == null) {
String requestPath = exchange.getRequestURI();
String httpMethod = exchange.getRequestMethod().toString().toLowerCase();

serviceId = HandlerUtils.findServiceId(toInternalKey(httpMethod, requestPath), mappings);
if(serviceId == null) {
setExchangeStatus(exchange, STATUS_INVALID_REQUEST_PATH, requestPath);
return;
}
exchange.getRequestHeaders().put(HttpStringConstants.SERVICE_ID, serviceId);
}
Handler.next(exchange, next);
}

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

if (tokens.length ==2) {
return toInternalKey(tokens[1], tokens[0]);
}

logger.warn("Invalid key {}", key);
return key;
}

protected static String toInternalKey(String method, String path) {
return String.format(INTERNAL_KEY_FORMAT, method, HandlerUtils.normalisePath(path));
}

@Override
public HttpHandler getNext() {
return next;
}

@Override
public MiddlewareHandler setNext(final HttpHandler next) {
Handlers.handlerNotNull(next);
this.next = next;
return this;
}

@Override
public boolean isEnabled() {
Object object = config.get(ENABLED);
return object != null && (Boolean)object;
}

@Override
public void register() {
ModuleRegistry.registerModule(ServiceDictHandler.class.getName(), config, null);
}


}
Loading

0 comments on commit 6b36c30

Please sign in to comment.