Merge pull request #431 from wehotel/develop

This commit is contained in:
hongqiaowei
2022-05-24 14:36:14 +08:00
committed by GitHub
6 changed files with 155 additions and 35 deletions

View File

@@ -26,7 +26,7 @@
<slf4j.version>1.7.36</slf4j.version> <slf4j.version>1.7.36</slf4j.version>
<commons-lang3.version>3.12.0</commons-lang3.version> <commons-lang3.version>3.12.0</commons-lang3.version>
<lombok.version>1.18.22</lombok.version> <lombok.version>1.18.22</lombok.version>
<apache.dubbo.version>2.7.5</apache.dubbo.version> <apache.dubbo.version>2.7.7</apache.dubbo.version>
<grpc.version>1.16.1</grpc.version> <grpc.version>1.16.1</grpc.version>
<mockito.version>3.4.6</mockito.version> <mockito.version>3.4.6</mockito.version>
<curator.version>4.0.1</curator.version> <curator.version>4.0.1</curator.version>

View File

@@ -45,10 +45,7 @@ import we.util.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
/** /**
@@ -110,21 +107,37 @@ public class RouteFilter extends FizzWebFilter {
} }
if (route == null) { if (route == null) {
String pathQuery = WebUtils.getClientReqPathQuery(exchange); /*String pathQuery = WebUtils.getClientReqPathQuery(exchange);
return fizzWebClient.send2service(traceId, req.getMethod(), WebUtils.getClientService(exchange), pathQuery, hdrs, req.getBody(), 0, 0, 0) return fizzWebClient.send2service(traceId, req.getMethod(), WebUtils.getClientService(exchange), pathQuery, hdrs, req.getBody(), 0, 0, 0)
.flatMap(genServerResponse(exchange));*/
Map.Entry<String, List<String>> pathQueryTemplate = WebUtils.getClientReqPathQueryTemplate(exchange).entrySet().iterator().next();
return fizzWebClient.send2service(traceId, req.getMethod(), WebUtils.getClientService(exchange), pathQueryTemplate.getKey(), hdrs, req.getBody(), 0, 0, 0, pathQueryTemplate.getValue().toArray(new String[0]))
.flatMap(genServerResponse(exchange)); .flatMap(genServerResponse(exchange));
} else if (route.type == ApiConfig.Type.SERVICE_DISCOVERY) { } else if (route.type == ApiConfig.Type.SERVICE_DISCOVERY) {
String pathQuery = getBackendPathQuery(req, route); /*String pathQuery = getBackendPathQuery(req, route);
String svc = RegistryCenterService.getServiceNameSpace(route.registryCenter, route.backendService); String svc = RegistryCenterService.getServiceNameSpace(route.registryCenter, route.backendService);
return fizzWebClient.send2service(traceId, route.method, svc, pathQuery, hdrs, req.getBody(), route.timeout, route.retryCount, route.retryInterval) return fizzWebClient.send2service(traceId, route.method, svc, pathQuery, hdrs, req.getBody(), route.timeout, route.retryCount, route.retryInterval)
.flatMap(genServerResponse(exchange));*/
Map.Entry<String, List<String>> pathQueryTemplate = getBackendPathQueryTemplate(req, route).entrySet().iterator().next();
String svc = RegistryCenterService.getServiceNameSpace(route.registryCenter, route.backendService);
return fizzWebClient.send2service(traceId, route.method, svc, pathQueryTemplate.getKey(), hdrs, req.getBody(), route.timeout, route.retryCount, route.retryInterval, pathQueryTemplate.getValue().toArray(new String[0]))
.flatMap(genServerResponse(exchange)); .flatMap(genServerResponse(exchange));
} else if (route.type == ApiConfig.Type.REVERSE_PROXY) { } else if (route.type == ApiConfig.Type.REVERSE_PROXY) {
String uri = ThreadContext.getStringBuilder().append(route.nextHttpHostPort) /*String uri = ThreadContext.getStringBuilder().append(route.nextHttpHostPort)
.append(getBackendPathQuery(req, route)) .append(getBackendPathQuery(req, route))
.toString(); .toString();
return fizzWebClient.send(traceId, route.method, uri, hdrs, req.getBody(), route.timeout, route.retryCount, route.retryInterval) return fizzWebClient.send(traceId, route.method, uri, hdrs, req.getBody(), route.timeout, route.retryCount, route.retryInterval)
.flatMap(genServerResponse(exchange));*/
Map.Entry<String, List<String>> pathQueryTemplate = getBackendPathQueryTemplate(req, route).entrySet().iterator().next();
String uri = ThreadContext.getStringBuilder().append(route.nextHttpHostPort)
.append(pathQueryTemplate.getKey())
.toString();
return fizzWebClient.send(traceId, route.method, uri, hdrs, req.getBody(), route.timeout, route.retryCount, route.retryInterval, pathQueryTemplate.getValue().toArray(new String[0]))
.flatMap(genServerResponse(exchange)); .flatMap(genServerResponse(exchange));
} else { } else {
@@ -146,6 +159,23 @@ public class RouteFilter extends FizzWebFilter {
} }
} }
private Map<String, List<String>> getBackendPathQueryTemplate(ServerHttpRequest request, Route route) {
String qry = route.query;
if (qry == null) {
MultiValueMap<String, String> queryParams = request.getQueryParams();
if (queryParams.isEmpty()) {
return Collections.singletonMap(route.backendPath, Collections.emptyList());
} else {
Map<String, List<String>> queryStringTemplate = WebUtils.toQueryStringTemplate(queryParams);
Map.Entry<String, List<String>> entry = queryStringTemplate.entrySet().iterator().next();
qry = route.backendPath + Consts.S.QUESTION + entry.getKey();
return Collections.singletonMap(qry, entry.getValue());
}
} else {
return Collections.singletonMap(route.backendPath + Consts.S.QUESTION + qry, Collections.emptyList());
}
}
private Function<ClientResponse, Mono<? extends Void>> genServerResponse(ServerWebExchange exchange) { private Function<ClientResponse, Mono<? extends Void>> genServerResponse(ServerWebExchange exchange) {
return remoteResp -> { return remoteResp -> {
ServerHttpResponse clientResp = exchange.getResponse(); ServerHttpResponse clientResp = exchange.getResponse();

View File

@@ -401,7 +401,8 @@ public class ApiConfigService implements ApplicationListener<ContextRefreshedEve
} }
if (clientCanAccess.isEmpty()) { if (clientCanAccess.isEmpty()) {
StringBuilder b = ThreadContext.getStringBuilder(); StringBuilder b = ThreadContext.getStringBuilder();
b.append("app ").append(app).append(" can't access ").append(JacksonUtils.writeValueAsString(apiConfigs)); // b.append("app ").append(app).append(" can't access ").append(JacksonUtils.writeValueAsString(apiConfigs));
b.append("app ").append(app).append(" can't access matching route");
return Result.fail(b.toString()); return Result.fail(b.toString());
} }
ApiConfig bestOne = clientCanAccess.get(0); ApiConfig bestOne = clientCanAccess.get(0);

View File

@@ -17,6 +17,7 @@
package we.proxy; package we.proxy;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -44,6 +45,7 @@ import we.util.WebUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.Duration; import java.time.Duration;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -73,14 +75,26 @@ public class FizzWebClient {
private WebClient webClient; private WebClient webClient;
public Mono<ClientResponse> send(String traceId, public Mono<ClientResponse> send(String traceId,
HttpMethod method, String uriOrSvc, @Nullable HttpHeaders headers, @Nullable Object body) { HttpMethod method, String uriOrSvc, @Nullable HttpHeaders headers, @Nullable Object body) {
return send(traceId, method, uriOrSvc, headers, body, 0, 0, 0); return send(traceId, method, uriOrSvc, headers, body, ArrayUtils.EMPTY_STRING_ARRAY);
}
public Mono<ClientResponse> send(String traceId,
HttpMethod method, String uriOrSvc, @Nullable HttpHeaders headers, @Nullable Object body, String... uriQryParamVals) {
return send(traceId, method, uriOrSvc, headers, body, 0, 0, 0, uriQryParamVals);
}
public Mono<ClientResponse> send(String traceId,
HttpMethod method, String uriOrSvc, @Nullable HttpHeaders headers, @Nullable Object body,
long timeout, long numRetries, long retryInterval) {
return send(traceId, method, uriOrSvc, headers, body, timeout, numRetries, retryInterval, ArrayUtils.EMPTY_STRING_ARRAY);
} }
public Mono<ClientResponse> send(String traceId, public Mono<ClientResponse> send(String traceId,
HttpMethod method, String uriOrSvc, @Nullable HttpHeaders headers, @Nullable Object body, HttpMethod method, String uriOrSvc, @Nullable HttpHeaders headers, @Nullable Object body,
long timeout, long numRetries, long retryInterval) { long timeout, long numRetries, long retryInterval, String... uriQryParamVals) {
String s = extractServiceOrAddress(uriOrSvc); String s = extractServiceOrAddress(uriOrSvc);
@@ -97,9 +111,9 @@ public class FizzWebClient {
} else { } else {
uri = discoveryClientUriSelector.getNextUri(s, path); uri = discoveryClientUriSelector.getNextUri(s, path);
} }
return send2uri(traceId, method, uri, headers, body, timeout); return send2uri(traceId, method, uri, headers, body, timeout, uriQryParamVals);
} else { } else {
return send2uri(traceId, method, uriOrSvc, headers, body, timeout); return send2uri(traceId, method, uriOrSvc, headers, body, timeout, uriQryParamVals);
} }
}); });
@@ -124,14 +138,28 @@ public class FizzWebClient {
} }
public Mono<ClientResponse> send2service(@Nullable String traceId, public Mono<ClientResponse> send2service(@Nullable String traceId,
HttpMethod method, String service, String relativeUri, @Nullable HttpHeaders headers, @Nullable Object body) { HttpMethod method, String service, String relativeUri, @Nullable HttpHeaders headers, @Nullable Object body) {
return send2service(traceId, method, service, relativeUri, headers, body, 0, 0, 0); return send2service(traceId, method, service, relativeUri, headers, body, 0, 0, 0);
} }
public Mono<ClientResponse> send2service(@Nullable String traceId,
HttpMethod method, String service, String relativeUri, @Nullable HttpHeaders headers, @Nullable Object body,
String... relativeUriQryParamVals) {
return send2service(traceId, method, service, relativeUri, headers, body, 0, 0, 0, relativeUriQryParamVals);
}
public Mono<ClientResponse> send2service(@Nullable String traceId,
HttpMethod method, String service, String relativeUri, @Nullable HttpHeaders headers, @Nullable Object body,
long timeout, long numRetries, long retryInterval) {
return send2service(traceId, method, service, relativeUri, headers, body, timeout, numRetries, retryInterval, ArrayUtils.EMPTY_STRING_ARRAY);
}
public Mono<ClientResponse> send2service(@Nullable String traceId, public Mono<ClientResponse> send2service(@Nullable String traceId,
HttpMethod method, String service, String relativeUri, @Nullable HttpHeaders headers, @Nullable Object body, HttpMethod method, String service, String relativeUri, @Nullable HttpHeaders headers, @Nullable Object body,
long timeout, long numRetries, long retryInterval) { long timeout, long numRetries, long retryInterval, String... relativeUriQryParamVals) {
Mono<ClientResponse> cr = Mono.just(Consts.S.EMPTY).flatMap(dummy -> { Mono<ClientResponse> cr = Mono.just(Consts.S.EMPTY).flatMap(dummy -> {
String uri = null; String uri = null;
@@ -144,7 +172,7 @@ public class FizzWebClient {
} else { } else {
uri = discoveryClientUriSelector.getNextUri(service, relativeUri); uri = discoveryClientUriSelector.getNextUri(service, relativeUri);
} }
return send2uri(traceId, method, uri, headers, body, timeout); return send2uri(traceId, method, uri, headers, body, timeout, relativeUriQryParamVals);
}); });
if (numRetries > 0) { if (numRetries > 0) {
cr = cr.flatMap(resp -> { cr = cr.flatMap(resp -> {
@@ -170,9 +198,19 @@ public class FizzWebClient {
return send2uri(traceId, method, uri, headers, body, 0); return send2uri(traceId, method, uri, headers, body, 0);
} }
public Mono<ClientResponse> send2uri(@Nullable String traceId, HttpMethod method, String uri, @Nullable HttpHeaders headers, @Nullable Object body, String... uriQryParamVals) {
return send2uri(traceId, method, uri, headers, body, 0, uriQryParamVals);
}
public Mono<ClientResponse> send2uri(@Nullable String traceId,
HttpMethod method, String uri, @Nullable HttpHeaders headers, @Nullable Object body,
long timeout) {
return send2uri(traceId, method, uri, headers, body, timeout, ArrayUtils.EMPTY_STRING_ARRAY);
}
public Mono<ClientResponse> send2uri(@Nullable String traceId, public Mono<ClientResponse> send2uri(@Nullable String traceId,
HttpMethod method, String uri, @Nullable HttpHeaders headers, @Nullable Object body, HttpMethod method, String uri, @Nullable HttpHeaders headers, @Nullable Object body,
long timeout) { long timeout, String... uriQryParamVals) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
StringBuilder b = ThreadContext.getStringBuilder(); StringBuilder b = ThreadContext.getStringBuilder();
@@ -180,18 +218,25 @@ public class FizzWebClient {
log.debug(b.toString(), LogService.BIZ_ID, traceId); log.debug(b.toString(), LogService.BIZ_ID, traceId);
} }
WebClient.RequestBodySpec req = webClient.method(method).uri(uri).headers( WebClient.RequestBodyUriSpec requestBodyUriSpec = webClient.method(method);
hdrs -> { WebClient.RequestBodySpec requestBodySpec = null;
if (headers != null) { if (uriQryParamVals.length == 0) {
headers.forEach( requestBodySpec = requestBodyUriSpec.uri(uri);
(h, vs) -> { } else {
hdrs.addAll(h, vs); requestBodySpec = requestBodyUriSpec.uri(uri, Arrays.stream(uriQryParamVals).toArray());
} }
); WebClient.RequestBodySpec req = requestBodySpec.headers(
} hdrs -> {
setHostHeader(uri, hdrs); if (headers != null) {
} headers.forEach(
); (h, vs) -> {
hdrs.addAll(h, vs);
}
);
}
setHostHeader(uri, hdrs);
}
);
if (body != null) { if (body != null) {
if (body instanceof BodyInserter) { if (body instanceof BodyInserter) {

View File

@@ -44,10 +44,7 @@ import java.net.URI;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Collections; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@@ -406,6 +403,19 @@ public abstract class WebUtils {
return pathQry; return pathQry;
} }
public static Map<String, List<String>> getClientReqPathQueryTemplate(ServerWebExchange exchange) {
String pathQry = getClientReqPath(exchange);
MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
if (queryParams.isEmpty()) {
return Collections.singletonMap(pathQry, Collections.emptyList());
} else {
Map<String, List<String>> queryStringTemplate = toQueryStringTemplate(queryParams);
Map.Entry<String, List<String>> entry = queryStringTemplate.entrySet().iterator().next();
pathQry = pathQry + Consts.S.QUESTION + entry.getKey();
return Collections.singletonMap(pathQry, entry.getValue());
}
}
public static String appendQuery(String path, ServerWebExchange exchange) { public static String appendQuery(String path, ServerWebExchange exchange) {
String qry = getClientReqQuery(exchange); String qry = getClientReqQuery(exchange);
if (qry != null) { if (qry != null) {
@@ -667,6 +677,40 @@ public abstract class WebUtils {
} }
} }
public static Map<String, List<String>> toQueryStringTemplate(MultiValueMap<String, String> queryParams) {
StringBuilder b = ThreadContext.getStringBuilder(ThreadContext.sb0);
Set<Map.Entry<String, List<String>>> params = queryParams.entrySet();
int ps = params.size(), cnt = 0;
List<String> paramValues = new ArrayList<>();
for (Map.Entry<String, List<String>> param : params) {
String name = param.getKey();
List<String> values = param.getValue();
if (values.isEmpty()) {
b.append(name);
} else {
int vs = values.size();
for (int i = 0; i < vs; ) {
b.append(name);
String v = values.get(i);
if (v != null) {
b.append(Consts.S.EQUAL);
if (!Consts.S.EMPTY.equals(v)) {
paramValues.add(v);
b.append(Consts.S.LEFT_BRACE).append(paramValues.size()).append(Consts.S.RIGHT_BRACE);
}
}
if ((++i) != vs) {
b.append(Consts.S.AND);
}
}
}
if ((++cnt) != ps) {
b.append(Consts.S.AND);
}
}
return Collections.singletonMap(b.toString(), paramValues);
}
// the method below will be deprecated. // the method below will be deprecated.
@Deprecated @Deprecated

View File

@@ -14,7 +14,7 @@
<httpcore.version>4.4.15</httpcore.version> <httpcore.version>4.4.15</httpcore.version>
<log4j2.version>2.17.2</log4j2.version> <log4j2.version>2.17.2</log4j2.version>
<slf4j.version>1.7.36</slf4j.version> <slf4j.version>1.7.36</slf4j.version>
<apache.dubbo.version>2.7.5</apache.dubbo.version> <apache.dubbo.version>2.7.7</apache.dubbo.version>
<grpc.version>1.16.1</grpc.version> <grpc.version>1.16.1</grpc.version>
<mockito.version>3.4.6</mockito.version> <mockito.version>3.4.6</mockito.version>
<curator.version>4.0.1</curator.version> <curator.version>4.0.1</curator.version>