mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
gateway动态修改参数
This commit is contained in:
@@ -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";
|
||||
|
@@ -3,24 +3,27 @@ package com.gitee.sop.gatewaycommon.gateway;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.gitee.sop.gatewaycommon.bean.SopConstants;
|
||||
import com.gitee.sop.gatewaycommon.gateway.common.FileUploadHttpServletRequest;
|
||||
import com.gitee.sop.gatewaycommon.gateway.common.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 io.netty.buffer.ByteBufAllocator;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.NettyDataBufferFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.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 org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.URI;
|
||||
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;
|
||||
@@ -32,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 返回请求参数
|
||||
*/
|
||||
@@ -45,6 +52,7 @@ public class ServerWebExchangeUtil {
|
||||
|
||||
/**
|
||||
* 设置请求参数
|
||||
*
|
||||
* @param exchange ServerWebExchange
|
||||
* @param apiParam 请求参数
|
||||
*/
|
||||
@@ -54,6 +62,7 @@ public class ServerWebExchangeUtil {
|
||||
|
||||
/**
|
||||
* 获取Spring Cloud Gateway请求的原始参数。前提是要使用ReadBodyRoutePredicateFactory
|
||||
*
|
||||
* @param exchange ServerWebExchange
|
||||
* @return 没有参数返回null
|
||||
* @see com.gitee.sop.gatewaycommon.gateway.route.ReadBodyRoutePredicateFactory
|
||||
@@ -77,6 +86,7 @@ public class ServerWebExchangeUtil {
|
||||
} else if (StringUtils.containsIgnoreCase(contentTypeStr, "multipart")) {
|
||||
// 如果是文件上传请求
|
||||
HttpServletRequest fileUploadRequest = getFileUploadRequest(exchange, cachedBody);
|
||||
setFileUploadRequest(exchange, fileUploadRequest);
|
||||
params = RequestUtil.convertMultipartRequestToMap(fileUploadRequest);
|
||||
} else {
|
||||
params = RequestUtil.parseQueryToMap(cachedBody);
|
||||
@@ -89,6 +99,7 @@ public class ServerWebExchangeUtil {
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
public static Map<String, String> buildParams(MultiValueMap<String, String> queryParams) {
|
||||
if (queryParams == null || queryParams.size() == 0) {
|
||||
return null;
|
||||
@@ -102,7 +113,8 @@ public class ServerWebExchangeUtil {
|
||||
|
||||
/**
|
||||
* 添加header
|
||||
* @param exchange 当前ServerWebExchange
|
||||
*
|
||||
* @param exchange 当前ServerWebExchange
|
||||
* @param headersConsumer headers
|
||||
* @return 返回一个新的ServerWebExchange
|
||||
*/
|
||||
@@ -112,7 +124,7 @@ public class ServerWebExchangeUtil {
|
||||
.mutate()
|
||||
.headers(headersConsumer)
|
||||
.build();
|
||||
// 将现在的request 变成 change对象
|
||||
// 创建一个新的exchange对象
|
||||
return exchange
|
||||
.mutate()
|
||||
.request(serverHttpRequestNew)
|
||||
@@ -122,23 +134,32 @@ public class ServerWebExchangeUtil {
|
||||
/**
|
||||
* 获取一个文件上传request
|
||||
*
|
||||
* @param exchange 当前ServerWebExchange
|
||||
* @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);
|
||||
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 exchange ServerWebExchange
|
||||
* @param apiParam 原始请求参数
|
||||
* @param paramsConsumer 执行参数更改
|
||||
* @param headerConsumer header更改
|
||||
* @param <T> 参数类型
|
||||
* @return 返回新的ServerWebExchange,参数没有被修改则返回null
|
||||
* @param <T> 参数类型
|
||||
* @return 返回新的ServerWebExchange
|
||||
*/
|
||||
public static <T extends Map<String, Object>> ServerWebExchange format(
|
||||
ServerWebExchange exchange
|
||||
@@ -147,55 +168,72 @@ public class ServerWebExchangeUtil {
|
||||
, 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) {
|
||||
return null;
|
||||
mediaType = MediaType.APPLICATION_FORM_URLENCODED;
|
||||
}
|
||||
paramsConsumer.accept(apiParam);
|
||||
String contentType = mediaType.toString().toLowerCase();
|
||||
// 修改后的请求体
|
||||
// 处理json请求(application/json)
|
||||
if (StringUtils.containsAny(contentType, "json", "text")) {
|
||||
//下面的将请求体再次封装写回到request里,传到下一级,否则,由于请求体已被消费,后续的服务将取不到值
|
||||
URI uri = serverHttpRequest.getURI();
|
||||
URI newUri = UriComponentsBuilder.fromUri(uri).build(true).toUri();
|
||||
ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri).build();
|
||||
|
||||
// 定义新的消息头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.putAll(exchange.getRequest().getHeaders());
|
||||
|
||||
// 自定义header
|
||||
headerConsumer.accept(headers);
|
||||
// 修改后的请求体
|
||||
String bodyStr = JSON.toJSONString(apiParam);
|
||||
byte[] bodyStrBytes = bodyStr.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
// 由于post的body只能订阅一次,由于上面代码中已经订阅过一次body。
|
||||
// 所以要再次封装请求到request才行,不然会报错请求已经订阅过
|
||||
request = new SopServerHttpRequestDecorator(request, bodyStrBytes, headers);
|
||||
|
||||
return exchange.mutate().request(request).build();
|
||||
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);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转DataBuffer
|
||||
* @param value 值
|
||||
* @return 返回buffer
|
||||
*/
|
||||
private static DataBuffer stringBuffer(String value) {
|
||||
byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
|
||||
NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
|
||||
DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
|
||||
buffer.write(bytes);
|
||||
return buffer;
|
||||
HttpHeaders headers = newRequest.getHeaders();
|
||||
// 自定义header
|
||||
headerConsumer.accept(headers);
|
||||
// 创建一个新的exchange
|
||||
return exchange.mutate().request(newRequest).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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<String> getParameterNames() {
|
||||
return null;
|
||||
return Collections.emptyEnumeration();
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
@@ -4,37 +4,73 @@ 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> bodyData;
|
||||
private Flux<DataBuffer> bodyDataBuffer;
|
||||
private HttpHeaders httpHeaders;
|
||||
private URI uri;
|
||||
|
||||
public SopServerHttpRequestDecorator(ServerHttpRequest delegate, byte[] bodyData, HttpHeaders httpHeaders) {
|
||||
/**
|
||||
* ServerHttpRequest包装,作用类似于HttpServletRequestWrapper
|
||||
* @param delegate 老的request
|
||||
* @param queryString get请求后面的参数
|
||||
*/
|
||||
public SopServerHttpRequestDecorator(ServerHttpRequest delegate, HttpHeaders newHeaders, String queryString) {
|
||||
super(delegate);
|
||||
if (httpHeaders == null) {
|
||||
throw new IllegalArgumentException("httpHeaders can not be null.");
|
||||
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.httpHeaders = httpHeaders;
|
||||
this.bodyData = stringBuffer(bodyData);
|
||||
this.bodyDataBuffer = stringBuffer(bodyData);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,17 +85,18 @@ public class SopServerHttpRequestDecorator extends ServerHttpRequestDecorator {
|
||||
return Flux.just(buffer);
|
||||
}
|
||||
|
||||
private SopServerHttpRequestDecorator(ServerHttpRequest delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return bodyData == null ? super.getBody() : bodyData;
|
||||
public URI getURI() {
|
||||
return uri == null ? super.getURI() : uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
return httpHeaders == null ? super.getHeaders() : httpHeaders;
|
||||
return this.httpHeaders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return bodyDataBuffer == null ? super.getBody() : bodyDataBuffer;
|
||||
}
|
||||
}
|
||||
|
@@ -35,10 +35,7 @@ public class ParameterFormatterFilter implements GlobalFilter, Ordered {
|
||||
exchange
|
||||
, apiParam
|
||||
, sopParameterFormatter::format
|
||||
, httpHeaders -> {
|
||||
httpHeaders.remove(ParamNames.HEADER_VERSION_NAME);
|
||||
httpHeaders.add(ParamNames.HEADER_VERSION_NAME, apiParam.fetchVersion());
|
||||
});
|
||||
, httpHeaders -> httpHeaders.set(ParamNames.HEADER_VERSION_NAME, apiParam.fetchVersion()));
|
||||
if (formatExchange == null) {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
}
|
@@ -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<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
|
||||
*
|
||||
|
@@ -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<String> list = new ArrayList<>(apiParam.size());
|
||||
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, "&");
|
||||
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;
|
||||
|
||||
|
Reference in New Issue
Block a user