mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-12 07:02:14 +08:00
Merge branch 'master' into registry-nacos
This commit is contained in:
@@ -1,5 +1,10 @@
|
|||||||
# changelog
|
# changelog
|
||||||
|
|
||||||
|
## 1.15.2
|
||||||
|
|
||||||
|
- 优化SpringCloudGateway上传文件功能
|
||||||
|
- 优化SpringCloudGateway动态修改参数功能
|
||||||
|
|
||||||
## 1.15.1
|
## 1.15.1
|
||||||
|
|
||||||
- 修复未配置正确MessageConverter导致的异常
|
- 修复未配置正确MessageConverter导致的异常
|
||||||
|
@@ -1,34 +1,34 @@
|
|||||||
* [首页](/?t=1565767132305)
|
* [首页](/?t=1565916799573)
|
||||||
* 开发文档
|
* 开发文档
|
||||||
* [快速体验](files/10010_快速体验.md?t=1565767132307)
|
* [快速体验](files/10010_快速体验.md?t=1565916799577)
|
||||||
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1565767132325)
|
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1565916799596)
|
||||||
* [新增接口](files/10020_新增接口.md?t=1565767132325)
|
* [新增接口](files/10020_新增接口.md?t=1565916799596)
|
||||||
* [业务参数校验](files/10030_业务参数校验.md?t=1565767132325)
|
* [业务参数校验](files/10030_业务参数校验.md?t=1565916799596)
|
||||||
* [错误处理](files/10040_错误处理.md?t=1565767132325)
|
* [错误处理](files/10040_错误处理.md?t=1565916799596)
|
||||||
* [编写文档](files/10041_编写文档.md?t=1565767132326)
|
* [编写文档](files/10041_编写文档.md?t=1565916799596)
|
||||||
* [接口交互详解](files/10050_接口交互详解.md?t=1565767132326)
|
* [接口交互详解](files/10050_接口交互详解.md?t=1565916799597)
|
||||||
* [easyopen支持](files/10070_easyopen支持.md?t=1565767132326)
|
* [easyopen支持](files/10070_easyopen支持.md?t=1565916799597)
|
||||||
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1565767132326)
|
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1565916799597)
|
||||||
* [ISV管理](files/10085_ISV管理.md?t=1565767132326)
|
* [ISV管理](files/10085_ISV管理.md?t=1565916799597)
|
||||||
* [自定义路由](files/10086_自定义路由.md?t=1565767132326)
|
* [自定义路由](files/10086_自定义路由.md?t=1565916799597)
|
||||||
* [自定义返回结果](files/10087_自定义返回结果.md?t=1565767132326)
|
* [自定义返回结果](files/10087_自定义返回结果.md?t=1565916799597)
|
||||||
* [自定义过滤器](files/10088_自定义过滤器.md?t=1565767132326)
|
* [自定义过滤器](files/10088_自定义过滤器.md?t=1565916799597)
|
||||||
* [路由授权](files/10090_路由授权.md?t=1565767132326)
|
* [路由授权](files/10090_路由授权.md?t=1565916799598)
|
||||||
* [接口限流](files/10092_接口限流.md?t=1565767132326)
|
* [接口限流](files/10092_接口限流.md?t=1565916799598)
|
||||||
* [监控日志](files/10093_监控日志.md?t=1565767132327)
|
* [监控日志](files/10093_监控日志.md?t=1565916799598)
|
||||||
* [SDK开发](files/10095_SDK开发.md?t=1565767132327)
|
* [SDK开发](files/10095_SDK开发.md?t=1565916799598)
|
||||||
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1565767132327)
|
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1565916799598)
|
||||||
* [应用授权](files/10097_应用授权.md?t=1565767132327)
|
* [应用授权](files/10097_应用授权.md?t=1565916799598)
|
||||||
* [传统web开发](files/10100_传统web开发.md?t=1565767132327)
|
* [传统web开发](files/10100_传统web开发.md?t=1565916799598)
|
||||||
* [文件上传](files/10104_文件上传.md?t=1565767132327)
|
* [文件上传](files/10104_文件上传.md?t=1565916799598)
|
||||||
* [nacos注册中心](files/10106_nacos注册中心.md?t=1565767132327)
|
* [nacos注册中心](files/10106_nacos注册中心.md?t=1565916799599)
|
||||||
* [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1565767132327)
|
* [扩展其它注册中心](files/10107_扩展其它注册中心.md?t=1565916799599)
|
||||||
* [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1565767132327)
|
* [配置Sleuth链路追踪](files/10109_配置Sleuth链路追踪.md?t=1565916799599)
|
||||||
* [预发布灰度发布](files/10110_预发布灰度发布.md?t=1565767132327)
|
* [预发布灰度发布](files/10110_预发布灰度发布.md?t=1565916799599)
|
||||||
* [动态修改请求参数](files/10111_动态修改请求参数.md?t=1565767132327)
|
* [动态修改请求参数](files/10111_动态修改请求参数.md?t=1565916799599)
|
||||||
* 原理分析
|
* 原理分析
|
||||||
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1565767132328)
|
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1565916799599)
|
||||||
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1565767132328)
|
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1565916799599)
|
||||||
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1565767132328)
|
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1565916799599)
|
||||||
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1565767132328)
|
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1565916799600)
|
||||||
* [常见问题](files/90100_常见问题.md?t=1565767132328)
|
* [常见问题](files/90100_常见问题.md?t=1565916799600)
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
```java
|
```java
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
ApiConfig.getInstance().setZuulParameterFormatter(requestParams -> {
|
ApiConfig.getInstance().setParameterFormatter(requestParams -> {
|
||||||
// 获取biz_content
|
// 获取biz_content
|
||||||
JSONObject jsonObject = requestParams.getJSONObject(ParamNames.BIZ_CONTENT_NAME);
|
JSONObject jsonObject = requestParams.getJSONObject(ParamNames.BIZ_CONTENT_NAME);
|
||||||
// 修改biz_content中的值
|
// 修改biz_content中的值
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-registry-api</artifactId>
|
<artifactId>sop-registry-api</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- easyopen starter -->
|
<!-- easyopen starter -->
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-common</artifactId>
|
<artifactId>sop-common</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -5,11 +5,11 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-common</artifactId>
|
<artifactId>sop-common</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>sop-gateway-common</artifactId>
|
<artifactId>sop-gateway-common</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>sop-gateway-common</name>
|
<name>sop-gateway-common</name>
|
||||||
|
@@ -18,6 +18,7 @@ import com.gitee.sop.gatewaycommon.manager.LimitConfigManager;
|
|||||||
import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
|
import com.gitee.sop.gatewaycommon.manager.RouteConfigManager;
|
||||||
import com.gitee.sop.gatewaycommon.manager.ServiceErrorManager;
|
import com.gitee.sop.gatewaycommon.manager.ServiceErrorManager;
|
||||||
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
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.DataNameBuilder;
|
||||||
import com.gitee.sop.gatewaycommon.result.DefaultDataNameBuilder;
|
import com.gitee.sop.gatewaycommon.result.DefaultDataNameBuilder;
|
||||||
import com.gitee.sop.gatewaycommon.result.ResultAppender;
|
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.validate.Validator;
|
||||||
import com.gitee.sop.gatewaycommon.zuul.configuration.ZuulErrorController;
|
import com.gitee.sop.gatewaycommon.zuul.configuration.ZuulErrorController;
|
||||||
import com.gitee.sop.gatewaycommon.zuul.param.ZuulParamBuilder;
|
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.gitee.sop.gatewaycommon.zuul.result.ZuulResultExecutor;
|
||||||
import com.netflix.zuul.context.RequestContext;
|
import com.netflix.zuul.context.RequestContext;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -150,7 +150,7 @@ public class ApiConfig {
|
|||||||
*/
|
*/
|
||||||
private ZuulErrorController zuulErrorController = new ZuulErrorController();
|
private ZuulErrorController zuulErrorController = new ZuulErrorController();
|
||||||
|
|
||||||
private ZuulParameterFormatter zuulParameterFormatter;
|
private ParameterFormatter parameterFormatter;
|
||||||
|
|
||||||
// -------- fields ---------
|
// -------- fields ---------
|
||||||
|
|
||||||
|
@@ -34,6 +34,8 @@ public class SopConstants {
|
|||||||
|
|
||||||
public static final String CACHE_API_PARAM = "cacheApiParam";
|
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_CODE = "x-service-error-code";
|
||||||
|
|
||||||
public static final String X_SERVICE_ERROR_MESSAGE = "x-service-error-message";
|
public static final String X_SERVICE_ERROR_MESSAGE = "x-service-error-message";
|
||||||
|
@@ -2,18 +2,28 @@ package com.gitee.sop.gatewaycommon.gateway;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
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.ApiParam;
|
||||||
|
import com.gitee.sop.gatewaycommon.param.FormHttpOutputMessage;
|
||||||
import com.gitee.sop.gatewaycommon.util.RequestUtil;
|
import com.gitee.sop.gatewaycommon.util.RequestUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.converter.FormHttpMessageConverter;
|
||||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
import org.springframework.util.MultiValueMap;
|
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 org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
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.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -25,10 +35,14 @@ import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_O
|
|||||||
/**
|
/**
|
||||||
* @author tanghc
|
* @author tanghc
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class ServerWebExchangeUtil {
|
public class ServerWebExchangeUtil {
|
||||||
|
|
||||||
|
private static FormHttpMessageConverter formHttpMessageConverter = new FormHttpMessageConverter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取请求参数
|
* 获取请求参数
|
||||||
|
*
|
||||||
* @param exchange ServerWebExchange
|
* @param exchange ServerWebExchange
|
||||||
* @return 返回请求参数
|
* @return 返回请求参数
|
||||||
*/
|
*/
|
||||||
@@ -38,6 +52,7 @@ public class ServerWebExchangeUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置请求参数
|
* 设置请求参数
|
||||||
|
*
|
||||||
* @param exchange ServerWebExchange
|
* @param exchange ServerWebExchange
|
||||||
* @param apiParam 请求参数
|
* @param apiParam 请求参数
|
||||||
*/
|
*/
|
||||||
@@ -47,6 +62,7 @@ public class ServerWebExchangeUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取Spring Cloud Gateway请求的原始参数。前提是要使用ReadBodyRoutePredicateFactory
|
* 获取Spring Cloud Gateway请求的原始参数。前提是要使用ReadBodyRoutePredicateFactory
|
||||||
|
*
|
||||||
* @param exchange ServerWebExchange
|
* @param exchange ServerWebExchange
|
||||||
* @return 没有参数返回null
|
* @return 没有参数返回null
|
||||||
* @see com.gitee.sop.gatewaycommon.gateway.route.ReadBodyRoutePredicateFactory
|
* @see com.gitee.sop.gatewaycommon.gateway.route.ReadBodyRoutePredicateFactory
|
||||||
@@ -69,7 +85,8 @@ public class ServerWebExchangeUtil {
|
|||||||
params = JSON.parseObject(cachedBody);
|
params = JSON.parseObject(cachedBody);
|
||||||
} else if (StringUtils.containsIgnoreCase(contentTypeStr, "multipart")) {
|
} else if (StringUtils.containsIgnoreCase(contentTypeStr, "multipart")) {
|
||||||
// 如果是文件上传请求
|
// 如果是文件上传请求
|
||||||
HttpServletRequest fileUploadRequest = ServletFileUploadUtil.getFileUploadRequest(exchange, cachedBody);
|
HttpServletRequest fileUploadRequest = getFileUploadRequest(exchange, cachedBody);
|
||||||
|
setFileUploadRequest(exchange, fileUploadRequest);
|
||||||
params = RequestUtil.convertMultipartRequestToMap(fileUploadRequest);
|
params = RequestUtil.convertMultipartRequestToMap(fileUploadRequest);
|
||||||
} else {
|
} else {
|
||||||
params = RequestUtil.parseQueryToMap(cachedBody);
|
params = RequestUtil.parseQueryToMap(cachedBody);
|
||||||
@@ -82,6 +99,7 @@ public class ServerWebExchangeUtil {
|
|||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Map<String, String> buildParams(MultiValueMap<String, String> queryParams) {
|
public static Map<String, String> buildParams(MultiValueMap<String, String> queryParams) {
|
||||||
if (queryParams == null || queryParams.size() == 0) {
|
if (queryParams == null || queryParams.size() == 0) {
|
||||||
return null;
|
return null;
|
||||||
@@ -95,7 +113,8 @@ public class ServerWebExchangeUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加header
|
* 添加header
|
||||||
* @param exchange 当前ServerWebExchange
|
*
|
||||||
|
* @param exchange 当前ServerWebExchange
|
||||||
* @param headersConsumer headers
|
* @param headersConsumer headers
|
||||||
* @return 返回一个新的ServerWebExchange
|
* @return 返回一个新的ServerWebExchange
|
||||||
*/
|
*/
|
||||||
@@ -105,12 +124,116 @@ public class ServerWebExchangeUtil {
|
|||||||
.mutate()
|
.mutate()
|
||||||
.headers(headersConsumer)
|
.headers(headersConsumer)
|
||||||
.build();
|
.build();
|
||||||
// 将现在的request 变成 change对象
|
// 创建一个新的exchange对象
|
||||||
return exchange
|
return exchange
|
||||||
.mutate()
|
.mutate()
|
||||||
.request(serverHttpRequestNew)
|
.request(serverHttpRequestNew)
|
||||||
.build();
|
.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 <T> 参数类型
|
||||||
|
* @return 返回新的ServerWebExchange
|
||||||
|
*/
|
||||||
|
public static <T extends Map<String, Object>> ServerWebExchange format(
|
||||||
|
ServerWebExchange exchange
|
||||||
|
, T apiParam
|
||||||
|
, Consumer<T> paramsConsumer
|
||||||
|
, Consumer<HttpHeaders> 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<String, Object> builder = RequestContentDataExtractor.extract(request);
|
||||||
|
for (Map.Entry<String, Object> 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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -4,13 +4,18 @@ import javax.servlet.ReadListener;
|
|||||||
import javax.servlet.ServletInputStream;
|
import javax.servlet.ServletInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte数组流包装
|
||||||
|
*
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
public class ByteArrayStreamWrapper extends ServletInputStream {
|
public class ByteArrayStreamWrapper extends ServletInputStream {
|
||||||
|
|
||||||
private byte[] data;
|
private byte[] data;
|
||||||
private int idx = 0;
|
private int idx = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new <code>ServletInputStreamWrapper</code> instance.
|
* Creates a new <code>ByteArrayStreamWrapper</code> instance.
|
||||||
*
|
*
|
||||||
* @param data a <code>byte[]</code> value
|
* @param data a <code>byte[]</code> value
|
||||||
*/
|
*/
|
||||||
|
@@ -22,6 +22,7 @@ import java.io.IOException;
|
|||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -250,7 +251,7 @@ public class FileUploadHttpServletRequest implements HttpServletRequest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Enumeration<String> getParameterNames() {
|
public Enumeration<String> getParameterNames() {
|
||||||
return null;
|
return Collections.emptyEnumeration();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -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<String, Object> extract(HttpServletRequest request) throws IOException {
|
||||||
|
return (request instanceof MultipartHttpServletRequest) ?
|
||||||
|
extractFromMultipartRequest((MultipartHttpServletRequest) request) :
|
||||||
|
extractFromRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MultiValueMap<String, Object> extractFromRequest(HttpServletRequest request) throws IOException {
|
||||||
|
MultiValueMap<String, Object> builder = new LinkedMultiValueMap<>();
|
||||||
|
Set<String> queryParams = findQueryParams(request);
|
||||||
|
|
||||||
|
for (Entry<String, String[]> 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<String, Object> extractFromMultipartRequest(MultipartHttpServletRequest request)
|
||||||
|
throws IOException {
|
||||||
|
MultiValueMap<String, Object> builder = new LinkedMultiValueMap<>();
|
||||||
|
Map<String, List<String>> queryParamsGroupedByName = findQueryParamsGroupedByName(
|
||||||
|
request);
|
||||||
|
Set<String> queryParams = findQueryParams(request);
|
||||||
|
|
||||||
|
for (Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
List<String> listOfAllParams = stream(request.getParameterMap().get(key))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<String> 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<String, List<MultipartFile>> 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<String> findQueryParams(HttpServletRequest request) {
|
||||||
|
Set<String> 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<String, List<String>> findQueryParamsGroupedByName(
|
||||||
|
HttpServletRequest request) {
|
||||||
|
String query = request.getQueryString();
|
||||||
|
if (isEmpty(query)) {
|
||||||
|
return emptyMap();
|
||||||
|
}
|
||||||
|
return UriComponentsBuilder.fromUriString("?" + query).build().getQueryParams();
|
||||||
|
}
|
||||||
|
}
|
@@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -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<DataBuffer> 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<DataBuffer> 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<DataBuffer> getBody() {
|
||||||
|
return bodyDataBuffer == null ? super.getBody() : bodyDataBuffer;
|
||||||
|
}
|
||||||
|
}
|
@@ -3,6 +3,7 @@ package com.gitee.sop.gatewaycommon.gateway.configuration;
|
|||||||
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||||
import com.gitee.sop.gatewaycommon.gateway.filter.GatewayModifyResponseGatewayFilter;
|
import com.gitee.sop.gatewaycommon.gateway.filter.GatewayModifyResponseGatewayFilter;
|
||||||
import com.gitee.sop.gatewaycommon.gateway.filter.LoadBalancerClientExtFilter;
|
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.filter.ValidateFilter;
|
||||||
import com.gitee.sop.gatewaycommon.gateway.handler.GatewayExceptionHandler;
|
import com.gitee.sop.gatewaycommon.gateway.handler.GatewayExceptionHandler;
|
||||||
import com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteRepository;
|
import com.gitee.sop.gatewaycommon.gateway.route.GatewayRouteRepository;
|
||||||
@@ -106,4 +107,9 @@ public class BaseGatewayConfiguration extends AbstractConfiguration {
|
|||||||
return gatewayRouteRepository;
|
return gatewayRouteRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
ParameterFormatterFilter parameterFormatterFilter() {
|
||||||
|
return new ParameterFormatterFilter();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@ package com.gitee.sop.gatewaycommon.gateway.filter;
|
|||||||
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
import com.gitee.sop.gatewaycommon.bean.ApiConfig;
|
||||||
import com.gitee.sop.gatewaycommon.bean.ConfigLimitDto;
|
import com.gitee.sop.gatewaycommon.bean.ConfigLimitDto;
|
||||||
import com.gitee.sop.gatewaycommon.exception.ApiException;
|
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.LimitManager;
|
||||||
import com.gitee.sop.gatewaycommon.limit.LimitType;
|
import com.gitee.sop.gatewaycommon.limit.LimitType;
|
||||||
import com.gitee.sop.gatewaycommon.manager.LimitConfigManager;
|
import com.gitee.sop.gatewaycommon.manager.LimitConfigManager;
|
||||||
@@ -34,7 +34,7 @@ public class LimitFilter implements GlobalFilter, Ordered {
|
|||||||
if (!apiConfig.isOpenLimit()) {
|
if (!apiConfig.isOpenLimit()) {
|
||||||
return chain.filter(exchange);
|
return chain.filter(exchange);
|
||||||
}
|
}
|
||||||
ApiParam apiParam = GatewayContext.getApiParam(exchange);
|
ApiParam apiParam = ServerWebExchangeUtil.getApiParam(exchange);
|
||||||
ConfigLimitDto configLimitDto = this.findConfigLimitDto(apiConfig, apiParam, exchange);
|
ConfigLimitDto configLimitDto = this.findConfigLimitDto(apiConfig, apiParam, exchange);
|
||||||
if (configLimitDto == null) {
|
if (configLimitDto == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -59,7 +59,7 @@ public class LimitFilter implements GlobalFilter, Ordered {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOrder() {
|
public int getOrder() {
|
||||||
return Orders.LIMIT_ORDER;
|
return Orders.LIMIT_FILTER_ORDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ConfigLimitDto findConfigLimitDto(ApiConfig apiConfig, ApiParam apiParam, ServerWebExchange exchange) {
|
protected ConfigLimitDto findConfigLimitDto(ApiConfig apiConfig, ApiParam apiParam, ServerWebExchange exchange) {
|
||||||
|
@@ -7,8 +7,18 @@ import org.springframework.core.Ordered;
|
|||||||
*/
|
*/
|
||||||
public class Orders {
|
public class Orders {
|
||||||
/** 验证拦截器order */
|
/** 验证拦截器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 */
|
/** 验证拦截器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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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<Void> 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;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
package com.gitee.sop.gatewaycommon.gateway.filter;
|
package com.gitee.sop.gatewaycommon.gateway.filter;
|
||||||
|
|
||||||
import com.gitee.sop.gatewaycommon.exception.ApiException;
|
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.ApiParam;
|
||||||
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
||||||
import com.gitee.sop.gatewaycommon.validate.Validator;
|
import com.gitee.sop.gatewaycommon.validate.Validator;
|
||||||
@@ -29,7 +29,7 @@ public class ValidateFilter implements GlobalFilter, Ordered {
|
|||||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||||
// 解析参数
|
// 解析参数
|
||||||
ApiParam param = paramBuilder.build(exchange);
|
ApiParam param = paramBuilder.build(exchange);
|
||||||
GatewayContext.setApiParam(exchange, param);
|
ServerWebExchangeUtil.setApiParam(exchange, param);
|
||||||
// 验证操作,这里有负责验证签名参数
|
// 验证操作,这里有负责验证签名参数
|
||||||
try {
|
try {
|
||||||
validator.validate(param);
|
validator.validate(param);
|
||||||
@@ -43,6 +43,6 @@ public class ValidateFilter implements GlobalFilter, Ordered {
|
|||||||
@Override
|
@Override
|
||||||
public int getOrder() {
|
public int getOrder() {
|
||||||
// 最优先执行
|
// 最优先执行
|
||||||
return Orders.VALIDATE_ORDER;
|
return Orders.VALIDATE_FILTER_ORDER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
package com.gitee.sop.gatewaycommon.gateway.param;
|
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 com.gitee.sop.gatewaycommon.param.BaseParamBuilder;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
||||||
@@ -13,8 +13,8 @@ import java.util.Map;
|
|||||||
public class GatewayParamBuilder extends BaseParamBuilder<ServerWebExchange> {
|
public class GatewayParamBuilder extends BaseParamBuilder<ServerWebExchange> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, String> buildRequestParams(ServerWebExchange exchange) {
|
public Map<String, ?> buildRequestParams(ServerWebExchange exchange) {
|
||||||
Map<String, String> params = GatewayContext.getRequestParams(exchange);
|
Map<String, ?> params = ServerWebExchangeUtil.getRequestParams(exchange);
|
||||||
return params == null ? Collections.emptyMap() : params;
|
return params == null ? Collections.emptyMap() : params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package com.gitee.sop.gatewaycommon.gateway.route;
|
package com.gitee.sop.gatewaycommon.gateway.route;
|
||||||
|
|
||||||
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil;
|
||||||
import com.gitee.sop.gatewaycommon.gateway.GatewayContext;
|
|
||||||
import com.gitee.sop.gatewaycommon.param.ParamNames;
|
import com.gitee.sop.gatewaycommon.param.ParamNames;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
|
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
|
||||||
@@ -45,14 +44,17 @@ public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFact
|
|||||||
public Predicate<ServerWebExchange> apply(Config config) {
|
public Predicate<ServerWebExchange> apply(Config config) {
|
||||||
|
|
||||||
return exchange -> {
|
return exchange -> {
|
||||||
Map<String, String> params = GatewayContext.getRequestParams(exchange);
|
Map<String, ?> params = ServerWebExchangeUtil.getRequestParams(exchange);
|
||||||
if (CollectionUtils.isEmpty(params)) {
|
if (CollectionUtils.isEmpty(params)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String nameVersion = config.param;
|
String nameVersion = config.param;
|
||||||
String name = params.getOrDefault(ParamNames.API_NAME, SopConstants.UNKNOWN_METHOD);
|
Object name = params.get(ParamNames.API_NAME);
|
||||||
String version = params.getOrDefault(ParamNames.VERSION_NAME, "");
|
Object version = params.get(ParamNames.VERSION_NAME);
|
||||||
return (name + version).equals(nameVersion);
|
if (name == null || version == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (name.toString() + version).equals(nameVersion);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,6 +6,7 @@ import com.gitee.sop.gatewaycommon.bean.BeanInitializer;
|
|||||||
import com.gitee.sop.gatewaycommon.bean.SpringContext;
|
import com.gitee.sop.gatewaycommon.bean.SpringContext;
|
||||||
import com.gitee.sop.gatewaycommon.limit.LimitManager;
|
import com.gitee.sop.gatewaycommon.limit.LimitManager;
|
||||||
import com.gitee.sop.gatewaycommon.message.ErrorFactory;
|
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.secret.IsvManager;
|
||||||
import com.gitee.sop.gatewaycommon.session.SessionManager;
|
import com.gitee.sop.gatewaycommon.session.SessionManager;
|
||||||
import com.gitee.sop.gatewaycommon.validate.Validator;
|
import com.gitee.sop.gatewaycommon.validate.Validator;
|
||||||
@@ -93,6 +94,13 @@ public class AbstractConfiguration implements ApplicationContextAware {
|
|||||||
return ApiConfig.getInstance().getSessionManager();
|
return ApiConfig.getInstance().getSessionManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
ParameterFormatter sopParameterFormatter(){
|
||||||
|
return ApiConfig.getInstance().getParameterFormatter();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 跨域过滤器
|
* 跨域过滤器
|
||||||
*
|
*
|
||||||
|
@@ -7,7 +7,7 @@ import java.util.Map;
|
|||||||
*
|
*
|
||||||
* @author tanghc
|
* @author tanghc
|
||||||
*/
|
*/
|
||||||
public interface ParameterFormatter<T extends Map<String, Object>> {
|
public interface Formatter<T extends Map<String, Object>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 参数格式化,即动态修改请求参数
|
* 参数格式化,即动态修改请求参数
|
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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<JSONObject> {
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package com.gitee.sop.gatewaycommon.util;
|
package com.gitee.sop.gatewaycommon.util;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
||||||
import org.apache.commons.fileupload.FileItem;
|
import org.apache.commons.fileupload.FileItem;
|
||||||
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
|
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
|
||||||
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||||
@@ -14,7 +15,10 @@ import java.io.IOException;
|
|||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
|
import java.net.URLEncoder;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -67,6 +71,31 @@ public class RequestUtil {
|
|||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将map参数转换成查询参数
|
||||||
|
* @return 返回aa=1&b=c...
|
||||||
|
*/
|
||||||
|
public static String convertMapToQueryString(Map<String, ?> apiParam) {
|
||||||
|
List<String> list = new ArrayList<>(apiParam.size());
|
||||||
|
try {
|
||||||
|
for (Map.Entry<String, ?> 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
|
* request中的参数转换成map
|
||||||
*
|
*
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
package com.gitee.sop.gatewaycommon.zuul.configuration;
|
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.ApiConfig;
|
||||||
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
import com.gitee.sop.gatewaycommon.bean.ApiContext;
|
||||||
import com.gitee.sop.gatewaycommon.manager.AbstractConfiguration;
|
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.manager.RouteRepositoryContext;
|
||||||
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
import com.gitee.sop.gatewaycommon.param.ParamBuilder;
|
||||||
import com.gitee.sop.gatewaycommon.zuul.filter.ErrorFilter;
|
import com.gitee.sop.gatewaycommon.zuul.filter.ErrorFilter;
|
||||||
@@ -47,12 +45,6 @@ public class BaseZuulConfiguration extends AbstractConfiguration {
|
|||||||
return ApiConfig.getInstance().getZuulParamBuilder();
|
return ApiConfig.getInstance().getZuulParamBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
ParameterFormatter<JSONObject> preParamFilter(){
|
|
||||||
return ApiConfig.getInstance().getZuulParameterFormatter();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 路由存储
|
* 路由存储
|
||||||
* @return
|
* @return
|
||||||
|
@@ -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_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;
|
private Integer filterOrder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -2,8 +2,8 @@ package com.gitee.sop.gatewaycommon.zuul.filter;
|
|||||||
|
|
||||||
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
import com.gitee.sop.gatewaycommon.param.ApiParam;
|
||||||
import com.gitee.sop.gatewaycommon.param.ParamNames;
|
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.ZuulContext;
|
||||||
import com.gitee.sop.gatewaycommon.zuul.param.ZuulParameterFormatter;
|
|
||||||
import com.gitee.sop.gatewaycommon.zuul.param.ZuulParameterUtil;
|
import com.gitee.sop.gatewaycommon.zuul.param.ZuulParameterUtil;
|
||||||
import com.netflix.zuul.context.RequestContext;
|
import com.netflix.zuul.context.RequestContext;
|
||||||
import com.netflix.zuul.exception.ZuulException;
|
import com.netflix.zuul.exception.ZuulException;
|
||||||
@@ -17,7 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
public class PreParameterFormatterFilter extends BaseZuulFilter {
|
public class PreParameterFormatterFilter extends BaseZuulFilter {
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private ZuulParameterFormatter zuulParameterFormatter;
|
private ParameterFormatter sopParameterFormatter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FilterType getFilterType() {
|
protected FilterType getFilterType() {
|
||||||
@@ -33,8 +33,8 @@ public class PreParameterFormatterFilter extends BaseZuulFilter {
|
|||||||
protected Object doRun(RequestContext requestContext) throws ZuulException {
|
protected Object doRun(RequestContext requestContext) throws ZuulException {
|
||||||
ApiParam apiParam = ZuulContext.getApiParam();
|
ApiParam apiParam = ZuulContext.getApiParam();
|
||||||
// 校验成功后进行参数转换
|
// 校验成功后进行参数转换
|
||||||
if (zuulParameterFormatter != null) {
|
if (sopParameterFormatter != null) {
|
||||||
ZuulParameterUtil.format(apiParam, zuulParameterFormatter::format);
|
ZuulParameterUtil.format(apiParam, sopParameterFormatter::format);
|
||||||
requestContext.addZuulRequestHeader(ParamNames.HEADER_VERSION_NAME, apiParam.fetchVersion());
|
requestContext.addZuulRequestHeader(ParamNames.HEADER_VERSION_NAME, apiParam.fetchVersion());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@@ -25,7 +25,7 @@ public class PreVersionDecisionFilter extends BaseZuulFilter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getFilterOrder() {
|
protected int getFilterOrder() {
|
||||||
return PRE_LIMIT_FILTER_ORDER + 1;
|
return PRE_VERSION_DECISION_FILTER_ORDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -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<JSONObject> {
|
|
||||||
}
|
|
@@ -2,7 +2,7 @@ package com.gitee.sop.gatewaycommon.zuul.param;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
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.gitee.sop.gatewaycommon.util.RequestUtil;
|
||||||
import com.netflix.zuul.context.RequestContext;
|
import com.netflix.zuul.context.RequestContext;
|
||||||
import com.netflix.zuul.http.HttpServletRequestWrapper;
|
import com.netflix.zuul.http.HttpServletRequestWrapper;
|
||||||
@@ -10,9 +10,7 @@ import com.netflix.zuul.http.ServletInputStreamWrapper;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.springframework.cloud.netflix.zuul.util.RequestContentDataExtractor;
|
import org.springframework.cloud.netflix.zuul.util.RequestContentDataExtractor;
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.HttpOutputMessage;
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.converter.FormHttpMessageConverter;
|
import org.springframework.http.converter.FormHttpMessageConverter;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
@@ -21,14 +19,8 @@ import org.springframework.web.multipart.commons.CommonsMultipartResolver;
|
|||||||
|
|
||||||
import javax.servlet.ServletInputStream;
|
import javax.servlet.ServletInputStream;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -63,24 +55,7 @@ public class ZuulParameterUtil {
|
|||||||
byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
|
byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
|
||||||
requestContext.setRequest(new ChangeParamsHttpServletRequestWrapper(request, bytes));
|
requestContext.setRequest(new ChangeParamsHttpServletRequestWrapper(request, bytes));
|
||||||
} else if(StringUtils.containsIgnoreCase(contentType, MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
|
} else if(StringUtils.containsIgnoreCase(contentType, MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
|
||||||
List<String> list = new ArrayList<>(apiParam.size());
|
String paramsStr = RequestUtil.convertMapToQueryString(apiParam);
|
||||||
try {
|
|
||||||
for (Map.Entry<String, Object> 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, "&");
|
|
||||||
byte[] data = paramsStr.getBytes(StandardCharsets.UTF_8);
|
byte[] data = paramsStr.getBytes(StandardCharsets.UTF_8);
|
||||||
requestContext.setRequest(new ChangeParamsHttpServletRequestWrapper(request, data));
|
requestContext.setRequest(new ChangeParamsHttpServletRequestWrapper(request, data));
|
||||||
} else if(RequestUtil.isMultipart(request)) {
|
} 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 static class ChangeParamsHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
||||||
private byte[] data;
|
private byte[] data;
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-registry-api</artifactId>
|
<artifactId>sop-registry-api</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
@@ -6,11 +6,11 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-common</artifactId>
|
<artifactId>sop-common</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>sop-service-common</artifactId>
|
<artifactId>sop-service-common</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>sop-service-common</name>
|
<name>sop-service-common</name>
|
||||||
|
@@ -26,7 +26,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-service-common</artifactId>
|
<artifactId>sop-service-common</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-service-common</artifactId>
|
<artifactId>sop-service-common</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
@@ -29,7 +29,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-service-common</artifactId>
|
<artifactId>sop-service-common</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-service-common</artifactId>
|
<artifactId>sop-service-common</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- eureka 服务发现 -->
|
<!-- eureka 服务发现 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-service-common</artifactId>
|
<artifactId>sop-service-common</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-gateway-common</artifactId>
|
<artifactId>sop-gateway-common</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- ↓↓↓ 使用spring cloud zuul ↓↓↓ -->
|
<!-- ↓↓↓ 使用spring cloud zuul ↓↓↓ -->
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gitee.sop</groupId>
|
<groupId>com.gitee.sop</groupId>
|
||||||
<artifactId>sop-registry-api</artifactId>
|
<artifactId>sop-registry-api</artifactId>
|
||||||
<version>1.15.1-SNAPSHOT</version>
|
<version>1.15.2-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
Reference in New Issue
Block a user