diff --git a/changelog.md b/changelog.md
index 3a943235..8059c5d1 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,10 @@
# changelog
+## 1.15.2
+
+- 优化SpringCloudGateway上传文件功能
+- 优化SpringCloudGateway动态修改参数功能
+
## 1.15.1
- 修复未配置正确MessageConverter导致的异常
diff --git a/doc/docs/_sidebar.md b/doc/docs/_sidebar.md
index 767cf8cc..d201e865 100644
--- a/doc/docs/_sidebar.md
+++ b/doc/docs/_sidebar.md
@@ -1,34 +1,34 @@
-* [首页](/?t=1565767132305)
+* [首页](/?t=1565916799573)
* 开发文档
- * [快速体验](files/10010_快速体验.md?t=1565767132307)
- * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1565767132325)
- * [新增接口](files/10020_新增接口.md?t=1565767132325)
- * [业务参数校验](files/10030_业务参数校验.md?t=1565767132325)
- * [错误处理](files/10040_错误处理.md?t=1565767132325)
- * [编写文档](files/10041_编写文档.md?t=1565767132326)
- * [接口交互详解](files/10050_接口交互详解.md?t=1565767132326)
- * [easyopen支持](files/10070_easyopen支持.md?t=1565767132326)
- * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1565767132326)
- * [ISV管理](files/10085_ISV管理.md?t=1565767132326)
- * [自定义路由](files/10086_自定义路由.md?t=1565767132326)
- * [自定义返回结果](files/10087_自定义返回结果.md?t=1565767132326)
- * [自定义过滤器](files/10088_自定义过滤器.md?t=1565767132326)
- * [路由授权](files/10090_路由授权.md?t=1565767132326)
- * [接口限流](files/10092_接口限流.md?t=1565767132326)
- * [监控日志](files/10093_监控日志.md?t=1565767132327)
- * [SDK开发](files/10095_SDK开发.md?t=1565767132327)
- * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1565767132327)
- * [应用授权](files/10097_应用授权.md?t=1565767132327)
- * [传统web开发](files/10100_传统web开发.md?t=1565767132327)
- * [文件上传](files/10104_文件上传.md?t=1565767132327)
- * [nacos注册中心](files/10106_nacos注册中心.md?t=1565767132327)
- * [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1565767132327)
- * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1565767132327)
- * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1565767132327)
- * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1565767132327)
+ * [快速体验](files/10010_快速体验.md?t=1565916799577)
+ * [项目接入到SOP](files/10011_项目接入到SOP.md?t=1565916799596)
+ * [新增接口](files/10020_新增接口.md?t=1565916799596)
+ * [业务参数校验](files/10030_业务参数校验.md?t=1565916799596)
+ * [错误处理](files/10040_错误处理.md?t=1565916799596)
+ * [编写文档](files/10041_编写文档.md?t=1565916799596)
+ * [接口交互详解](files/10050_接口交互详解.md?t=1565916799597)
+ * [easyopen支持](files/10070_easyopen支持.md?t=1565916799597)
+ * [使用签名校验工具](files/10080_使用签名校验工具.md?t=1565916799597)
+ * [ISV管理](files/10085_ISV管理.md?t=1565916799597)
+ * [自定义路由](files/10086_自定义路由.md?t=1565916799597)
+ * [自定义返回结果](files/10087_自定义返回结果.md?t=1565916799597)
+ * [自定义过滤器](files/10088_自定义过滤器.md?t=1565916799597)
+ * [路由授权](files/10090_路由授权.md?t=1565916799598)
+ * [接口限流](files/10092_接口限流.md?t=1565916799598)
+ * [监控日志](files/10093_监控日志.md?t=1565916799598)
+ * [SDK开发](files/10095_SDK开发.md?t=1565916799598)
+ * [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1565916799598)
+ * [应用授权](files/10097_应用授权.md?t=1565916799598)
+ * [传统web开发](files/10100_传统web开发.md?t=1565916799598)
+ * [文件上传](files/10104_文件上传.md?t=1565916799598)
+ * [nacos注册中心](files/10106_nacos注册中心.md?t=1565916799599)
+ * [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1565916799599)
+ * [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1565916799599)
+ * [预发布灰度发布](files/10110_预发布灰度发布.md?t=1565916799599)
+ * [动态修改请求参数](files/10111_动态修改请求参数.md?t=1565916799599)
* 原理分析
- * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1565767132328)
- * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1565767132328)
- * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1565767132328)
- * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1565767132328)
- * [常见问题](files/90100_常见问题.md?t=1565767132328)
+ * [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1565916799599)
+ * [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1565916799599)
+ * [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1565916799599)
+ * [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1565916799600)
+ * [常见问题](files/90100_常见问题.md?t=1565916799600)
diff --git a/doc/docs/files/10111_动态修改请求参数.md b/doc/docs/files/10111_动态修改请求参数.md
index 90f2f7f4..b8d1d89f 100644
--- a/doc/docs/files/10111_动态修改请求参数.md
+++ b/doc/docs/files/10111_动态修改请求参数.md
@@ -14,7 +14,7 @@
```java
public static void main(String[] args) {
- ApiConfig.getInstance().setZuulParameterFormatter(requestParams -> {
+ ApiConfig.getInstance().setParameterFormatter(requestParams -> {
// 获取biz_content
JSONObject jsonObject = requestParams.getJSONObject(ParamNames.BIZ_CONTENT_NAME);
// 修改biz_content中的值
diff --git a/sop-admin/sop-admin-server/pom.xml b/sop-admin/sop-admin-server/pom.xml
index e2bf8da2..5b5fb943 100644
--- a/sop-admin/sop-admin-server/pom.xml
+++ b/sop-admin/sop-admin-server/pom.xml
@@ -30,7 +30,7 @@
com.gitee.sop
sop-registry-api
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT
diff --git a/sop-common/pom.xml b/sop-common/pom.xml
index 3812e07f..a040c4dc 100644
--- a/sop-common/pom.xml
+++ b/sop-common/pom.xml
@@ -5,7 +5,7 @@
4.0.0
com.gitee.sop
sop-common
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT
pom
diff --git a/sop-common/sop-gateway-common/pom.xml b/sop-common/sop-gateway-common/pom.xml
index 01eb5160..7632cd29 100644
--- a/sop-common/sop-gateway-common/pom.xml
+++ b/sop-common/sop-gateway-common/pom.xml
@@ -5,11 +5,11 @@
com.gitee.sop
sop-common
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT
../pom.xml
sop-gateway-common
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT
jar
sop-gateway-common
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java
index ab6fb813..a61e9f6a 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/ApiConfig.java
@@ -18,6 +18,7 @@ import com.gitee.sop.gatewaycommon.manager.LimitConfigManager;
import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
import com.gitee.sop.gatewaycommon.manager.ServiceErrorManager;
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
+import com.gitee.sop.gatewaycommon.param.ParameterFormatter;
import com.gitee.sop.gatewaycommon.result.DataNameBuilder;
import com.gitee.sop.gatewaycommon.result.DefaultDataNameBuilder;
import com.gitee.sop.gatewaycommon.result.ResultAppender;
@@ -34,7 +35,6 @@ import com.gitee.sop.gatewaycommon.validate.Signer;
import com.gitee.sop.gatewaycommon.validate.Validator;
import com.gitee.sop.gatewaycommon.zuul.configuration.ZuulErrorController;
import com.gitee.sop.gatewaycommon.zuul.param.ZuulParamBuilder;
-import com.gitee.sop.gatewaycommon.zuul.param.ZuulParameterFormatter;
import com.gitee.sop.gatewaycommon.zuul.result.ZuulResultExecutor;
import com.netflix.zuul.context.RequestContext;
import lombok.Data;
@@ -150,7 +150,7 @@ public class ApiConfig {
*/
private ZuulErrorController zuulErrorController = new ZuulErrorController();
- private ZuulParameterFormatter zuulParameterFormatter;
+ private ParameterFormatter parameterFormatter;
// -------- fields ---------
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java
index 4a3f5c99..649f1a7f 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java
@@ -34,6 +34,8 @@ public class SopConstants {
public static final String CACHE_API_PARAM = "cacheApiParam";
+ public static final String CACHE_UPLOAD_REQUEST = "cacheUploadRequest";
+
public static final String X_SERVICE_ERROR_CODE = "x-service-error-code";
public static final String X_SERVICE_ERROR_MESSAGE = "x-service-error-message";
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 e5aa91ac..884ed753 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
@@ -2,18 +2,28 @@ 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.ServletFileUploadUtil;
+import com.gitee.sop.gatewaycommon.gateway.common.FileUploadHttpServletRequest;
+import com.gitee.sop.gatewaycommon.gateway.common.RequestContentDataExtractor;
+import com.gitee.sop.gatewaycommon.gateway.common.SopServerHttpRequestDecorator;
import com.gitee.sop.gatewaycommon.param.ApiParam;
+import com.gitee.sop.gatewaycommon.param.FormHttpOutputMessage;
import com.gitee.sop.gatewaycommon.util.RequestUtil;
+import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
+import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.MultiValueMap;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.server.ServerWebExchange;
import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -25,10 +35,14 @@ import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_O
/**
* @author tanghc
*/
+@Slf4j
public class ServerWebExchangeUtil {
+ private static FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
+
/**
* 获取请求参数
+ *
* @param exchange ServerWebExchange
* @return 返回请求参数
*/
@@ -38,6 +52,7 @@ public class ServerWebExchangeUtil {
/**
* 设置请求参数
+ *
* @param exchange ServerWebExchange
* @param apiParam 请求参数
*/
@@ -47,6 +62,7 @@ public class ServerWebExchangeUtil {
/**
* 获取Spring Cloud Gateway请求的原始参数。前提是要使用ReadBodyRoutePredicateFactory
+ *
* @param exchange ServerWebExchange
* @return 没有参数返回null
* @see com.gitee.sop.gatewaycommon.gateway.route.ReadBodyRoutePredicateFactory
@@ -69,7 +85,8 @@ public class ServerWebExchangeUtil {
params = JSON.parseObject(cachedBody);
} else if (StringUtils.containsIgnoreCase(contentTypeStr, "multipart")) {
// 如果是文件上传请求
- HttpServletRequest fileUploadRequest = ServletFileUploadUtil.getFileUploadRequest(exchange, cachedBody);
+ HttpServletRequest fileUploadRequest = getFileUploadRequest(exchange, cachedBody);
+ setFileUploadRequest(exchange, fileUploadRequest);
params = RequestUtil.convertMultipartRequestToMap(fileUploadRequest);
} else {
params = RequestUtil.parseQueryToMap(cachedBody);
@@ -82,6 +99,7 @@ public class ServerWebExchangeUtil {
return params;
}
+
public static Map buildParams(MultiValueMap queryParams) {
if (queryParams == null || queryParams.size() == 0) {
return null;
@@ -95,7 +113,8 @@ public class ServerWebExchangeUtil {
/**
* 添加header
- * @param exchange 当前ServerWebExchange
+ *
+ * @param exchange 当前ServerWebExchange
* @param headersConsumer headers
* @return 返回一个新的ServerWebExchange
*/
@@ -105,12 +124,116 @@ public class ServerWebExchangeUtil {
.mutate()
.headers(headersConsumer)
.build();
- // 将现在的request 变成 change对象
+ // 创建一个新的exchange对象
return exchange
.mutate()
.request(serverHttpRequestNew)
.build();
}
+ /**
+ * 获取一个文件上传request
+ *
+ * @param exchange 当前ServerWebExchange
+ * @param requestBody 上传文件请求体内容
+ * @return 返回文件上传request
+ */
+ public static HttpServletRequest getFileUploadRequest(ServerWebExchange exchange, String requestBody) {
+ byte[] data = requestBody.getBytes(StandardCharsets.UTF_8);
+ return new FileUploadHttpServletRequest(exchange.getRequest(), data);
+ }
+
+ public static HttpServletRequest getFileUploadRequest(ServerWebExchange exchange) {
+ return exchange.getAttribute(SopConstants.CACHE_UPLOAD_REQUEST);
+ }
+
+ public static void setFileUploadRequest(ServerWebExchange exchange, HttpServletRequest request) {
+ exchange.getAttributes().put(SopConstants.CACHE_UPLOAD_REQUEST, request);
+ }
+
+ /**
+ * 修改请求参数。参考自:https://blog.csdn.net/fuck487/article/details/85166162
+ *
+ * @param exchange ServerWebExchange
+ * @param apiParam 原始请求参数
+ * @param paramsConsumer 执行参数更改
+ * @param headerConsumer header更改
+ * @param 参数类型
+ * @return 返回新的ServerWebExchange
+ */
+ public static > ServerWebExchange format(
+ ServerWebExchange exchange
+ , T apiParam
+ , Consumer paramsConsumer
+ , Consumer headerConsumer
+ ) {
+ ServerHttpRequest serverHttpRequest = exchange.getRequest();
+ HttpHeaders newHeaders = HttpHeaders.writableHttpHeaders(serverHttpRequest.getHeaders());
+ // 新的request
+ ServerHttpRequest newRequest;
+ if (serverHttpRequest.getMethod() == HttpMethod.GET) {
+ paramsConsumer.accept(apiParam);
+ // 新的查询参数
+ String queryString = RequestUtil.convertMapToQueryString(apiParam);
+ // 创建一个新的request,并使用新的uri
+ newRequest = new SopServerHttpRequestDecorator(serverHttpRequest, newHeaders, queryString);
+ } else {
+ MediaType mediaType = serverHttpRequest.getHeaders().getContentType();
+ if (mediaType == null) {
+ mediaType = MediaType.APPLICATION_FORM_URLENCODED;
+ }
+ paramsConsumer.accept(apiParam);
+ String contentType = mediaType.toString().toLowerCase();
+ // 修改后的请求体
+ // 处理json请求(application/json)
+ if (StringUtils.containsAny(contentType, "json", "text")) {
+ String bodyStr = JSON.toJSONString(apiParam);
+ byte[] bodyBytes = bodyStr.getBytes(StandardCharsets.UTF_8);
+ newRequest = new SopServerHttpRequestDecorator(serverHttpRequest, newHeaders, bodyBytes);
+ } else if (StringUtils.contains(contentType, "multipart")) {
+ // 处理文件上传请求
+ FormHttpOutputMessage outputMessage = new FormHttpOutputMessage();
+ HttpServletRequest request = ServerWebExchangeUtil.getFileUploadRequest(exchange);
+ try {
+ // 转成MultipartRequest
+ if (!(request instanceof MultipartHttpServletRequest)) {
+ CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
+ request = commonsMultipartResolver.resolveMultipart(request);
+ }
+ // 重写新的值
+ MultiValueMap builder = RequestContentDataExtractor.extract(request);
+ for (Map.Entry entry : apiParam.entrySet()) {
+ Object value = entry.getValue();
+ if (value instanceof List) {
+ builder.put(entry.getKey(), (List) value);
+ } else {
+ builder.put(entry.getKey(), Collections.singletonList(String.valueOf(value)));
+ }
+ }
+ // 将字段以及上传文件重写写入到流中
+ formHttpMessageConverter.write(builder, mediaType, outputMessage);
+ // 获取新的上传文件流
+ byte[] bodyBytes = outputMessage.getInput();
+ newRequest = new SopServerHttpRequestDecorator(serverHttpRequest, newHeaders, bodyBytes);
+ // 必须要重新指定content-type,因为此时的boundary已经发生改变
+ MediaType contentTypeMultipart = outputMessage.getHeaders().getContentType();
+ newRequest.getHeaders().setContentType(contentTypeMultipart);
+ } catch (IOException e) {
+ log.error("修改上传文件请求参数失败, apiParam:{}", apiParam, e);
+ throw new RuntimeException(e);
+ }
+ } else {
+ // 否则一律按表单请求处理
+ String bodyStr = RequestUtil.convertMapToQueryString(apiParam);
+ byte[] bodyBytes = bodyStr.getBytes(StandardCharsets.UTF_8);
+ newRequest = new SopServerHttpRequestDecorator(serverHttpRequest, newHeaders, bodyBytes);
+ }
+ }
+ HttpHeaders headers = newRequest.getHeaders();
+ // 自定义header
+ headerConsumer.accept(headers);
+ // 创建一个新的exchange
+ return exchange.mutate().request(newRequest).build();
+ }
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ByteArrayStreamWrapper.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ByteArrayStreamWrapper.java
index 57ba85d6..93c592a3 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ByteArrayStreamWrapper.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ByteArrayStreamWrapper.java
@@ -4,13 +4,18 @@ import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.IOException;
+/**
+ * byte数组流包装
+ *
+ * @author tanghc
+ */
public class ByteArrayStreamWrapper extends ServletInputStream {
private byte[] data;
private int idx = 0;
/**
- * Creates a new ServletInputStreamWrapper
instance.
+ * Creates a new ByteArrayStreamWrapper
instance.
*
* @param data a byte[]
value
*/
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/FileUploadHttpServletRequest.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/FileUploadHttpServletRequest.java
index 0a316372..1127c284 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/FileUploadHttpServletRequest.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/FileUploadHttpServletRequest.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.Collection;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;
@@ -250,7 +251,7 @@ public class FileUploadHttpServletRequest implements HttpServletRequest {
@Override
public Enumeration getParameterNames() {
- return null;
+ return Collections.emptyEnumeration();
}
@Override
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/RequestContentDataExtractor.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/RequestContentDataExtractor.java
new file mode 100644
index 00000000..543f5e96
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/RequestContentDataExtractor.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2013-2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.gitee.sop.gatewaycommon.gateway.common;
+
+import org.springframework.core.io.InputStreamResource;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static java.util.Arrays.stream;
+import static java.util.Collections.emptyMap;
+import static org.springframework.util.StringUtils.isEmpty;
+import static org.springframework.util.StringUtils.tokenizeToStringArray;
+import static org.springframework.util.StringUtils.uriDecode;
+
+public class RequestContentDataExtractor {
+ public static MultiValueMap extract(HttpServletRequest request) throws IOException {
+ return (request instanceof MultipartHttpServletRequest) ?
+ extractFromMultipartRequest((MultipartHttpServletRequest) request) :
+ extractFromRequest(request);
+ }
+
+ private static MultiValueMap extractFromRequest(HttpServletRequest request) throws IOException {
+ MultiValueMap builder = new LinkedMultiValueMap<>();
+ Set queryParams = findQueryParams(request);
+
+ for (Entry entry : request.getParameterMap().entrySet()) {
+ String key = entry.getKey();
+
+ if (!queryParams.contains(key) && entry.getValue() != null) {
+ for (String value : entry.getValue()) {
+ builder.add(key, value);
+ }
+ }
+ }
+
+ return builder;
+ }
+
+ private static MultiValueMap extractFromMultipartRequest(MultipartHttpServletRequest request)
+ throws IOException {
+ MultiValueMap builder = new LinkedMultiValueMap<>();
+ Map> queryParamsGroupedByName = findQueryParamsGroupedByName(
+ request);
+ Set queryParams = findQueryParams(request);
+
+ for (Entry entry : request.getParameterMap().entrySet()) {
+ String key = entry.getKey();
+ List listOfAllParams = stream(request.getParameterMap().get(key))
+ .collect(Collectors.toList());
+ List listOfOnlyQueryParams = queryParamsGroupedByName.get(key);
+
+ if(listOfOnlyQueryParams != null) {
+ listOfOnlyQueryParams = listOfOnlyQueryParams.stream()
+ .map(param -> uriDecode(param, Charset.defaultCharset()))
+ .collect(Collectors.toList());
+ if (!listOfOnlyQueryParams.containsAll(listOfAllParams)) {
+ listOfAllParams.removeAll(listOfOnlyQueryParams);
+ for (String value : listOfAllParams) {
+ builder.add(key,
+ new HttpEntity<>(value, newHttpHeaders(request, key)));
+ }
+ }
+ }
+
+ if (!queryParams.contains(key)) {
+ for (String value : entry.getValue()) {
+ builder.add(key,
+ new HttpEntity<>(value, newHttpHeaders(request, key)));
+ }
+ }
+ }
+
+ for (Entry> parts : request.getMultiFileMap().entrySet()) {
+ for (MultipartFile file : parts.getValue()) {
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentDispositionFormData(file.getName(), file.getOriginalFilename());
+ if (file.getContentType() != null) {
+ headers.setContentType(MediaType.valueOf(file.getContentType()));
+ }
+
+ HttpEntity entity = new HttpEntity<>(new InputStreamResource(file.getInputStream()), headers);
+ builder.add(parts.getKey(), entity);
+ }
+ }
+
+ return builder;
+ }
+
+ private static HttpHeaders newHttpHeaders(MultipartHttpServletRequest request,
+ String key) {
+ HttpHeaders headers = new HttpHeaders();
+ String type = request.getMultipartContentType(key);
+
+ if (type != null) {
+ headers.setContentType(MediaType.valueOf(type));
+ }
+ return headers;
+ }
+
+ private static Set findQueryParams(HttpServletRequest request) {
+ Set result = new HashSet<>();
+ String query = request.getQueryString();
+
+ if (query != null) {
+ for (String value : tokenizeToStringArray(query, "&")) {
+ if (value.contains("=")) {
+ value = value.substring(0, value.indexOf("="));
+ }
+ result.add(value);
+ }
+ }
+
+ return result;
+ }
+
+ static Map> findQueryParamsGroupedByName(
+ HttpServletRequest request) {
+ String query = request.getQueryString();
+ if (isEmpty(query)) {
+ return emptyMap();
+ }
+ return UriComponentsBuilder.fromUriString("?" + query).build().getQueryParams();
+ }
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ServletFileUploadUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ServletFileUploadUtil.java
deleted file mode 100644
index 9cb299c6..00000000
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ServletFileUploadUtil.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.gitee.sop.gatewaycommon.gateway.common;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.server.ServerWebExchange;
-
-import javax.servlet.http.HttpServletRequest;
-import java.nio.charset.StandardCharsets;
-
-/**
- * @author tanghc
- */
-@Slf4j
-public class ServletFileUploadUtil {
-
- public static HttpServletRequest getFileUploadRequest(ServerWebExchange exchange, String requestBody) {
- byte[] data = requestBody.getBytes(StandardCharsets.UTF_8);
- return new FileUploadHttpServletRequest(exchange.getRequest(), data);
- }
-
-}
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..479726be
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/SopServerHttpRequestDecorator.java
@@ -0,0 +1,102 @@
+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.HttpMethod;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
+import org.springframework.web.util.UriComponentsBuilder;
+import reactor.core.publisher.Flux;
+
+import java.net.URI;
+
+/**
+ * @author tanghc
+ */
+public class SopServerHttpRequestDecorator extends ServerHttpRequestDecorator {
+
+ private Flux bodyDataBuffer;
+ private HttpHeaders httpHeaders;
+ private URI uri;
+
+ /**
+ * ServerHttpRequest包装,作用类似于HttpServletRequestWrapper
+ * @param delegate 老的request
+ * @param queryString get请求后面的参数
+ */
+ public SopServerHttpRequestDecorator(ServerHttpRequest delegate, HttpHeaders newHeaders, String queryString) {
+ super(delegate);
+ if (delegate.getMethod() != HttpMethod.GET) {
+ throw new IllegalArgumentException("this constructor must be used by GET request.");
+ }
+ if (queryString == null) {
+ throw new IllegalArgumentException("queryString can not be null.");
+ }
+ if (newHeaders == null) {
+ throw new IllegalArgumentException("newHeaders can not be null.");
+ }
+
+ this.httpHeaders = newHeaders;
+ this.uri = UriComponentsBuilder.fromUri(delegate.getURI())
+ .replaceQuery(queryString)
+ .build(true)
+ .toUri();
+ }
+
+
+
+ /**
+ * ServerHttpRequest包装,作用类似于HttpServletRequestWrapper
+ * @param delegate 老的request
+ * @param newHeaders 新的headers
+ * @param bodyData 请求体内容
+ */
+ public SopServerHttpRequestDecorator(ServerHttpRequest delegate, HttpHeaders newHeaders, byte[] bodyData) {
+ // 将请求体再次封装写回到request里,传到下一级,否则,由于请求体已被消费,后续的服务将取不到值
+ super(delegate);
+ if (bodyData == null) {
+ throw new IllegalArgumentException("bodyData can not be null.");
+ }
+ if (newHeaders == null) {
+ throw new IllegalArgumentException("newHeaders can not be null.");
+ }
+ this.httpHeaders = newHeaders;
+ // 由于请求体已改变,这里要重新设置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.bodyDataBuffer = 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);
+ }
+
+ @Override
+ public URI getURI() {
+ return uri == null ? super.getURI() : uri;
+ }
+
+ @Override
+ public HttpHeaders getHeaders() {
+ return this.httpHeaders;
+ }
+
+ @Override
+ public Flux getBody() {
+ return bodyDataBuffer == null ? super.getBody() : bodyDataBuffer;
+ }
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/configuration/BaseGatewayConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/configuration/BaseGatewayConfiguration.java
index 5a3c2b6e..badbd26f 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/configuration/BaseGatewayConfiguration.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/configuration/BaseGatewayConfiguration.java
@@ -3,6 +3,7 @@ package com.gitee.sop.gatewaycommon.gateway.configuration;
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
import com.gitee.sop.gatewaycommon.gateway.filter.GatewayModifyResponseGatewayFilter;
import com.gitee.sop.gatewaycommon.gateway.filter.LoadBalancerClientExtFilter;
+import com.gitee.sop.gatewaycommon.gateway.filter.ParameterFormatterFilter;
import com.gitee.sop.gatewaycommon.gateway.filter.ValidateFilter;
import com.gitee.sop.gatewaycommon.gateway.handler.GatewayExceptionHandler;
import com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteRepository;
@@ -106,4 +107,9 @@ public class BaseGatewayConfiguration extends AbstractConfiguration {
return gatewayRouteRepository;
}
+ @Bean
+ ParameterFormatterFilter parameterFormatterFilter() {
+ return new ParameterFormatterFilter();
+ }
+
}
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 ae7573c4..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
@@ -3,7 +3,7 @@ package com.gitee.sop.gatewaycommon.gateway.filter;
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
import com.gitee.sop.gatewaycommon.bean.ConfigLimitDto;
import com.gitee.sop.gatewaycommon.exception.ApiException;
-import com.gitee.sop.gatewaycommon.gateway.GatewayContext;
+import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil;
import com.gitee.sop.gatewaycommon.limit.LimitManager;
import com.gitee.sop.gatewaycommon.limit.LimitType;
import com.gitee.sop.gatewaycommon.manager.LimitConfigManager;
@@ -34,7 +34,7 @@ public class LimitFilter implements GlobalFilter, Ordered {
if (!apiConfig.isOpenLimit()) {
return chain.filter(exchange);
}
- ApiParam apiParam = GatewayContext.getApiParam(exchange);
+ ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange);
ConfigLimitDto configLimitDto = this.findConfigLimitDto(apiConfig, apiParam, exchange);
if (configLimitDto == null) {
return null;
@@ -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
new file mode 100644
index 00000000..d015662b
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/ParameterFormatterFilter.java
@@ -0,0 +1,51 @@
+package com.gitee.sop.gatewaycommon.gateway.filter;
+
+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 lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+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
+ */
+@Slf4j
+public class ParameterFormatterFilter implements GlobalFilter, Ordered {
+
+ @Autowired(required = false)
+ private ParameterFormatter sopParameterFormatter;
+
+ @Override
+ public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange);
+ if (apiParam == null) {
+ return chain.filter(exchange);
+ }
+ // 校验成功后进行参数转换
+ if (sopParameterFormatter != null) {
+ ServerWebExchange formatExchange = ServerWebExchangeUtil.format(
+ exchange
+ , apiParam
+ , sopParameterFormatter::format
+ , httpHeaders -> httpHeaders.set(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 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 66e3e928..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
@@ -1,7 +1,7 @@
package com.gitee.sop.gatewaycommon.gateway.filter;
import com.gitee.sop.gatewaycommon.exception.ApiException;
-import com.gitee.sop.gatewaycommon.gateway.GatewayContext;
+import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil;
import com.gitee.sop.gatewaycommon.param.ApiParam;
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
import com.gitee.sop.gatewaycommon.validate.Validator;
@@ -29,7 +29,7 @@ public class ValidateFilter implements GlobalFilter, Ordered {
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 解析参数
ApiParam param = paramBuilder.build(exchange);
- GatewayContext.setApiParam(exchange, param);
+ ServerWebExchangeUtil.setApiParam(exchange, param);
// 验证操作,这里有负责验证签名参数
try {
validator.validate(param);
@@ -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/gateway/param/GatewayParamBuilder.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java
index dcdbe855..2867b184 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/param/GatewayParamBuilder.java
@@ -1,6 +1,6 @@
package com.gitee.sop.gatewaycommon.gateway.param;
-import com.gitee.sop.gatewaycommon.gateway.GatewayContext;
+import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil;
import com.gitee.sop.gatewaycommon.param.BaseParamBuilder;
import org.springframework.web.server.ServerWebExchange;
@@ -13,8 +13,8 @@ import java.util.Map;
public class GatewayParamBuilder extends BaseParamBuilder {
@Override
- public Map buildRequestParams(ServerWebExchange exchange) {
- Map params = GatewayContext.getRequestParams(exchange);
+ public Map buildRequestParams(ServerWebExchange exchange) {
+ Map params = ServerWebExchangeUtil.getRequestParams(exchange);
return params == null ? Collections.emptyMap() : params;
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
index 10ffb40e..cb8a0a86 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java
@@ -1,7 +1,6 @@
package com.gitee.sop.gatewaycommon.gateway.route;
-import com.gitee.sop.gatewaycommon.bean.SopConstants;
-import com.gitee.sop.gatewaycommon.gateway.GatewayContext;
+import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil;
import com.gitee.sop.gatewaycommon.param.ParamNames;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
@@ -45,14 +44,17 @@ public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFact
public Predicate apply(Config config) {
return exchange -> {
- Map params = GatewayContext.getRequestParams(exchange);
+ Map params = ServerWebExchangeUtil.getRequestParams(exchange);
if (CollectionUtils.isEmpty(params)) {
return false;
}
String nameVersion = config.param;
- String name = params.getOrDefault(ParamNames.API_NAME, SopConstants.UNKNOWN_METHOD);
- String version = params.getOrDefault(ParamNames.VERSION_NAME, "");
- return (name + version).equals(nameVersion);
+ Object name = params.get(ParamNames.API_NAME);
+ Object version = params.get(ParamNames.VERSION_NAME);
+ if (name == null || version == null) {
+ return false;
+ }
+ return (name.toString() + version).equals(nameVersion);
};
}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java
index 9b01bd32..af742251 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/AbstractConfiguration.java
@@ -6,6 +6,7 @@ import com.gitee.sop.gatewaycommon.bean.BeanInitializer;
import com.gitee.sop.gatewaycommon.bean.SpringContext;
import com.gitee.sop.gatewaycommon.limit.LimitManager;
import com.gitee.sop.gatewaycommon.message.ErrorFactory;
+import com.gitee.sop.gatewaycommon.param.ParameterFormatter;
import com.gitee.sop.gatewaycommon.secret.IsvManager;
import com.gitee.sop.gatewaycommon.session.SessionManager;
import com.gitee.sop.gatewaycommon.validate.Validator;
@@ -93,6 +94,13 @@ public class AbstractConfiguration implements ApplicationContextAware {
return ApiConfig.getInstance().getSessionManager();
}
+ @Bean
+ @ConditionalOnMissingBean
+ ParameterFormatter sopParameterFormatter(){
+ return ApiConfig.getInstance().getParameterFormatter();
+ }
+
+
/**
* 跨域过滤器
*
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ParameterFormatter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/Formatter.java
similarity index 82%
rename from sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ParameterFormatter.java
rename to sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/Formatter.java
index 8fd2caf7..697f2ec8 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/ParameterFormatter.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/manager/Formatter.java
@@ -7,7 +7,7 @@ import java.util.Map;
*
* @author tanghc
*/
-public interface ParameterFormatter> {
+public interface Formatter> {
/**
* 参数格式化,即动态修改请求参数
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/FormHttpOutputMessage.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/FormHttpOutputMessage.java
new file mode 100644
index 00000000..b32123fa
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/FormHttpOutputMessage.java
@@ -0,0 +1,33 @@
+package com.gitee.sop.gatewaycommon.param;
+
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpOutputMessage;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * @author tanghc
+ */
+public class FormHttpOutputMessage implements HttpOutputMessage {
+
+ private HttpHeaders headers = new HttpHeaders();
+ private ByteArrayOutputStream output = new ByteArrayOutputStream();
+
+ @Override
+ public HttpHeaders getHeaders() {
+ return this.headers;
+ }
+
+ @Override
+ public OutputStream getBody() throws IOException {
+ return this.output;
+ }
+
+ public byte[] getInput() throws IOException {
+ this.output.flush();
+ return this.output.toByteArray();
+ }
+
+}
\ No newline at end of file
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ParameterFormatter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ParameterFormatter.java
new file mode 100644
index 00000000..92a7f7f6
--- /dev/null
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/param/ParameterFormatter.java
@@ -0,0 +1,10 @@
+package com.gitee.sop.gatewaycommon.param;
+
+import com.alibaba.fastjson.JSONObject;
+import com.gitee.sop.gatewaycommon.manager.Formatter;
+
+/**
+ * @author tanghc
+ */
+public interface ParameterFormatter extends Formatter {
+}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java
index ed1a51ce..04315a71 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java
@@ -1,6 +1,7 @@
package com.gitee.sop.gatewaycommon.util;
import com.alibaba.fastjson.JSON;
+import com.gitee.sop.gatewaycommon.bean.SopConstants;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
@@ -14,7 +15,10 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.URLDecoder;
+import java.net.URLEncoder;
import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -67,6 +71,31 @@ public class RequestUtil {
return params;
}
+ /**
+ * 将map参数转换成查询参数
+ * @return 返回aa=1&b=c...
+ */
+ public static String convertMapToQueryString(Map apiParam) {
+ List list = new ArrayList<>(apiParam.size());
+ try {
+ for (Map.Entry entry : apiParam.entrySet()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ if (value instanceof Collection) {
+ Collection collection = (Collection) value;
+ for (Object el : collection) {
+ list.add(key + "=" + URLEncoder.encode(String.valueOf(el), SopConstants.UTF8));
+ }
+ } else {
+ list.add(key + "=" + URLEncoder.encode(String.valueOf(value), SopConstants.UTF8));
+ }
+ }
+ } catch (UnsupportedEncodingException e) {
+ log.error("字符集不支持", e);
+ }
+ return org.apache.commons.lang.StringUtils.join(list, "&");
+ }
+
/**
* request中的参数转换成map
*
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java
index e93c5a33..f0470ec0 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/configuration/BaseZuulConfiguration.java
@@ -1,10 +1,8 @@
package com.gitee.sop.gatewaycommon.zuul.configuration;
-import com.alibaba.fastjson.JSONObject;
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
import com.gitee.sop.gatewaycommon.bean.ApiContext;
import com.gitee.sop.gatewaycommon.manager.AbstractConfiguration;
-import com.gitee.sop.gatewaycommon.manager.ParameterFormatter;
import com.gitee.sop.gatewaycommon.manager.RouteRepositoryContext;
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
import com.gitee.sop.gatewaycommon.zuul.filter.ErrorFilter;
@@ -47,12 +45,6 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
return ApiConfig.getInstance().getZuulParamBuilder();
}
- @Bean
- @ConditionalOnMissingBean
- ParameterFormatter preParamFilter(){
- return ApiConfig.getInstance().getZuulParameterFormatter();
- }
-
/**
* 路由存储
* @return
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/PreParameterFormatterFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreParameterFormatterFilter.java
index 9f88470c..e7f725b4 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreParameterFormatterFilter.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/PreParameterFormatterFilter.java
@@ -2,8 +2,8 @@ package com.gitee.sop.gatewaycommon.zuul.filter;
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 com.gitee.sop.gatewaycommon.zuul.param.ZuulParameterFormatter;
import com.gitee.sop.gatewaycommon.zuul.param.ZuulParameterUtil;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
@@ -17,7 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired;
public class PreParameterFormatterFilter extends BaseZuulFilter {
@Autowired(required = false)
- private ZuulParameterFormatter zuulParameterFormatter;
+ private ParameterFormatter sopParameterFormatter;
@Override
protected FilterType getFilterType() {
@@ -33,8 +33,8 @@ public class PreParameterFormatterFilter extends BaseZuulFilter {
protected Object doRun(RequestContext requestContext) throws ZuulException {
ApiParam apiParam = ZuulContext.getApiParam();
// 校验成功后进行参数转换
- if (zuulParameterFormatter != null) {
- ZuulParameterUtil.format(apiParam, zuulParameterFormatter::format);
+ if (sopParameterFormatter != null) {
+ ZuulParameterUtil.format(apiParam, sopParameterFormatter::format);
requestContext.addZuulRequestHeader(ParamNames.HEADER_VERSION_NAME, apiParam.fetchVersion());
}
return null;
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
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterFormatter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterFormatter.java
deleted file mode 100644
index 23885acd..00000000
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterFormatter.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.gitee.sop.gatewaycommon.zuul.param;
-
-import com.alibaba.fastjson.JSONObject;
-import com.gitee.sop.gatewaycommon.manager.ParameterFormatter;
-
-/**
- * @author tanghc
- */
-public interface ZuulParameterFormatter extends ParameterFormatter {
-}
diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterUtil.java
index d8e29c8d..ed8158ad 100644
--- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterUtil.java
+++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/param/ZuulParameterUtil.java
@@ -2,7 +2,7 @@ package com.gitee.sop.gatewaycommon.zuul.param;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
-import com.gitee.sop.gatewaycommon.bean.SopConstants;
+import com.gitee.sop.gatewaycommon.param.FormHttpOutputMessage;
import com.gitee.sop.gatewaycommon.util.RequestUtil;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.HttpServletRequestWrapper;
@@ -10,9 +10,7 @@ import com.netflix.zuul.http.ServletInputStreamWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.netflix.zuul.util.RequestContentDataExtractor;
-import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
-import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.util.MultiValueMap;
@@ -21,14 +19,8 @@ import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -63,24 +55,7 @@ public class ZuulParameterUtil {
byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
requestContext.setRequest(new ChangeParamsHttpServletRequestWrapper(request, bytes));
} else if(StringUtils.containsIgnoreCase(contentType, MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
- List list = new ArrayList<>(apiParam.size());
- try {
- for (Map.Entry entry : apiParam.entrySet()) {
- String key = entry.getKey();
- Object value = entry.getValue();
- if (value instanceof Collection) {
- Collection collection = (Collection) value;
- for (Object el : collection) {
- list.add(key + "=" + URLEncoder.encode(String.valueOf(el), SopConstants.UTF8));
- }
- } else {
- list.add(key + "=" + URLEncoder.encode(String.valueOf(value), SopConstants.UTF8));
- }
- }
- } catch (UnsupportedEncodingException e) {
- log.error("字符集不支持", e);
- }
- String paramsStr = StringUtils.join(list, "&");
+ String paramsStr = RequestUtil.convertMapToQueryString(apiParam);
byte[] data = paramsStr.getBytes(StandardCharsets.UTF_8);
requestContext.setRequest(new ChangeParamsHttpServletRequestWrapper(request, data));
} else if(RequestUtil.isMultipart(request)) {
@@ -128,29 +103,6 @@ public class ZuulParameterUtil {
}
}
-
- private static class FormHttpOutputMessage implements HttpOutputMessage {
-
- private HttpHeaders headers = new HttpHeaders();
- private ByteArrayOutputStream output = new ByteArrayOutputStream();
-
- @Override
- public HttpHeaders getHeaders() {
- return this.headers;
- }
-
- @Override
- public OutputStream getBody() throws IOException {
- return this.output;
- }
-
- public byte[] getInput() throws IOException {
- this.output.flush();
- return this.output.toByteArray();
- }
-
- }
-
private static class ChangeParamsHttpServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] data;
diff --git a/sop-common/sop-registry-api/pom.xml b/sop-common/sop-registry-api/pom.xml
index 167b691d..a7a89cde 100644
--- a/sop-common/sop-registry-api/pom.xml
+++ b/sop-common/sop-registry-api/pom.xml
@@ -5,7 +5,7 @@
4.0.0
com.gitee.sop
sop-registry-api
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT
UTF-8
diff --git a/sop-common/sop-service-common/pom.xml b/sop-common/sop-service-common/pom.xml
index 89b0d9eb..f22638cb 100644
--- a/sop-common/sop-service-common/pom.xml
+++ b/sop-common/sop-service-common/pom.xml
@@ -6,11 +6,11 @@
com.gitee.sop
sop-common
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT
../pom.xml
sop-service-common
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT
jar
sop-service-common
diff --git a/sop-example/sop-auth/pom.xml b/sop-example/sop-auth/pom.xml
index 1f268e44..50ccf8c2 100644
--- a/sop-example/sop-auth/pom.xml
+++ b/sop-example/sop-auth/pom.xml
@@ -26,7 +26,7 @@
com.gitee.sop
sop-service-common
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT
org.springframework.cloud
diff --git a/sop-example/sop-book/sop-book-web/pom.xml b/sop-example/sop-book/sop-book-web/pom.xml
index 08b2e25f..e17aef98 100644
--- a/sop-example/sop-book/sop-book-web/pom.xml
+++ b/sop-example/sop-book/sop-book-web/pom.xml
@@ -24,7 +24,7 @@
com.gitee.sop
sop-service-common
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT
com.gitee.sop
diff --git a/sop-example/sop-easyopen/pom.xml b/sop-example/sop-easyopen/pom.xml
index b6fd5e41..1e2d9bfc 100644
--- a/sop-example/sop-easyopen/pom.xml
+++ b/sop-example/sop-easyopen/pom.xml
@@ -29,7 +29,7 @@
com.gitee.sop
sop-service-common
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT
org.springframework.cloud
diff --git a/sop-example/sop-springmvc/pom.xml b/sop-example/sop-springmvc/pom.xml
index a318d6e0..8596a4d6 100644
--- a/sop-example/sop-springmvc/pom.xml
+++ b/sop-example/sop-springmvc/pom.xml
@@ -20,7 +20,7 @@
com.gitee.sop
sop-service-common
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT
diff --git a/sop-example/sop-story/sop-story-web/pom.xml b/sop-example/sop-story/sop-story-web/pom.xml
index c1b2f763..f800e269 100644
--- a/sop-example/sop-story/sop-story-web/pom.xml
+++ b/sop-example/sop-story/sop-story-web/pom.xml
@@ -24,7 +24,7 @@
com.gitee.sop
sop-service-common
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT
com.gitee.sop
diff --git a/sop-gateway/pom.xml b/sop-gateway/pom.xml
index b68791c7..4146a1c0 100644
--- a/sop-gateway/pom.xml
+++ b/sop-gateway/pom.xml
@@ -23,7 +23,7 @@
com.gitee.sop
sop-gateway-common
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT
diff --git a/sop-website/website-server/pom.xml b/sop-website/website-server/pom.xml
index 45186dfc..015d1e65 100644
--- a/sop-website/website-server/pom.xml
+++ b/sop-website/website-server/pom.xml
@@ -25,7 +25,7 @@
com.gitee.sop
sop-registry-api
- 1.15.1-SNAPSHOT
+ 1.15.2-SNAPSHOT