From de8ad5ffaa6fb76cd88b7091c6307fce4f18066a Mon Sep 17 00:00:00 2001 From: tanghc Date: Fri, 16 Aug 2019 11:13:01 +0800 Subject: [PATCH] =?UTF-8?q?gateway=E5=8A=A8=E6=80=81=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gateway/ServerWebExchangeUtil.java | 68 +++++++++++++++++-- .../common/SopServerHttpRequestDecorator.java | 65 ++++++++++++++++++ .../gateway/filter/LimitFilter.java | 2 +- .../gatewaycommon/gateway/filter/Orders.java | 14 +++- .../filter/ParameterFormatterFilter.java | 25 +++++-- .../gateway/filter/ValidateFilter.java | 2 +- .../zuul/filter/BaseZuulFilter.java | 3 + .../zuul/filter/PreVersionDecisionFilter.java | 2 +- 8 files changed, 166 insertions(+), 15 deletions(-) create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/SopServerHttpRequestDecorator.java diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java index d1e7a84f..76129ba7 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java @@ -3,17 +3,23 @@ package com.gitee.sop.gatewaycommon.gateway; import com.alibaba.fastjson.JSON; import com.gitee.sop.gatewaycommon.bean.SopConstants; import com.gitee.sop.gatewaycommon.gateway.common.FileUploadHttpServletRequest; +import com.gitee.sop.gatewaycommon.gateway.common.SopServerHttpRequestDecorator; import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.util.RequestUtil; +import io.netty.buffer.ByteBufAllocator; import org.apache.commons.lang3.StringUtils; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.NettyDataBufferFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.MultiValueMap; import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.util.UriComponentsBuilder; import javax.servlet.http.HttpServletRequest; +import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.List; @@ -126,16 +132,70 @@ public class ServerWebExchangeUtil { } /** - * 修改请求参数 + * 修改请求参数。参考自:https://blog.csdn.net/fuck487/article/details/85166162 * @param exchange ServerWebExchange * @param apiParam 请求参数 - * @param consumer 执行参数更改 + * @param paramsConsumer 执行参数更改 + * @param headerConsumer header更改 * @param 参数类型 - * @return 返回新的ServerWebExchange + * @return 返回新的ServerWebExchange,参数没有被修改则返回null */ - public static > ServerWebExchange format(ServerWebExchange exchange, T apiParam, Consumer consumer) { + public static > ServerWebExchange format( + ServerWebExchange exchange + , T apiParam + , Consumer paramsConsumer + , Consumer headerConsumer + ) { + ServerHttpRequest serverHttpRequest = exchange.getRequest(); + if (serverHttpRequest.getMethod() == HttpMethod.GET) { + paramsConsumer.accept(apiParam); + } else { + MediaType mediaType = serverHttpRequest.getHeaders().getContentType(); + if (mediaType == null) { + return null; + } + paramsConsumer.accept(apiParam); + String contentType = mediaType.toString().toLowerCase(); + if (StringUtils.containsAny(contentType, "json", "text")) { + //下面的将请求体再次封装写回到request里,传到下一级,否则,由于请求体已被消费,后续的服务将取不到值 + URI uri = serverHttpRequest.getURI(); + URI newUri = UriComponentsBuilder.fromUri(uri).build(true).toUri(); + ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri).build(); + + // 定义新的消息头 + HttpHeaders headers = new HttpHeaders(); + headers.putAll(exchange.getRequest().getHeaders()); + + // 自定义header + headerConsumer.accept(headers); + // 修改后的请求体 + String bodyStr = JSON.toJSONString(apiParam); + byte[] bodyStrBytes = bodyStr.getBytes(StandardCharsets.UTF_8); + + // 由于post的body只能订阅一次,由于上面代码中已经订阅过一次body。 + // 所以要再次封装请求到request才行,不然会报错请求已经订阅过 + request = new SopServerHttpRequestDecorator(request, bodyStrBytes, headers); + + return exchange.mutate().request(request).build(); + } else { + + } + } return null; } + /** + * 字符串转DataBuffer + * @param value 值 + * @return 返回buffer + */ + private static DataBuffer stringBuffer(String value) { + byte[] bytes = value.getBytes(StandardCharsets.UTF_8); + NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); + DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length); + buffer.write(bytes); + return buffer; + } + } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/SopServerHttpRequestDecorator.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/SopServerHttpRequestDecorator.java new file mode 100644 index 00000000..cb4e0da8 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/SopServerHttpRequestDecorator.java @@ -0,0 +1,65 @@ +package com.gitee.sop.gatewaycommon.gateway.common; + +import io.netty.buffer.ByteBufAllocator; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.NettyDataBufferFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpRequestDecorator; +import reactor.core.publisher.Flux; + +/** + * @author tanghc + */ +public class SopServerHttpRequestDecorator extends ServerHttpRequestDecorator { + + private Flux bodyData; + private HttpHeaders httpHeaders; + + public SopServerHttpRequestDecorator(ServerHttpRequest delegate, byte[] bodyData, HttpHeaders httpHeaders) { + super(delegate); + if (httpHeaders == null) { + throw new IllegalArgumentException("httpHeaders can not be null."); + } + if (bodyData == null) { + throw new IllegalArgumentException("bodyData can not be null."); + } + // 由于请求体已改变,这里要重新设置contentLength + int contentLength = bodyData.length; + httpHeaders.setContentLength(contentLength); + + if (contentLength <= 0) { + // TODO: this causes a 'HTTP/1.1 411 Length Required' on httpbin.org + httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); + } + + this.httpHeaders = httpHeaders; + this.bodyData = stringBuffer(bodyData); + } + + /** + * 字符串转DataBuffer + * @param bytes 请求体 + * @return 返回buffer + */ + private static Flux stringBuffer(byte[] bytes) { + NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); + DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length); + buffer.write(bytes); + return Flux.just(buffer); + } + + private SopServerHttpRequestDecorator(ServerHttpRequest delegate) { + super(delegate); + } + + @Override + public Flux getBody() { + return bodyData == null ? super.getBody() : bodyData; + } + + @Override + public HttpHeaders getHeaders() { + return httpHeaders == null ? super.getHeaders() : httpHeaders; + } +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LimitFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LimitFilter.java index 872df6d1..c24ef5d3 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LimitFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LimitFilter.java @@ -59,7 +59,7 @@ public class LimitFilter implements GlobalFilter, Ordered { @Override public int getOrder() { - return Orders.LIMIT_ORDER; + return Orders.LIMIT_FILTER_ORDER; } protected ConfigLimitDto findConfigLimitDto(ApiConfig apiConfig, ApiParam apiParam, ServerWebExchange exchange) { diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/Orders.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/Orders.java index 1485d969..cd3db928 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/Orders.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/Orders.java @@ -7,8 +7,18 @@ import org.springframework.core.Ordered; */ public class Orders { /** 验证拦截器order */ - public static final int VALIDATE_ORDER = Ordered.HIGHEST_PRECEDENCE + 1000; + public static final int VALIDATE_FILTER_ORDER = Ordered.HIGHEST_PRECEDENCE + 1000; + + /** 参数格式化过滤器 */ + public static final int PARAMETER_FORMATTER_FILTER_ORDER = VALIDATE_FILTER_ORDER + 1; + + /** 权限验证过滤 */ + public static final int PRE_ROUTE_PERMISSION_FILTER_ORDER = PARAMETER_FORMATTER_FILTER_ORDER + 100; /** 验证拦截器order */ - public static final int LIMIT_ORDER = VALIDATE_ORDER + 1; + public static final int LIMIT_FILTER_ORDER = PRE_ROUTE_PERMISSION_FILTER_ORDER + 100; + + /** 决定版本号过滤器 */ + public static final int VERSION_DECISION_FILTER_ORDER = LIMIT_FILTER_ORDER + 100; + } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ParameterFormatterFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ParameterFormatterFilter.java index 5a15a658..1624a680 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ParameterFormatterFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ParameterFormatterFilter.java @@ -4,7 +4,6 @@ import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; import com.gitee.sop.gatewaycommon.param.ApiParam; import com.gitee.sop.gatewaycommon.param.ParamNames; import com.gitee.sop.gatewaycommon.param.ParameterFormatter; -import com.gitee.sop.gatewaycommon.zuul.ZuulContext; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.filter.GatewayFilterChain; @@ -13,6 +12,8 @@ import org.springframework.core.Ordered; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; +import static com.gitee.sop.gatewaycommon.gateway.filter.Orders.PARAMETER_FORMATTER_FILTER_ORDER; + /** * @author tanghc */ @@ -24,18 +25,30 @@ public class ParameterFormatterFilter implements GlobalFilter, Ordered { @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { - ApiParam apiParam = ZuulContext.getApiParam(); + ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange); + if (apiParam == null) { + return chain.filter(exchange); + } // 校验成功后进行参数转换 if (sopParameterFormatter != null) { - ServerWebExchange formatExchange = ServerWebExchangeUtil.format(exchange, apiParam, sopParameterFormatter::format); - ServerWebExchange serverWebExchange = ServerWebExchangeUtil.addHeaders(formatExchange, httpHeaders -> httpHeaders.add(ParamNames.HEADER_VERSION_NAME, apiParam.fetchVersion())); - return chain.filter(serverWebExchange); + ServerWebExchange formatExchange = ServerWebExchangeUtil.format( + exchange + , apiParam + , sopParameterFormatter::format + , httpHeaders -> { + httpHeaders.remove(ParamNames.HEADER_VERSION_NAME); + httpHeaders.add(ParamNames.HEADER_VERSION_NAME, apiParam.fetchVersion()); + }); + if (formatExchange == null) { + return chain.filter(exchange); + } + return chain.filter(formatExchange); } return chain.filter(exchange); } @Override public int getOrder() { - return 0; + return PARAMETER_FORMATTER_FILTER_ORDER; } } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java index 4a038386..72c6d582 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ValidateFilter.java @@ -43,6 +43,6 @@ public class ValidateFilter implements GlobalFilter, Ordered { @Override public int getOrder() { // 最优先执行 - return Orders.VALIDATE_ORDER; + return Orders.VALIDATE_FILTER_ORDER; } } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/BaseZuulFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/BaseZuulFilter.java index 2147c1f3..77851c7b 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/BaseZuulFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/BaseZuulFilter.java @@ -32,6 +32,9 @@ public abstract class BaseZuulFilter extends ZuulFilter { /** 限流过滤 */ public static final int PRE_LIMIT_FILTER_ORDER = PRE_ROUTE_PERMISSION_FILTER_ORDER + 100; + /** 决定版本号过滤器 */ + public static final int PRE_VERSION_DECISION_FILTER_ORDER = PRE_LIMIT_FILTER_ORDER + 100; + private Integer filterOrder; /** diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreVersionDecisionFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreVersionDecisionFilter.java index d0198414..e8bcfef4 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreVersionDecisionFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreVersionDecisionFilter.java @@ -25,7 +25,7 @@ public class PreVersionDecisionFilter extends BaseZuulFilter { @Override protected int getFilterOrder() { - return PRE_LIMIT_FILTER_ORDER + 1; + return PRE_VERSION_DECISION_FILTER_ORDER; } @Override