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

gateway AccessLogFilter 中添加获取 request body 的 getRequestBody 方法

reghao 8 месяцев назад
Родитель
Сommit
94cdafca83
1 измененных файлов с 74 добавлено и 1 удалено
  1. 74 1
      gateway/src/main/java/cn/reghao/tnb/gateway/log/AccessLogFilter.java

+ 74 - 1
gateway/src/main/java/cn/reghao/tnb/gateway/log/AccessLogFilter.java

@@ -4,15 +4,23 @@ 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;
@@ -56,11 +64,76 @@ public class AccessLogFilter implements GlobalFilter, Ordered {
             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);
+    }
+
+    /**
+     * 获取 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);
+                });
+
+        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);
+
+        // 通过 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();
+            }
+        };
     }
 
     /**