From 0bc0432ac3c28554a4a64c2a699cc62d17599957 Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 15 Aug 2019 17:54:40 +0800 Subject: [PATCH 1/2] =?UTF-8?q?gateway=E6=94=AF=E6=8C=81=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gatewaycommon/gateway/GatewayContext.java | 78 ---- .../gateway/ServerWebExchangeUtil.java | 116 ++++++ .../common/ByteArrayStreamWrapper.java | 46 +++ .../common/FileUploadHttpServletRequest.java | 387 ++++++++++++++++++ .../gateway/common/ServletFileUploadUtil.java | 20 + .../sop/gatewaycommon/util/RequestUtil.java | 5 +- 6 files changed, 571 insertions(+), 81 deletions(-) delete mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/GatewayContext.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ByteArrayStreamWrapper.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/FileUploadHttpServletRequest.java create mode 100644 sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ServletFileUploadUtil.java diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/GatewayContext.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/GatewayContext.java deleted file mode 100644 index 8b7e2d2c..00000000 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/GatewayContext.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.gitee.sop.gatewaycommon.gateway; - -import com.gitee.sop.gatewaycommon.bean.ApiContext; -import com.gitee.sop.gatewaycommon.bean.SopConstants; -import com.gitee.sop.gatewaycommon.param.ApiParam; -import com.gitee.sop.gatewaycommon.util.RequestUtil; -import org.springframework.http.HttpMethod; -import org.springframework.util.MultiValueMap; -import org.springframework.web.server.ServerWebExchange; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_FOR_MAP; -import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_OBJECT_KEY; - -/** - * @author tanghc - */ -public class GatewayContext extends ApiContext { - - /** - * 获取请求参数 - * @param exchange - * @return - */ - public static ApiParam getApiParam(ServerWebExchange exchange) { - return exchange.getAttribute(SopConstants.CACHE_API_PARAM); - } - - /** - * 设置请求参数 - * @param exchange - * @param apiParam - */ - public static void setApiParam(ServerWebExchange exchange, ApiParam apiParam) { - exchange.getAttributes().put(SopConstants.CACHE_API_PARAM, apiParam); - } - - /** - * 获取Spring Cloud Gateway请求的原始参数。前提是要使用ReadBodyRoutePredicateFactory - * @param exchange - * @return 没有参数返回null - * @see com.gitee.sop.gatewaycommon.gateway.route.ReadBodyRoutePredicateFactory - */ - public static Map getRequestParams(ServerWebExchange exchange) { - Map params = exchange.getAttribute(CACHE_REQUEST_BODY_FOR_MAP); - if (params != null) { - return params; - } - if (exchange.getRequest().getMethod() == HttpMethod.GET) { - MultiValueMap queryParams = exchange.getRequest().getQueryParams(); - params = buildParams(queryParams); - } else { - String cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY); - if (cachedBody != null) { - params = RequestUtil.parseQueryToMap(cachedBody); - } - } - if (params != null) { - exchange.getAttributes().put(CACHE_REQUEST_BODY_FOR_MAP, params); - } - return params; - } - - private static Map buildParams(MultiValueMap queryParams) { - if (queryParams == null || queryParams.size() == 0) { - return null; - } - Map params = new HashMap<>(queryParams.size()); - for (Map.Entry> entry : queryParams.entrySet()) { - String val = entry.getValue().get(0); - params.put(entry.getKey(), val); - } - return params; - } -} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java new file mode 100644 index 00000000..e5aa91ac --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java @@ -0,0 +1,116 @@ +package com.gitee.sop.gatewaycommon.gateway; + +import com.alibaba.fastjson.JSON; +import com.gitee.sop.gatewaycommon.bean.SopConstants; +import com.gitee.sop.gatewaycommon.gateway.common.ServletFileUploadUtil; +import com.gitee.sop.gatewaycommon.param.ApiParam; +import com.gitee.sop.gatewaycommon.util.RequestUtil; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.util.MultiValueMap; +import org.springframework.web.server.ServerWebExchange; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_FOR_MAP; +import static com.gitee.sop.gatewaycommon.bean.SopConstants.CACHE_REQUEST_BODY_OBJECT_KEY; + +/** + * @author tanghc + */ +public class ServerWebExchangeUtil { + + /** + * 获取请求参数 + * @param exchange ServerWebExchange + * @return 返回请求参数 + */ + public static ApiParam getApiParam(ServerWebExchange exchange) { + return exchange.getAttribute(SopConstants.CACHE_API_PARAM); + } + + /** + * 设置请求参数 + * @param exchange ServerWebExchange + * @param apiParam 请求参数 + */ + public static void setApiParam(ServerWebExchange exchange, ApiParam apiParam) { + exchange.getAttributes().put(SopConstants.CACHE_API_PARAM, apiParam); + } + + /** + * 获取Spring Cloud Gateway请求的原始参数。前提是要使用ReadBodyRoutePredicateFactory + * @param exchange ServerWebExchange + * @return 没有参数返回null + * @see com.gitee.sop.gatewaycommon.gateway.route.ReadBodyRoutePredicateFactory + */ + public static Map getRequestParams(ServerWebExchange exchange) { + Map params = exchange.getAttribute(CACHE_REQUEST_BODY_FOR_MAP); + if (params != null) { + return params; + } + if (exchange.getRequest().getMethod() == HttpMethod.GET) { + MultiValueMap queryParams = exchange.getRequest().getQueryParams(); + params = buildParams(queryParams); + } else { + String cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY); + if (cachedBody != null) { + MediaType contentType = exchange.getRequest().getHeaders().getContentType(); + String contentTypeStr = contentType == null ? "" : contentType.toString().toLowerCase(); + // 如果是json方式提交 + if (StringUtils.containsAny(contentTypeStr, "json", "text")) { + params = JSON.parseObject(cachedBody); + } else if (StringUtils.containsIgnoreCase(contentTypeStr, "multipart")) { + // 如果是文件上传请求 + HttpServletRequest fileUploadRequest = ServletFileUploadUtil.getFileUploadRequest(exchange, cachedBody); + params = RequestUtil.convertMultipartRequestToMap(fileUploadRequest); + } else { + params = RequestUtil.parseQueryToMap(cachedBody); + } + } + } + if (params != null) { + exchange.getAttributes().put(CACHE_REQUEST_BODY_FOR_MAP, params); + } + return params; + } + + public static Map buildParams(MultiValueMap queryParams) { + if (queryParams == null || queryParams.size() == 0) { + return null; + } + Map params = new HashMap<>(queryParams.size()); + for (Map.Entry> entry : queryParams.entrySet()) { + params.put(entry.getKey(), entry.getValue().get(0)); + } + return params; + } + + /** + * 添加header + * @param exchange 当前ServerWebExchange + * @param headersConsumer headers + * @return 返回一个新的ServerWebExchange + */ + public static ServerWebExchange addHeaders(ServerWebExchange exchange, Consumer headersConsumer) { + // 创建一个新的request + ServerHttpRequest serverHttpRequestNew = exchange.getRequest() + .mutate() + .headers(headersConsumer) + .build(); + // 将现在的request 变成 change对象 + return exchange + .mutate() + .request(serverHttpRequestNew) + .build(); + } + + +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ByteArrayStreamWrapper.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ByteArrayStreamWrapper.java new file mode 100644 index 00000000..57ba85d6 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ByteArrayStreamWrapper.java @@ -0,0 +1,46 @@ +package com.gitee.sop.gatewaycommon.gateway.common; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import java.io.IOException; + +public class ByteArrayStreamWrapper extends ServletInputStream { + + private byte[] data; + private int idx = 0; + + /** + * Creates a new ServletInputStreamWrapper instance. + * + * @param data a byte[] value + */ + public ByteArrayStreamWrapper(byte[] data) { + if (data == null) + data = new byte[0]; + this.data = data; + } + + @Override + public int read() throws IOException { + if (idx == data.length) + return -1; + // I have to AND the byte with 0xff in order to ensure that it is returned as an unsigned integer + // the lack of this was causing a weird bug when manually unzipping gzipped request bodies + return data[idx++] & 0xff; + } + + @Override + public boolean isFinished() { + return true; + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } +} \ No newline at end of file diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/FileUploadHttpServletRequest.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/FileUploadHttpServletRequest.java new file mode 100644 index 00000000..41218e9d --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/FileUploadHttpServletRequest.java @@ -0,0 +1,387 @@ +package com.gitee.sop.gatewaycommon.gateway.common; + +import org.springframework.http.HttpMethod; +import org.springframework.http.server.reactive.ServerHttpRequest; + +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Map; + +/** + * 上传文件的request + * + * @author tanghc + */ +public class FileUploadHttpServletRequest implements HttpServletRequest { + private ServerHttpRequest serverHttpRequest; + private byte[] data; + + public FileUploadHttpServletRequest(ServerHttpRequest serverHttpRequest, byte[] data) { + this.serverHttpRequest = serverHttpRequest; + this.data = data; + } + + @Override + public ServletInputStream getInputStream() throws IOException { + return new ByteArrayStreamWrapper(data); + } + + @Override + public int getContentLength() { + return data.length; + } + + @Override + public long getContentLengthLong() { + return data.length; + } + + @Override + public String getAuthType() { + return null; + } + + @Override + public Cookie[] getCookies() { + return new Cookie[0]; + } + + @Override + public long getDateHeader(String s) { + return 0; + } + + @Override + public String getHeader(String s) { + return null; + } + + @Override + public Enumeration getHeaders(String s) { + return null; + } + + @Override + public Enumeration getHeaderNames() { + return null; + } + + @Override + public int getIntHeader(String s) { + return 0; + } + + @Override + public String getMethod() { + return HttpMethod.POST.name(); + } + + @Override + public String getPathInfo() { + return null; + } + + @Override + public String getPathTranslated() { + return null; + } + + @Override + public String getContextPath() { + return "/"; + } + + @Override + public String getQueryString() { + return null; + } + + @Override + public String getRemoteUser() { + return null; + } + + @Override + public boolean isUserInRole(String s) { + return false; + } + + @Override + public Principal getUserPrincipal() { + return null; + } + + @Override + public String getRequestedSessionId() { + return null; + } + + @Override + public String getRequestURI() { + return null; + } + + @Override + public StringBuffer getRequestURL() { + return null; + } + + @Override + public String getServletPath() { + return null; + } + + @Override + public HttpSession getSession(boolean b) { + return null; + } + + @Override + public HttpSession getSession() { + return null; + } + + @Override + public String changeSessionId() { + return null; + } + + @Override + public boolean isRequestedSessionIdValid() { + return false; + } + + @Override + public boolean isRequestedSessionIdFromCookie() { + return false; + } + + @Override + public boolean isRequestedSessionIdFromURL() { + return false; + } + + @Override + public boolean isRequestedSessionIdFromUrl() { + return false; + } + + @Override + public boolean authenticate(HttpServletResponse httpServletResponse) throws IOException, ServletException { + return false; + } + + @Override + public void login(String s, String s1) throws ServletException { + + } + + @Override + public void logout() throws ServletException { + + } + + @Override + public Collection getParts() throws IOException, ServletException { + return null; + } + + @Override + public Part getPart(String s) throws IOException, ServletException { + return null; + } + + @Override + public T upgrade(Class aClass) throws IOException, ServletException { + return null; + } + + @Override + public Object getAttribute(String s) { + return null; + } + + @Override + public Enumeration getAttributeNames() { + return null; + } + + @Override + public String getCharacterEncoding() { + return null; + } + + @Override + public void setCharacterEncoding(String s) throws UnsupportedEncodingException { + + } + + @Override + public String getContentType() { + return serverHttpRequest.getHeaders().getContentType().toString(); + } + + @Override + public String getParameter(String s) { + return null; + } + + @Override + public Enumeration getParameterNames() { + return null; + } + + @Override + public String[] getParameterValues(String s) { + return new String[0]; + } + + @Override + public Map getParameterMap() { + return null; + } + + @Override + public String getProtocol() { + return null; + } + + @Override + public String getScheme() { + return null; + } + + @Override + public String getServerName() { + return null; + } + + @Override + public int getServerPort() { + return 0; + } + + @Override + public BufferedReader getReader() throws IOException { + return null; + } + + @Override + public String getRemoteAddr() { + return null; + } + + @Override + public String getRemoteHost() { + return null; + } + + @Override + public void setAttribute(String s, Object o) { + + } + + @Override + public void removeAttribute(String s) { + + } + + @Override + public Locale getLocale() { + return null; + } + + @Override + public Enumeration getLocales() { + return null; + } + + @Override + public boolean isSecure() { + return false; + } + + @Override + public RequestDispatcher getRequestDispatcher(String s) { + return null; + } + + @Override + public String getRealPath(String s) { + return null; + } + + @Override + public int getRemotePort() { + return 0; + } + + @Override + public String getLocalName() { + return null; + } + + @Override + public String getLocalAddr() { + return null; + } + + @Override + public int getLocalPort() { + return 0; + } + + @Override + public ServletContext getServletContext() { + return null; + } + + @Override + public AsyncContext startAsync() throws IllegalStateException { + return null; + } + + @Override + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { + return null; + } + + @Override + public boolean isAsyncStarted() { + return false; + } + + @Override + public boolean isAsyncSupported() { + return false; + } + + @Override + public AsyncContext getAsyncContext() { + return null; + } + + @Override + public DispatcherType getDispatcherType() { + return null; + } +} \ No newline at end of file diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ServletFileUploadUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ServletFileUploadUtil.java new file mode 100644 index 00000000..9cb299c6 --- /dev/null +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/ServletFileUploadUtil.java @@ -0,0 +1,20 @@ +package com.gitee.sop.gatewaycommon.gateway.common; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.server.ServerWebExchange; + +import javax.servlet.http.HttpServletRequest; +import java.nio.charset.StandardCharsets; + +/** + * @author tanghc + */ +@Slf4j +public class ServletFileUploadUtil { + + public static HttpServletRequest getFileUploadRequest(ServerWebExchange exchange, String requestBody) { + byte[] data = requestBody.getBytes(StandardCharsets.UTF_8); + return new FileUploadHttpServletRequest(exchange.getRequest(), data); + } + +} diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java index 97a3d361..ed1a51ce 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/util/RequestUtil.java @@ -101,9 +101,8 @@ public class RequestUtil { * @return 返回表单中的字段内容 */ public static Map convertMultipartRequestToMap(HttpServletRequest request) { - DiskFileItemFactory factory = new DiskFileItemFactory(); - //2、创建一个文件上传解析器 - ServletFileUpload upload = new ServletFileUpload(factory); + // 创建一个文件上传解析器 + ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory()); Map params = new HashMap<>(16); try { List fileItems = upload.parseRequest(request); From 27033a7d0a324374d27bcc2d6fe9dd4bc0eb99c9 Mon Sep 17 00:00:00 2001 From: tanghc Date: Thu, 15 Aug 2019 18:00:19 +0800 Subject: [PATCH 2/2] =?UTF-8?q?gateway=E6=94=AF=E6=8C=81=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/FileUploadHttpServletRequest.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/FileUploadHttpServletRequest.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/FileUploadHttpServletRequest.java index 41218e9d..0a316372 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/FileUploadHttpServletRequest.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/common/FileUploadHttpServletRequest.java @@ -55,6 +55,14 @@ public class FileUploadHttpServletRequest implements HttpServletRequest { return data.length; } + /** + * 最关键这个要返回正确 + */ + @Override + public String getContentType() { + return serverHttpRequest.getHeaders().getContentType().toString(); + } + @Override public String getAuthType() { return null; @@ -235,11 +243,6 @@ public class FileUploadHttpServletRequest implements HttpServletRequest { } - @Override - public String getContentType() { - return serverHttpRequest.getHeaders().getContentType().toString(); - } - @Override public String getParameter(String s) { return null;