diff --git a/fizz-common/src/main/java/we/spring/web/server/ext/FizzServerWebExchangeDecorator.java b/fizz-common/src/main/java/we/spring/web/server/ext/FizzServerWebExchangeDecorator.java index 8146cca..2467161 100644 --- a/fizz-common/src/main/java/we/spring/web/server/ext/FizzServerWebExchangeDecorator.java +++ b/fizz-common/src/main/java/we/spring/web/server/ext/FizzServerWebExchangeDecorator.java @@ -125,26 +125,31 @@ public class FizzServerWebExchangeDecorator extends ServerWebExchangeDecorator { for (Map.Entry> fieldValuesEntry : fieldValuesEntries) { String field = fieldValuesEntry.getKey(); List values = fieldValuesEntry.getValue(); - if (CollectionUtils.isEmpty(values)) { + if (values.isEmpty()) { b.append(URLEncoder.encode(field, Consts.C.UTF8)); } else { int vs = values.size(); for (int i = 0; i < vs; ) { - b.append(URLEncoder.encode(field, Consts.C.UTF8)) - .append('=') - .append(URLEncoder.encode(values.get(i), Consts.C.UTF8)); - if ((++i) != vs) { - b.append('&'); + String v = values.get(i); + b.append(URLEncoder.encode(field, Consts.C.UTF8)); + if (v != null) { + b.append(Consts.S.EQUAL); + if (!Consts.S.EMPTY.equals(v)) { + b.append(URLEncoder.encode(v, Consts.C.UTF8)); } + } + if ((++i) != vs) { + b.append(Consts.S.AND); + } } } if ((++cnt) != fs) { - b.append('&'); + b.append(Consts.S.AND); } } - } catch (UnsupportedEncodingException ex) { - throw new IllegalStateException(ex); + req.setBody(b.toString()); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException(e); } - req.setBody(b.toString()); } } diff --git a/fizz-common/src/main/java/we/util/Consts.java b/fizz-common/src/main/java/we/util/Consts.java index 2c3ed0c..ea76fa4 100644 --- a/fizz-common/src/main/java/we/util/Consts.java +++ b/fizz-common/src/main/java/we/util/Consts.java @@ -53,6 +53,8 @@ public final class Consts { public static final char RIGHT_BRACE = '}'; public static final char SQUARE = '^'; public static final char HASH = '#'; + public static final char AND = '&'; + public static final char OR = '|'; public static final char LF = '\n'; public static final char TAB = '\t'; diff --git a/fizz-core/src/main/java/we/filter/FlowControlFilter.java b/fizz-core/src/main/java/we/filter/FlowControlFilter.java index b678cb0..679725c 100644 --- a/fizz-core/src/main/java/we/filter/FlowControlFilter.java +++ b/fizz-core/src/main/java/we/filter/FlowControlFilter.java @@ -110,7 +110,7 @@ public class FlowControlFilter extends FizzWebFilter { String traceId = WebUtils.getTraceId(exchange); LogService.setBizId(traceId); if (!apiConfigService.serviceConfigMap.containsKey(service)) { - String json = WebUtils.jsonRespBody(HttpStatus.FORBIDDEN.value(), "no service " + service, traceId); + String json = WebUtils.jsonRespBody(HttpStatus.FORBIDDEN.value(), "no service " + service + " in flow config", traceId); return WebUtils.buildJsonDirectResponse(exchange, HttpStatus.FORBIDDEN, null, json); } String app = WebUtils.getAppId(exchange); diff --git a/fizz-core/src/main/java/we/filter/RouteFilter.java b/fizz-core/src/main/java/we/filter/RouteFilter.java index c0e1fa4..cfc985d 100644 --- a/fizz-core/src/main/java/we/filter/RouteFilter.java +++ b/fizz-core/src/main/java/we/filter/RouteFilter.java @@ -28,6 +28,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; +import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.BodyExtractors; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.server.ServerWebExchange; @@ -35,7 +36,6 @@ import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Mono; import we.config.SystemConfig; import we.flume.clients.log4j2appender.LogService; -import we.legacy.RespEntity; import we.plugin.auth.ApiConfig; import we.proxy.FizzWebClient; import we.proxy.Route; @@ -105,7 +105,7 @@ public class RouteFilter extends FizzWebFilter { Route route = exchange.getAttribute(WebUtils.ROUTE); HttpHeaders hdrs = null; - if (route.type != ApiConfig.Type.DUBBO) { + if (route != null && route.type != ApiConfig.Type.DUBBO) { hdrs = WebUtils.mergeAppendHeaders(exchange); } @@ -114,12 +114,12 @@ public class RouteFilter extends FizzWebFilter { return send(exchange, req.getMethod(), WebUtils.getClientService(exchange), pathQuery, hdrs, route); } else if (route.type == ApiConfig.Type.SERVICE_DISCOVERY) { - String pathQuery = route.getBackendPathQuery(); + String pathQuery = getBackendPathQuery(req, route); return send(exchange, route.method, route.backendService, pathQuery, hdrs, route); } else if (route.type == ApiConfig.Type.REVERSE_PROXY) { String uri = ThreadContext.getStringBuilder().append(route.nextHttpHostPort) - .append(route.getBackendPathQuery()) + .append(getBackendPathQuery(req, route)) .toString(); return fizzWebClient.send(traceId, route.method, uri, hdrs, req.getBody(), route.timeout, route.retryCount, route.retryInterval).flatMap(genServerResponse(exchange)); @@ -139,6 +139,20 @@ public class RouteFilter extends FizzWebFilter { } } + private String getBackendPathQuery(ServerHttpRequest request, Route route) { + String qry = route.query; + if (qry == null) { + MultiValueMap queryParams = request.getQueryParams(); + if (queryParams.isEmpty()) { + return route.backendPath; + } else { + return route.backendPath + Consts.S.QUESTION + WebUtils.toQueryString(queryParams); + } + } else { + return route.backendPath + Consts.S.QUESTION + qry; + } + } + private Mono send(ServerWebExchange exchange, HttpMethod method, String service, String relativeUri, HttpHeaders hdrs, Route r) { ServerHttpRequest clientReq = exchange.getRequest(); if (r == null) { diff --git a/fizz-core/src/main/java/we/plugin/auth/ApiConfig.java b/fizz-core/src/main/java/we/plugin/auth/ApiConfig.java index e5f7e1c..9b7c747 100644 --- a/fizz-core/src/main/java/we/plugin/auth/ApiConfig.java +++ b/fizz-core/src/main/java/we/plugin/auth/ApiConfig.java @@ -231,7 +231,7 @@ public class ApiConfig { .method( request.getMethod()) .backendService(this.backendService) .backendPath( this.backendPath) - .query( WebUtils.getClientReqQuery(exchange)) +// .query( WebUtils.getClientReqQuery(exchange)) // .pluginConfigs( this.pluginConfigs) .rpcMethod( this.rpcMethod) .rpcParamTypes( this.rpcParamTypes) diff --git a/fizz-core/src/main/java/we/proxy/Route.java b/fizz-core/src/main/java/we/proxy/Route.java index 6168bc6..7d43b1a 100644 --- a/fizz-core/src/main/java/we/proxy/Route.java +++ b/fizz-core/src/main/java/we/proxy/Route.java @@ -38,10 +38,14 @@ public class Route { public String backendPath; + @Deprecated public String query; public String nextHttpHostPort; + /** + * use pluginConfigs(List pcs) method to update this value. + */ public List pluginConfigs; public boolean pluginConfigsChange = false; @@ -80,6 +84,7 @@ public class Route { return this; } + @Deprecated public Route query(String qry) { query = qry; return this; @@ -131,6 +136,7 @@ public class Route { return this; } + @Deprecated public String getBackendPathQuery() { if (query != null) { return backendPath + Consts.S.QUESTION + query; diff --git a/fizz-core/src/main/java/we/util/WebUtils.java b/fizz-core/src/main/java/we/util/WebUtils.java index 5dc667f..4c101d8 100644 --- a/fizz-core/src/main/java/we/util/WebUtils.java +++ b/fizz-core/src/main/java/we/util/WebUtils.java @@ -27,18 +27,20 @@ import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.lang.Nullable; +import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import we.config.SystemConfig; import we.filter.FilterResult; import we.flume.clients.log4j2appender.LogService; -import we.legacy.RespEntity; import we.plugin.auth.ApiConfig; import we.plugin.auth.AuthPluginFilter; import we.proxy.Route; +import java.io.UnsupportedEncodingException; import java.net.URI; +import java.net.URLEncoder; import java.util.Collections; import java.util.List; import java.util.Map; @@ -84,7 +86,7 @@ public abstract class WebUtils { private static final String app = "app"; - private static final String respbT = "respbT"; +// private static final String respbT = "respbT"; public static final String TRACE_ID = "traid@"; @@ -369,12 +371,14 @@ public abstract class WebUtils { } public static String getClientReqPathQuery(ServerWebExchange exchange) { - String relativeUri = getClientReqPath(exchange); - String qry = getClientReqQuery(exchange); - if (qry != null) { - relativeUri = relativeUri + Consts.S.QUESTION + qry; + String pathQry = getClientReqPath(exchange); +// String qry = getClientReqQuery(exchange); + MultiValueMap queryParams = exchange.getRequest().getQueryParams(); + if (!queryParams.isEmpty()) { + String qry = toQueryString(queryParams); + pathQry = pathQry + Consts.S.QUESTION + qry; } - return relativeUri; + return pathQry; } public static String appendQuery(String path, ServerWebExchange exchange) { @@ -618,7 +622,8 @@ public abstract class WebUtils { } public static String jsonRespBody(int code, @Nullable String msg, @Nullable String traceId, @Nullable Object context) { - StringBuilder b = ThreadContext.getStringBuilder(respbT); +// StringBuilder b = ThreadContext.getStringBuilder(respbT); + StringBuilder b = ThreadContext.getStringBuilder(); b.append(s0).append(SystemConfig.FIZZ_ERR_RESP_CODE_FIELD).append(s1).append(code); if (StringUtils.isNotBlank(msg)) { b.append(s2).append(SystemConfig.FIZZ_ERR_RESP_MSG_FIELD).append(s3).append(msg).append(s4); @@ -632,4 +637,48 @@ public abstract class WebUtils { b.append(s7); return b.toString(); } + + public static String toQueryString(MultiValueMap queryParams) { + StringBuilder b = ThreadContext.getStringBuilder(); + Set>> params = queryParams.entrySet(); + int ps = params.size(), cnt = 0; + try { + for (Map.Entry> param : params) { + String name = param.getKey(); + List values = param.getValue(); + if (values.isEmpty()) { + b.append(URLEncoder.encode(name, Consts.C.UTF8)); + } else { + int vs = values.size(); + for (int i = 0; i < vs; ) { + b.append(URLEncoder.encode(name, Consts.C.UTF8)); + String v = values.get(i); + if (v != null) { + b.append(Consts.S.EQUAL); + if (!Consts.S.EMPTY.equals(v)) { + b.append(URLEncoder.encode(v, Consts.C.UTF8)); + } + } + if ((++i) != vs) { + b.append(Consts.S.AND); + } + } + } + if ((++cnt) != ps) { + b.append(Consts.S.AND); + } + } + return b.toString(); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException(e); + } + } + +// private static String encodeQueryParamComp(String source) { +// try { +// return URLEncoder.encode(source, Consts.C.UTF8); +// } catch (UnsupportedEncodingException e) { +// return URLEncoder.encode(source); +// } +// } } diff --git a/fizz-core/src/test/java/we/util/WebUtilsTests.java b/fizz-core/src/test/java/we/util/WebUtilsTests.java index 40a4204..edbe0c7 100644 --- a/fizz-core/src/test/java/we/util/WebUtilsTests.java +++ b/fizz-core/src/test/java/we/util/WebUtilsTests.java @@ -4,6 +4,13 @@ import com.fasterxml.jackson.core.JsonProcessingException; import org.junit.jupiter.api.Test; import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.web.server.MockServerWebExchange; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -41,4 +48,16 @@ public class WebUtilsTests { clientReqPath = WebUtils.getClientReqPath(mockExchange); assertEquals("/ybiz1", clientReqPath); } + + @Test + void toQueryStringTest() { + MultiValueMap mvm = new LinkedMultiValueMap<>(); + List v0 = Stream.of("", "v0").collect(Collectors.toList()); + v0.add(null); + mvm.put("k0", v0); + List v1 = Stream.of("v1").collect(Collectors.toList()); + mvm.put("k1", v1); + String s = WebUtils.toQueryString(mvm); + assertEquals("k0=&k0=v0&k0&k1=v1", s); + } } diff --git a/fizz-spring-boot-starter/src/main/resources/META-INF/spring.factories b/fizz-spring-boot-starter/src/main/resources/META-INF/spring.factories index cf6374b..9ee2176 100644 --- a/fizz-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ b/fizz-spring-boot-starter/src/main/resources/META-INF/spring.factories @@ -44,4 +44,5 @@ we.proxy.EurekaUriSelector,\ we.proxy.FizzWebClient,\ we.proxy.NacosUriSelector,\ we.proxy.RpcInstanceServiceImpl,\ -we.stats.ratelimit.ResourceRateLimitConfigService +we.stats.ratelimit.ResourceRateLimitConfigService,\ +we.global_resource.GlobalResourceService