Skip to content

Commit

Permalink
feat: use json_path to analyze body param (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
chuntaojun committed Jun 19, 2023
1 parent f1581c4 commit d367bda
Show file tree
Hide file tree
Showing 10 changed files with 298 additions and 41 deletions.
Expand Up @@ -21,15 +21,18 @@
import com.tencent.polaris.api.pojo.ServiceRule;
import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.common.exception.PolarisBlockException;
import com.tencent.polaris.common.parser.QueryParser;
import com.tencent.polaris.common.registry.PolarisOperator;
import com.tencent.polaris.common.registry.PolarisOperatorDelegate;
import com.tencent.polaris.common.router.ObjectParser;
import com.tencent.polaris.common.parser.JavaObjectQueryParser;
import com.tencent.polaris.common.router.RuleHandler;
import com.tencent.polaris.ratelimit.api.rpc.Argument;
import com.tencent.polaris.ratelimit.api.rpc.QuotaResponse;
import com.tencent.polaris.ratelimit.api.rpc.QuotaResultCode;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;

import com.tencent.polaris.specification.api.v1.traffic.manage.RateLimitProto;
import org.apache.dubbo.common.constants.CommonConstants;
Expand All @@ -50,9 +53,12 @@ public class RateLimitFilter extends PolarisOperatorDelegate implements Filter {

private final RuleHandler ruleHandler;

private final QueryParser parser;

public RateLimitFilter() {
LOGGER.info("[POLARIS] init polaris ratelimit");
ruleHandler = new RuleHandler();
parser = QueryParser.load();
}

@Override
Expand Down Expand Up @@ -80,12 +86,8 @@ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcExcept
}
break;
case QUERY:
Object queryValue = ObjectParser
.parseArgumentsByExpression(matchArgument.getKey(), invocation.getArguments());
if (null != queryValue) {
arguments.add(Argument
.buildQuery(matchArgument.getKey(), String.valueOf(queryValue)));
}
Optional<String> queryValue = parser.parse(matchArgument.getKey(), invocation.getArguments());
queryValue.ifPresent(s -> arguments.add(Argument.buildQuery(matchArgument.getKey(), s)));
break;
default:
break;
Expand Down
Expand Up @@ -22,15 +22,10 @@
import com.tencent.polaris.api.pojo.ServiceEventKey.EventType;
import com.tencent.polaris.api.pojo.ServiceRule;
import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.common.parser.QueryParser;
import com.tencent.polaris.common.registry.PolarisOperator;
import com.tencent.polaris.common.registry.PolarisOperators;
import com.tencent.polaris.common.router.ObjectParser;
import com.tencent.polaris.common.router.RuleHandler;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.tencent.polaris.specification.api.v1.traffic.manage.RoutingProto;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.Invocation;
Expand All @@ -42,6 +37,12 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

public class PolarisRouter extends AbstractRouter {

private static final Logger LOGGER = LoggerFactory.getLogger(PolarisRouter.class);
Expand All @@ -50,13 +51,16 @@ public class PolarisRouter extends AbstractRouter {

private final PolarisOperator polarisOperator;

private final QueryParser parser;

public PolarisRouter(URL url) {
super(url);
LOGGER.info("[POLARIS] init service router, url is {}, parameters are {}", url,
url.getParameters());
this.priority = url.getParameter(Constants.PRIORITY_KEY, 0);
routeRuleHandler = new RuleHandler();
polarisOperator = PolarisOperators.INSTANCE.getPolarisOperator(url.getHost(), url.getPort());
parser = QueryParser.load();
}

@Override
Expand Down Expand Up @@ -96,10 +100,8 @@ public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation
} else if (routeLabel.startsWith(RouteArgument.LABEL_KEY_QUERY)) {
String queryName = routeLabel.substring(RouteArgument.LABEL_KEY_QUERY.length());
if (!StringUtils.isBlank(queryName)) {
Object value = ObjectParser.parseArgumentsByExpression(queryName, invocation.getArguments());
if (null != value) {
arguments.add(RouteArgument.buildQuery(queryName, String.valueOf(value)));
}
Optional<String> value = parser.parse(queryName, invocation.getArguments());
value.ifPresent(s -> arguments.add(RouteArgument.buildQuery(queryName, s)));
}
}
}
Expand Down
Expand Up @@ -29,30 +29,34 @@
import com.tencent.polaris.api.pojo.ServiceRule;
import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.common.exception.PolarisBlockException;
import com.tencent.polaris.common.parser.QueryParser;
import com.tencent.polaris.common.registry.PolarisOperator;
import com.tencent.polaris.common.registry.PolarisOperatorDelegate;
import com.tencent.polaris.common.router.ObjectParser;
import com.tencent.polaris.common.router.RuleHandler;
import com.tencent.polaris.ratelimit.api.rpc.Argument;
import com.tencent.polaris.ratelimit.api.rpc.QuotaResponse;
import com.tencent.polaris.ratelimit.api.rpc.QuotaResultCode;
import java.util.HashSet;
import java.util.Set;

import com.tencent.polaris.specification.api.v1.traffic.manage.RateLimitProto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

@Activate(group = Constants.PROVIDER)
public class RateLimitFilter extends PolarisOperatorDelegate implements Filter {

private static final Logger LOGGER = LoggerFactory.getLogger(RateLimitFilter.class);

private final RuleHandler ruleHandler;

private final QueryParser parser;

public RateLimitFilter() {
LOGGER.info("[POLARIS] init polaris ratelimit");
ruleHandler = new RuleHandler();
parser = QueryParser.load();
}

@Override
Expand Down Expand Up @@ -80,12 +84,8 @@ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcExcept
}
break;
case QUERY:
Object queryValue = ObjectParser
.parseArgumentsByExpression(matchArgument.getKey(), invocation.getArguments());
if (null != queryValue) {
arguments.add(Argument
.buildQuery(matchArgument.getKey(), String.valueOf(queryValue)));
}
Optional<String> queryValue = parser.parse(matchArgument.getKey(), invocation.getArguments());
queryValue.ifPresent(value -> arguments.add(Argument.buildQuery(matchArgument.getKey(), value)));
break;
default:
break;
Expand Down
Expand Up @@ -31,13 +31,14 @@
import com.tencent.polaris.api.pojo.ServiceEventKey.EventType;
import com.tencent.polaris.api.pojo.ServiceRule;
import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.common.parser.QueryParser;
import com.tencent.polaris.common.registry.PolarisOperator;
import com.tencent.polaris.common.registry.PolarisOperators;
import com.tencent.polaris.common.router.ObjectParser;
import com.tencent.polaris.common.router.RuleHandler;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import com.tencent.polaris.specification.api.v1.traffic.manage.RoutingProto;
Expand All @@ -56,6 +57,8 @@ public class PolarisRouter implements Router {

private final int priority;

private final QueryParser parser;

public PolarisRouter(URL url) {
super();
LOGGER.info("[POLARIS] init service router, url is {}, parameters are {}", url,
Expand All @@ -64,6 +67,7 @@ public PolarisRouter(URL url) {
this.priority = url.getParameter(Constants.PRIORITY_KEY, 0);
routeRuleHandler = new RuleHandler();
polarisOperator = PolarisOperators.INSTANCE.getPolarisOperator(url.getHost(), url.getPort());
parser = QueryParser.load();
}

@Override
Expand Down Expand Up @@ -108,10 +112,8 @@ public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation
} else if (routeLabel.startsWith(RouteArgument.LABEL_KEY_QUERY)) {
String queryName = routeLabel.substring(RouteArgument.LABEL_KEY_QUERY.length());
if (!StringUtils.isBlank(queryName)) {
Object value = ObjectParser.parseArgumentsByExpression(queryName, invocation.getArguments());
if (null != value) {
arguments.add(RouteArgument.buildQuery(queryName, String.valueOf(value)));
}
Optional<String> value = parser.parse(queryName, invocation.getArguments());
value.ifPresent(v -> arguments.add(RouteArgument.buildQuery(queryName, v)));
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions polaris-adapter-dubbo/pom.xml
Expand Up @@ -22,5 +22,15 @@
<artifactId>slf4j-api</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Expand Up @@ -15,30 +15,39 @@
* specific language governing permissions and limitations under the License.
*/

package com.tencent.polaris.common.router;
package com.tencent.polaris.common.parser;

import com.tencent.polaris.api.utils.StringUtils;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ObjectParser {
public class JavaObjectQueryParser implements QueryParser {

private static final Pattern ARRAY_PATTERN = Pattern.compile("^.+\\[[0-9]+\\]");

private static final Logger LOGGER = LoggerFactory.getLogger(ObjectParser.class);
private static final Logger LOGGER = LoggerFactory.getLogger(JavaObjectQueryParser.class);

private static final String PREFIX_PARAM = "param";

private static final String PREFIX_PARAM_ARRAY = "param[";

public static Object parseArgumentsByExpression(String restKey, Object[] parameters) {
@Override
public String name() {
return "JavaObject";
}


@Override
public Optional<String> parse(String restKey, Object[] parameters) {
int index = -1;
if (restKey.startsWith(PREFIX_PARAM)) {
index = 0;
Expand All @@ -52,11 +61,14 @@ public static Object parseArgumentsByExpression(String restKey, Object[] paramet
LOGGER.warn("invalid object expression for {}", restKey);
}
if (index == -1 || parameters.length <= index) {
return null;
return Optional.empty();
}
Object targetValue = parameters[index];
if (restKey.length() == 0) {
return targetValue;
if (Objects.isNull(targetValue)) {
return Optional.empty();
}
return Optional.ofNullable(Objects.toString(targetValue));
}
// omit the starting dot
restKey = restKey.substring(1);
Expand All @@ -66,10 +78,13 @@ public static Object parseArgumentsByExpression(String restKey, Object[] paramet
if (null == targetValue) {
break;
}
targetValue = ObjectParser.resolveValue(token, targetValue);
targetValue = JavaObjectQueryParser.resolveValue(token, targetValue);
}
}
return targetValue;
if (Objects.isNull(targetValue)) {
return Optional.empty();
}
return Optional.ofNullable(Objects.toString(targetValue));
}

private static Object resolveValue(String path, Object value) {
Expand Down Expand Up @@ -194,4 +209,5 @@ private static Object getObjectByFieldName(Object target, String fieldName) thro
field.setAccessible(true);
return field.get(target);
}

}
@@ -0,0 +1,89 @@
/*
* Tencent is pleased to support the open source community by making Polaris available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package com.tencent.polaris.common.parser;

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;
import shade.polaris.com.google.gson.Gson;

import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;

class JsonPathQueryParser implements QueryParser {

private static final Pattern ARRAY_PATTERN = Pattern.compile("^.+\\[[0-9]+\\]");

private static final String PREFIX_PARAM = "param";

private static final String PREFIX_PARAM_ARRAY = "param[";


@Override
public String name() {
return "JsonPath";
}

@Override
public Optional<String> parse(String query, Object[] parameters) {
if (Objects.isNull(parameters) || parameters.length == 0) {
return Optional.empty();
}
Index index = resolveIndex(query);
if (index.index == -1 || index.index > parameters.length) {
return Optional.empty();
}
String str = new Gson().toJson(parameters[index.index]);
ReadContext ctx = JsonPath.parse(str);
Object value = ctx.read(index.key, Object.class);
if (Objects.isNull(value)) {
return Optional.empty();
}
return Optional.of(Objects.toString(value));
}

private Index resolveIndex(String key) {
if (key.startsWith(PREFIX_PARAM_ARRAY)) {
int endIndex = key.indexOf("]");
String indexStr = key.substring(PREFIX_PARAM_ARRAY.length(), endIndex);
int index = Integer.parseInt(indexStr);
int startIndex = endIndex + 2;
if (!Objects.equals(key.charAt(endIndex+1), '.')) {
startIndex = endIndex + 1;
}
return new Index(index, key.substring(startIndex));
}
if (key.startsWith(PREFIX_PARAM)) {
return new Index(0, key.replace(PREFIX_PARAM + ".", ""));
}
return EMPTY_INDEX;
}

private static final Index EMPTY_INDEX = new Index(-1, "");

private static final class Index {
private final int index;

private final String key;

public Index(int index, String key) {
this.index = index;
this.key = key;
}
}
}

0 comments on commit d367bda

Please sign in to comment.