Просмотр исходного кода

update 优化 gateway filter顺序 与 代码工具封装

疯狂的狮子li 3 лет назад
Родитель
Сommit
c8dfec28cc

+ 4 - 5
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/GlobalCacheRequestFilter.java

@@ -1,10 +1,10 @@
 package com.ruoyi.gateway.filter;
 
+import com.ruoyi.gateway.utils.WebFluxUtils;
 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
 import org.springframework.cloud.gateway.filter.GlobalFilter;
 import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
 import org.springframework.core.Ordered;
-import org.springframework.http.HttpMethod;
 import org.springframework.stereotype.Component;
 import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Mono;
@@ -19,9 +19,8 @@ public class GlobalCacheRequestFilter implements GlobalFilter, Ordered {
 
     @Override
     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
-        // GET DELETE 不过滤
-        HttpMethod method = exchange.getRequest().getMethod();
-        if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE) {
+        // 只缓存json类型请求
+        if (!WebFluxUtils.isJsonRequest(exchange)) {
             return chain.filter(exchange);
         }
         return ServerWebExchangeUtils.cacheRequestBody(exchange, (serverHttpRequest) -> {
@@ -34,6 +33,6 @@ public class GlobalCacheRequestFilter implements GlobalFilter, Ordered {
 
     @Override
     public int getOrder() {
-        return 0;
+        return Ordered.HIGHEST_PRECEDENCE;
     }
 }

+ 7 - 51
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/GlobalLogFilter.java

@@ -2,29 +2,19 @@ package com.ruoyi.gateway.filter;
 
 import cn.hutool.core.map.MapUtil;
 import com.ruoyi.common.core.utils.JsonUtils;
-import com.ruoyi.common.core.utils.StringUtils;
 import com.ruoyi.gateway.config.properties.CustomGatewayProperties;
+import com.ruoyi.gateway.utils.WebFluxUtils;
 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.core.io.buffer.DataBuffer;
-import org.springframework.http.MediaType;
 import org.springframework.http.server.reactive.ServerHttpRequest;
 import org.springframework.stereotype.Component;
 import org.springframework.util.MultiValueMap;
 import org.springframework.web.server.ServerWebExchange;
-import org.springframework.web.util.UriComponentsBuilder;
-import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
-import java.net.URI;
-import java.nio.charset.StandardCharsets;
-import java.util.LinkedHashSet;
-
-import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR;
-
 /**
  * 全局日志过滤器
  * <p>
@@ -43,16 +33,16 @@ public class GlobalLogFilter implements GlobalFilter, Ordered {
 
     @Override
     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
-        ServerHttpRequest request = exchange.getRequest();
-        String path = getOriginalRequestUrl(exchange);
-        String url = request.getMethod().name() + " " + path;
-
         if (!customGatewayProperties.getRequestLog()) {
             return chain.filter(exchange);
         }
+        ServerHttpRequest request = exchange.getRequest();
+        String path = WebFluxUtils.getOriginalRequestUrl(exchange);
+        String url = request.getMethod().name() + " " + path;
+
         // 打印请求参数
-        if (isJsonRequest(request)) {
-            String jsonParam = resolveBodyFromRequest(request);
+        if (WebFluxUtils.isJsonRequest(exchange)) {
+            String jsonParam = WebFluxUtils.resolveBodyFromCacheRequest(exchange);
             log.debug("[PLUS]开始请求 => URL[{}],参数类型[json],参数:[{}]", url, jsonParam);
         } else {
             MultiValueMap<String, String> parameterMap = request.getQueryParams();
@@ -79,38 +69,4 @@ public class GlobalLogFilter implements GlobalFilter, Ordered {
         return Ordered.LOWEST_PRECEDENCE;
     }
 
-    /**
-     * 判断本次请求的数据类型是否为json
-     *
-     * @param request request
-     * @return boolean
-     */
-    private boolean isJsonRequest(ServerHttpRequest request) {
-        MediaType contentType = request.getHeaders().getContentType();
-        if (contentType != null) {
-            return StringUtils.startsWithIgnoreCase(contentType.toString(), MediaType.APPLICATION_JSON_VALUE);
-        }
-        return false;
-    }
-
-    private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
-        //获取请求体
-        Flux<DataBuffer> body = serverHttpRequest.getBody();
-        StringBuilder sb = new StringBuilder();
-        body.subscribe(buffer -> {
-            byte[] bytes = new byte[buffer.readableByteCount()];
-            buffer.read(bytes);
-            String bodyString = new String(bytes, StandardCharsets.UTF_8);
-            sb.append(bodyString);
-        });
-        return sb.toString();
-    }
-
-    public static String getOriginalRequestUrl(ServerWebExchange exchange) {
-        ServerHttpRequest request = exchange.getRequest();
-        LinkedHashSet<URI> uris = exchange.getRequiredAttribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
-        URI requestUri = uris.stream().findFirst().orElse(request.getURI());
-        return UriComponentsBuilder.fromPath(requestUri.getRawPath()).build().toUriString();
-    }
-
 }

+ 1 - 19
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java

@@ -9,15 +9,8 @@ import com.ruoyi.gateway.utils.WebFluxUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cloud.gateway.filter.GatewayFilter;
 import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
-import org.springframework.core.io.buffer.DataBuffer;
-import org.springframework.core.io.buffer.DataBufferUtils;
 import org.springframework.http.server.reactive.ServerHttpRequest;
 import org.springframework.stereotype.Component;
-import reactor.core.publisher.Flux;
-
-import java.nio.CharBuffer;
-import java.nio.charset.StandardCharsets;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * 验证码过滤器
@@ -49,7 +42,7 @@ public class ValidateCodeFilter extends AbstractGatewayFilterFactory<Object> {
             }
 
             try {
-                String rspStr = resolveBodyFromRequest(request);
+                String rspStr = WebFluxUtils.resolveBodyFromCacheRequest(exchange);
                 Dict obj = JsonUtils.parseMap(rspStr);
                 validateCodeService.checkCaptcha(obj.getStr(CODE), obj.getStr(UUID));
             } catch (Exception e) {
@@ -59,15 +52,4 @@ public class ValidateCodeFilter extends AbstractGatewayFilterFactory<Object> {
         };
     }
 
-    private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
-        // 获取请求体
-        Flux<DataBuffer> body = serverHttpRequest.getBody();
-        AtomicReference<String> bodyRef = new AtomicReference<>();
-        body.subscribe(buffer -> {
-            CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
-            DataBufferUtils.release(buffer);
-            bodyRef.set(charBuffer.toString());
-        });
-        return bodyRef.get();
-    }
 }

+ 2 - 12
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/XssFilter.java

@@ -3,6 +3,7 @@ package com.ruoyi.gateway.filter;
 import cn.hutool.http.HtmlUtil;
 import com.ruoyi.common.core.utils.StringUtils;
 import com.ruoyi.gateway.config.properties.XssProperties;
+import com.ruoyi.gateway.utils.WebFluxUtils;
 import io.netty.buffer.ByteBufAllocator;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -12,7 +13,6 @@ import org.springframework.core.Ordered;
 import org.springframework.core.io.buffer.*;
 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.http.server.reactive.ServerHttpRequestDecorator;
 import org.springframework.stereotype.Component;
@@ -43,7 +43,7 @@ public class XssFilter implements GlobalFilter, Ordered {
             return chain.filter(exchange);
         }
         // 非json类型,不过滤
-        if (!isJsonRequest(exchange)) {
+        if (!WebFluxUtils.isJsonRequest(exchange)) {
             return chain.filter(exchange);
         }
         // excludeUrls 不过滤
@@ -93,16 +93,6 @@ public class XssFilter implements GlobalFilter, Ordered {
         return serverHttpRequestDecorator;
     }
 
-    /**
-     * 是否是Json请求
-     *
-     * @param exchange HTTP请求
-     */
-    public boolean isJsonRequest(ServerWebExchange exchange) {
-        String header = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
-        return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
-    }
-
     @Override
     public int getOrder() {
         return -100;

+ 68 - 0
ruoyi-gateway/src/main/java/com/ruoyi/gateway/utils/WebFluxUtils.java

@@ -2,13 +2,30 @@ package com.ruoyi.gateway.utils;
 
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.gateway.filter.GlobalCacheRequestFilter;
+import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
 import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferUtils;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpRequest;
 import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.util.UriComponentsBuilder;
+import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
+import java.net.URI;
+import java.nio.CharBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.LinkedHashSet;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
+
+import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR;
+
 /**
  * WebFlux 工具类
  *
@@ -16,6 +33,57 @@ import reactor.core.publisher.Mono;
  */
 public class WebFluxUtils {
 
+    /**
+     * 获取原请求路径
+     */
+    public static String getOriginalRequestUrl(ServerWebExchange exchange) {
+        ServerHttpRequest request = exchange.getRequest();
+        LinkedHashSet<URI> uris = exchange.getRequiredAttribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
+        URI requestUri = uris.stream().findFirst().orElse(request.getURI());
+        return UriComponentsBuilder.fromPath(requestUri.getRawPath()).build().toUriString();
+    }
+
+    /**
+     * 是否是Json请求
+     *
+     * @param exchange HTTP请求
+     */
+    public static boolean isJsonRequest(ServerWebExchange exchange) {
+        String header = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
+        return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
+    }
+
+    /**
+     * 读取request内的body
+     *
+     * 注意一个request只能读取一次 读取之后需要重新包装
+     */
+    public static String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
+        // 获取请求体
+        Flux<DataBuffer> body = serverHttpRequest.getBody();
+        AtomicReference<String> bodyRef = new AtomicReference<>();
+        body.subscribe(buffer -> {
+            CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
+            DataBufferUtils.release(buffer);
+            bodyRef.set(charBuffer.toString());
+        });
+        return bodyRef.get();
+    }
+
+    /**
+     * 从缓存中读取request内的body
+     *
+     * 注意要求经过 {@link ServerWebExchangeUtils#cacheRequestBody(ServerWebExchange, Function)} 此方法创建缓存
+     * 框架内已经使用 {@link GlobalCacheRequestFilter} 全局创建了body缓存
+     *
+     * @return body
+     */
+    public static String resolveBodyFromCacheRequest(ServerWebExchange exchange) {
+        DataBuffer buffer = (DataBuffer) exchange.getAttributes().get(ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR);
+        CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
+        return charBuffer.toString();
+    }
+
     /**
      * 设置webflux模型响应
      *