Pārlūkot izejas kodu

修改 gateway 中对新构造 ServerHttpRequest 的处理

reghao 1 nedēļu atpakaļ
vecāks
revīzija
3928887e8e

+ 12 - 79
gateway/src/main/java/cn/reghao/tnb/gateway/log/AccessLogFilter.java

@@ -4,30 +4,21 @@ import lombok.extern.slf4j.Slf4j;
 import org.reactivestreams.Publisher;
 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
 import org.springframework.cloud.gateway.filter.GlobalFilter;
-import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage;
-import org.springframework.cloud.gateway.support.BodyInserterContext;
 import org.springframework.core.Ordered;
 import org.springframework.core.io.buffer.DataBuffer;
 import org.springframework.core.io.buffer.DataBufferFactory;
 import org.springframework.core.io.buffer.DataBufferUtils;
 import org.springframework.core.io.buffer.DefaultDataBufferFactory;
-import org.springframework.http.HttpHeaders;
 import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
 import org.springframework.http.server.reactive.ServerHttpResponse;
 import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
 import org.springframework.stereotype.Component;
-import org.springframework.web.reactive.function.BodyInserter;
-import org.springframework.web.reactive.function.BodyInserters;
-import org.springframework.web.reactive.function.server.HandlerStrategies;
-import org.springframework.web.reactive.function.server.ServerRequest;
 import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
 import java.nio.charset.StandardCharsets;
 import java.util.*;
-import java.util.function.Consumer;
 
 /**
  * HTTP 请求响应日志过滤器
@@ -60,80 +51,22 @@ public class AccessLogFilter implements GlobalFilter, Ordered {
     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
         String requestId = UUID.randomUUID().toString().replace("-", "");
         long requestTime = System.currentTimeMillis();
-        Consumer<HttpHeaders> headers = header -> {
-            header.set("x-request-id", requestId);
-            header.set("x-request-time", ""+requestTime);
-        };
-        exchange.getRequest().mutate().headers(headers).build();
 
-        // 获取响应体
-        ServerHttpResponseDecorator decoratedResponse = recordResponseLog(exchange);
-        return chain.filter(exchange.mutate().response(decoratedResponse).build());
-        //return getRequestBody(exchange, chain);
-    }
+        // 1. 构建包含新 Header 的请求
+        ServerHttpRequest newRequest = exchange.getRequest().mutate()
+                .header("x-request-id", requestId)
+                .header("x-request-time", String.valueOf(requestTime))
+                .build();
 
-    /**
-     * 获取 request body
-     *
-     * @param
-     * @return
-     * @date 2025-07-18 14:44:53
-     */
-    private Mono<Void> getRequestBody(ServerWebExchange exchange, GatewayFilterChain chain) {
-        ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
-        Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
-                .flatMap(body ->{
-                    //gatewayLog.setRequestBody(body);
-                    return Mono.just(body);
-                });
+        // 2. 先生成包含新请求的 Exchange
+        ServerWebExchange newExchange = exchange.mutate()
+                .request(newRequest)
+                .build();
 
-        HttpHeaders headers = new HttpHeaders();
-        headers.putAll(exchange.getRequest().getHeaders());
-        // the new content type will be computed by bodyInserter
-        // and then set in the request decorator
-        headers.remove(HttpHeaders.CONTENT_LENGTH);
-        CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
+        // 3. 将 newExchange 传给装饰器(关键:传入的是带 Header 的对象)
+        ServerHttpResponseDecorator decoratedResponse = recordResponseLog(newExchange);
 
-        // 通过 BodyInserter 插入 body(支持修改body), 避免 request body 只能获取一次
-        BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
-        return bodyInserter.insert(outputMessage,new BodyInserterContext())
-                .then(Mono.defer(() -> {
-                    // 重新封装请求
-                    ServerHttpRequest decoratedRequest = requestDecorate(exchange, headers, outputMessage);
-
-                    // 记录响应日志
-                    ServerHttpResponseDecorator decoratedResponse = recordResponseLog(exchange);
-                    return chain.filter(exchange.mutate().request(decoratedRequest).response(decoratedResponse).build())
-                            .then(Mono.fromRunnable(() -> {
-                                // 打印日志
-                                //writeAccessLog(gatewayLog);
-                            }));
-                }));
-    }
-
-    private ServerHttpRequestDecorator requestDecorate(ServerWebExchange exchange, HttpHeaders headers,
-                                                       CachedBodyOutputMessage outputMessage) {
-        return new ServerHttpRequestDecorator(exchange.getRequest()) {
-            @Override
-            public HttpHeaders getHeaders() {
-                long contentLength = headers.getContentLength();
-                HttpHeaders httpHeaders = new HttpHeaders();
-                httpHeaders.putAll(super.getHeaders());
-                if (contentLength > 0) {
-                    httpHeaders.setContentLength(contentLength);
-                } else {
-                    // TODO: this causes a 'HTTP/1.1 411 Length Required' // on
-                    // httpbin.org
-                    httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
-                }
-                return httpHeaders;
-            }
-
-            @Override
-            public Flux<DataBuffer> getBody() {
-                return outputMessage.getBody();
-            }
-        };
+        return chain.filter(newExchange.mutate().response(decoratedResponse).build());
     }
 
     /**

+ 11 - 9
gateway/src/main/java/cn/reghao/tnb/gateway/token/GlobalTokenFilter.java

@@ -16,7 +16,6 @@ import org.springframework.core.io.buffer.DataBuffer;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.data.redis.core.ValueOperations;
 import org.springframework.http.HttpCookie;
-import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.server.reactive.ServerHttpRequest;
@@ -30,7 +29,6 @@ import reactor.core.publisher.Mono;
 import java.nio.charset.StandardCharsets;
 import java.security.interfaces.RSAPublicKey;
 import java.util.*;
-import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
 /**
@@ -102,13 +100,17 @@ public class GlobalTokenFilter implements GlobalFilter, Ordered {
         }
 
         final UserLogin userLogin1 = userLogin;
-        Consumer<HttpHeaders> headers = header -> {
-            header.set("x-user-id", ""+userLogin1.getUserId());
-            header.set("x-login-id", userLogin1.getLoginId());
-            header.set("x-user-roles", userLogin1.getRoles());
-        };
-        exchange.getRequest().mutate().headers(headers).build();
-        return chain.filter(exchange);
+        // 1. 构建包含新 Header 的请求
+        ServerHttpRequest newRequest = exchange.getRequest().mutate()
+                .header("x-user-id", ""+userLogin1.getUserId())
+                .header("x-login-id", userLogin1.getLoginId())
+                .header("x-user-roles", userLogin1.getRoles())
+                .build();
+        // 2. 先生成包含新请求的 Exchange
+        ServerWebExchange newExchange = exchange.mutate()
+                .request(newRequest)
+                .build();
+        return chain.filter(newExchange);
     }
 
     private UserData getUserData(ServerHttpRequest request) {