|
|
@@ -1,295 +1,294 @@
|
|
|
-package com.fdkankan.gateway.filter;
|
|
|
-
|
|
|
-import cn.hutool.core.exceptions.ExceptionUtil;
|
|
|
-import cn.hutool.core.net.URLDecoder;
|
|
|
-import cn.hutool.core.util.StrUtil;
|
|
|
-import com.alibaba.fastjson.JSON;
|
|
|
-import com.alibaba.fastjson.JSONObject;
|
|
|
-import com.fdkankan.common.constant.ServerCode;
|
|
|
-import com.fdkankan.gateway.log.GatewayLog;
|
|
|
-import com.fdkankan.gateway.response.ResultData;
|
|
|
-import com.fdkankan.gateway.util.WebUtil;
|
|
|
-import com.yomahub.tlog.context.TLogContext;
|
|
|
-import java.nio.charset.StandardCharsets;
|
|
|
-import java.util.Calendar;
|
|
|
-import java.util.Date;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.reactivestreams.Publisher;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-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.route.Route;
|
|
|
-import org.springframework.cloud.gateway.support.BodyInserterContext;
|
|
|
-import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
|
|
|
-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.HttpStatus;
|
|
|
-import org.springframework.http.MediaType;
|
|
|
-import org.springframework.http.codec.HttpMessageReader;
|
|
|
-import org.springframework.http.codec.ServerCodecConfigurer;
|
|
|
-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.util.MultiValueMap;
|
|
|
-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;
|
|
|
-
|
|
|
-/**
|
|
|
- * 请求、响应过滤器
|
|
|
- */
|
|
|
-@Slf4j
|
|
|
-@Component
|
|
|
-public class AccessLogFilter implements GlobalFilter, Ordered {
|
|
|
-
|
|
|
- private final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private ServerCodecConfigurer serverCodecConfigurer;
|
|
|
-
|
|
|
- @Override
|
|
|
- public int getOrder() {
|
|
|
- return -100;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
|
|
-
|
|
|
-// ServerRequest serverRequest = ServerRequest.create(exchange, serverCodecConfigurer.getReaders());
|
|
|
-
|
|
|
- ServerHttpRequest request = exchange.getRequest();
|
|
|
- // 请求路径
|
|
|
- String requestPath = request.getPath().pathWithinApplication().value();
|
|
|
-
|
|
|
- Route route = getGatewayRoute(exchange);
|
|
|
-
|
|
|
- String ipAddress = WebUtil.getIpAddress(request);
|
|
|
-
|
|
|
- GatewayLog gatewayLog = new GatewayLog();
|
|
|
- gatewayLog.setSchema(request.getURI().getScheme());
|
|
|
- gatewayLog.setRequestMethod(request.getMethodValue());
|
|
|
- gatewayLog.setRequestPath(requestPath);
|
|
|
- gatewayLog.setTargetServer(route.getId());
|
|
|
- gatewayLog.setRequestTime(new Date());
|
|
|
- gatewayLog.setIp(ipAddress);
|
|
|
- gatewayLog.setTraceId(TLogContext.getTraceId());
|
|
|
-
|
|
|
-
|
|
|
- MediaType mediaType = request.getHeaders().getContentType();
|
|
|
-
|
|
|
- if(MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(mediaType)
|
|
|
- || MediaType.APPLICATION_JSON.isCompatibleWith(mediaType)){
|
|
|
- return writeBodyLog(exchange, chain, gatewayLog);
|
|
|
- }
|
|
|
- else{
|
|
|
- return writeBasicLog(exchange, chain, gatewayLog);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- private Mono<Void> writeBasicLog(ServerWebExchange exchange, GatewayFilterChain chain, GatewayLog accessLog) {
|
|
|
- StringBuilder builder = new StringBuilder();
|
|
|
- MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
|
|
|
- for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
|
|
|
- builder.append(entry.getKey()).append("=").append(StrUtil.join(",", entry.getValue()));
|
|
|
- }
|
|
|
- accessLog.setRequestBody(builder.toString());
|
|
|
-
|
|
|
- //获取响应体
|
|
|
- ServerHttpResponseDecorator decoratedResponse = recordResponseLog(exchange, accessLog);
|
|
|
-
|
|
|
- return chain.filter(exchange.mutate().response(decoratedResponse).build())
|
|
|
- .doOnError(e->{
|
|
|
- // 打印日志
|
|
|
- writeBadAccessLog(accessLog, e);
|
|
|
- })
|
|
|
- .then(Mono.fromRunnable(() -> {
|
|
|
- // 打印日志
|
|
|
- writeAccessLog(accessLog);
|
|
|
- }));
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 参考: org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory
|
|
|
- * @param exchange
|
|
|
- * @param chain
|
|
|
- * @param gatewayLog
|
|
|
- * @return
|
|
|
- */
|
|
|
- @SuppressWarnings("unchecked")
|
|
|
- private Mono writeBodyLog(ServerWebExchange exchange, GatewayFilterChain chain, GatewayLog gatewayLog) {
|
|
|
- ServerRequest serverRequest = ServerRequest.create(exchange,serverCodecConfigurer.getReaders());
|
|
|
-
|
|
|
- Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
|
|
|
- .flatMap(body ->{
|
|
|
- gatewayLog.setRequestBody(URLDecoder.decode(body, StandardCharsets.UTF_8));
|
|
|
- return Mono.just(body);
|
|
|
- });
|
|
|
-
|
|
|
- // 通过 BodyInserter 插入 body(支持修改body), 避免 request body 只能获取一次
|
|
|
- BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
|
|
|
- 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);
|
|
|
-
|
|
|
- return bodyInserter.insert(outputMessage,new BodyInserterContext())
|
|
|
- .then(Mono.defer(() -> {
|
|
|
-
|
|
|
- // 重新封装请求
|
|
|
- ServerHttpRequest decoratedRequest = requestDecorate(exchange, headers, outputMessage);
|
|
|
-
|
|
|
- // 记录响应日志
|
|
|
- ServerHttpResponseDecorator decoratedResponse = recordResponseLog(exchange, gatewayLog);
|
|
|
-
|
|
|
- // 记录普通的
|
|
|
- return chain.filter(exchange.mutate().request(decoratedRequest).response(decoratedResponse).build())
|
|
|
- .doOnError(e->{
|
|
|
- // 打印日志
|
|
|
- writeBadAccessLog(gatewayLog, e);
|
|
|
- })
|
|
|
- .then(Mono.fromRunnable(() -> {
|
|
|
- // 打印日志
|
|
|
- writeAccessLog(gatewayLog);
|
|
|
- }));
|
|
|
- }));
|
|
|
- }
|
|
|
-
|
|
|
- private void writeBadAccessLog(GatewayLog gatewayLog, Throwable e){
|
|
|
- gatewayLog.setResponseTime(Calendar.getInstance().getTime());
|
|
|
- gatewayLog.setExecuteTime(gatewayLog.getResponseTime().getTime()-gatewayLog.getRequestTime().getTime());
|
|
|
- gatewayLog.setCode(ServerCode.SYSTEM_ERROR.code());
|
|
|
- gatewayLog.setMessage(ServerCode.SYSTEM_ERROR.message());
|
|
|
- gatewayLog.setResponseData(ExceptionUtil.stacktraceToString(e, 3000));
|
|
|
- this.writeAccessLog(gatewayLog);
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 打印日志
|
|
|
- * @param gatewayLog 网关日志
|
|
|
- */
|
|
|
- private void writeAccessLog(GatewayLog gatewayLog) {
|
|
|
- log.info(JSON.toJSONString(gatewayLog));
|
|
|
- //日志写入mongodb
|
|
|
-// mongoTemplate.insert(gatewayLog, "gatewayLog");
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- private Route getGatewayRoute(ServerWebExchange exchange) {
|
|
|
- return exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 请求装饰器,重新计算 headers
|
|
|
- * @param exchange
|
|
|
- * @param headers
|
|
|
- * @param outputMessage
|
|
|
- * @return
|
|
|
- */
|
|
|
- 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 {
|
|
|
- httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
|
|
|
- }
|
|
|
- return httpHeaders;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public Flux<DataBuffer> getBody() {
|
|
|
- return outputMessage.getBody();
|
|
|
- }
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 记录响应日志
|
|
|
- * 通过 DataBufferFactory 解决响应体分段传输问题。
|
|
|
- */
|
|
|
- private ServerHttpResponseDecorator recordResponseLog(ServerWebExchange exchange, GatewayLog gatewayLog) {
|
|
|
- ServerHttpResponse response = exchange.getResponse();
|
|
|
- DataBufferFactory bufferFactory = response.bufferFactory();
|
|
|
-
|
|
|
- return new ServerHttpResponseDecorator(response) {
|
|
|
-
|
|
|
- @Override
|
|
|
- public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
|
|
|
- if (body instanceof Flux) {
|
|
|
- Date responseTime = Calendar.getInstance().getTime();
|
|
|
- gatewayLog.setResponseTime(responseTime);
|
|
|
- // 计算执行时间
|
|
|
- long executeTime = (responseTime.getTime() - gatewayLog.getRequestTime().getTime());
|
|
|
-
|
|
|
- gatewayLog.setExecuteTime(executeTime);
|
|
|
-
|
|
|
- // 获取响应类型,如果是 json 就打印
|
|
|
- String originalResponseContentType = exchange.getAttribute(ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);
|
|
|
-
|
|
|
- if (this.getStatusCode().equals(HttpStatus.OK)
|
|
|
- && StrUtil.isNotBlank(originalResponseContentType)
|
|
|
-// && originalResponseContentType.contains("application/json")
|
|
|
- ) {
|
|
|
-
|
|
|
- Flux<? extends DataBuffer> fluxBody = Flux.from(body);
|
|
|
- return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
|
|
|
-
|
|
|
- // 合并多个流集合,解决返回体分段传输
|
|
|
- DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
|
|
|
- DataBuffer join = dataBufferFactory.join(dataBuffers);
|
|
|
- byte[] content = new byte[join.readableByteCount()];
|
|
|
- join.read(content);
|
|
|
-
|
|
|
- // 释放掉内存
|
|
|
- DataBufferUtils.release(join);
|
|
|
- String responseResult = new String(content, StandardCharsets.UTF_8);
|
|
|
-
|
|
|
- HttpHeaders headers = response.getHeaders();
|
|
|
- MediaType contentType = headers.getContentType();
|
|
|
- if(MediaType.APPLICATION_JSON.isCompatibleWith(contentType)){
|
|
|
- JSONObject result = JSON.parseObject(responseResult);
|
|
|
- String message = result.getString("message");
|
|
|
- if(StrUtil.isEmpty(message)){
|
|
|
- message = result.getString("msg");
|
|
|
- }
|
|
|
- gatewayLog.setCode(result.getInteger("code"));
|
|
|
- gatewayLog.setMessage(message);
|
|
|
- gatewayLog.setResponseData(JSON.toJSONString(result.get("data")));
|
|
|
- }
|
|
|
-
|
|
|
- return bufferFactory.wrap(content);
|
|
|
- }));
|
|
|
- }
|
|
|
- }
|
|
|
- // if body is not a flux. never got there.
|
|
|
- return super.writeWith(body);
|
|
|
- }
|
|
|
- };
|
|
|
- }
|
|
|
-}
|
|
|
+//package com.fdkankan.gateway.filter;
|
|
|
+//
|
|
|
+//import cn.hutool.core.exceptions.ExceptionUtil;
|
|
|
+//import cn.hutool.core.net.URLDecoder;
|
|
|
+//import cn.hutool.core.util.StrUtil;
|
|
|
+//import com.alibaba.fastjson.JSON;
|
|
|
+//import com.alibaba.fastjson.JSONObject;
|
|
|
+//import com.fdkankan.common.constant.ServerCode;
|
|
|
+//import com.fdkankan.gateway.response.ResultData;
|
|
|
+//import com.fdkankan.gateway.util.WebUtil;
|
|
|
+//import com.yomahub.tlog.context.TLogContext;
|
|
|
+//import java.nio.charset.StandardCharsets;
|
|
|
+//import java.util.Calendar;
|
|
|
+//import java.util.Date;
|
|
|
+//import java.util.List;
|
|
|
+//import java.util.Map;
|
|
|
+//import lombok.extern.slf4j.Slf4j;
|
|
|
+//import org.reactivestreams.Publisher;
|
|
|
+//import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+//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.route.Route;
|
|
|
+//import org.springframework.cloud.gateway.support.BodyInserterContext;
|
|
|
+//import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
|
|
|
+//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.HttpStatus;
|
|
|
+//import org.springframework.http.MediaType;
|
|
|
+//import org.springframework.http.codec.HttpMessageReader;
|
|
|
+//import org.springframework.http.codec.ServerCodecConfigurer;
|
|
|
+//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.util.MultiValueMap;
|
|
|
+//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;
|
|
|
+//
|
|
|
+///**
|
|
|
+// * 请求、响应过滤器
|
|
|
+// */
|
|
|
+//@Slf4j
|
|
|
+//@Component
|
|
|
+//public class AccessLogFilter implements GlobalFilter, Ordered {
|
|
|
+//
|
|
|
+// private final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();
|
|
|
+//
|
|
|
+// @Autowired
|
|
|
+// private ServerCodecConfigurer serverCodecConfigurer;
|
|
|
+//
|
|
|
+// @Override
|
|
|
+// public int getOrder() {
|
|
|
+// return -100;
|
|
|
+// }
|
|
|
+//
|
|
|
+// @Override
|
|
|
+// public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
|
|
+//
|
|
|
+//// ServerRequest serverRequest = ServerRequest.create(exchange, serverCodecConfigurer.getReaders());
|
|
|
+//
|
|
|
+// ServerHttpRequest request = exchange.getRequest();
|
|
|
+// // 请求路径
|
|
|
+// String requestPath = request.getPath().pathWithinApplication().value();
|
|
|
+//
|
|
|
+// Route route = getGatewayRoute(exchange);
|
|
|
+//
|
|
|
+// String ipAddress = WebUtil.getIpAddress(request);
|
|
|
+//
|
|
|
+// GatewayLog gatewayLog = new GatewayLog();
|
|
|
+// gatewayLog.setSchema(request.getURI().getScheme());
|
|
|
+// gatewayLog.setRequestMethod(request.getMethodValue());
|
|
|
+// gatewayLog.setRequestPath(requestPath);
|
|
|
+// gatewayLog.setTargetServer(route.getId());
|
|
|
+// gatewayLog.setRequestTime(new Date());
|
|
|
+// gatewayLog.setIp(ipAddress);
|
|
|
+// gatewayLog.setTraceId(TLogContext.getTraceId());
|
|
|
+//
|
|
|
+//
|
|
|
+// MediaType mediaType = request.getHeaders().getContentType();
|
|
|
+//
|
|
|
+// if(MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(mediaType)
|
|
|
+// || MediaType.APPLICATION_JSON.isCompatibleWith(mediaType)){
|
|
|
+// return writeBodyLog(exchange, chain, gatewayLog);
|
|
|
+// }
|
|
|
+// else{
|
|
|
+// return writeBasicLog(exchange, chain, gatewayLog);
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+// private Mono<Void> writeBasicLog(ServerWebExchange exchange, GatewayFilterChain chain, GatewayLog accessLog) {
|
|
|
+// StringBuilder builder = new StringBuilder();
|
|
|
+// MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
|
|
|
+// for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
|
|
|
+// builder.append(entry.getKey()).append("=").append(StrUtil.join(",", entry.getValue()));
|
|
|
+// }
|
|
|
+// accessLog.setRequestBody(builder.toString());
|
|
|
+//
|
|
|
+// //获取响应体
|
|
|
+// ServerHttpResponseDecorator decoratedResponse = recordResponseLog(exchange, accessLog);
|
|
|
+//
|
|
|
+// return chain.filter(exchange.mutate().response(decoratedResponse).build())
|
|
|
+// .doOnError(e->{
|
|
|
+// // 打印日志
|
|
|
+// writeBadAccessLog(accessLog, e);
|
|
|
+// })
|
|
|
+// .then(Mono.fromRunnable(() -> {
|
|
|
+// // 打印日志
|
|
|
+// writeAccessLog(accessLog);
|
|
|
+// }));
|
|
|
+// }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 参考: org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory
|
|
|
+// * @param exchange
|
|
|
+// * @param chain
|
|
|
+// * @param gatewayLog
|
|
|
+// * @return
|
|
|
+// */
|
|
|
+// @SuppressWarnings("unchecked")
|
|
|
+// private Mono writeBodyLog(ServerWebExchange exchange, GatewayFilterChain chain, GatewayLog gatewayLog) {
|
|
|
+// ServerRequest serverRequest = ServerRequest.create(exchange,serverCodecConfigurer.getReaders());
|
|
|
+//
|
|
|
+// Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
|
|
|
+// .flatMap(body ->{
|
|
|
+// gatewayLog.setRequestBody(URLDecoder.decode(body, StandardCharsets.UTF_8));
|
|
|
+// return Mono.just(body);
|
|
|
+// });
|
|
|
+//
|
|
|
+// // 通过 BodyInserter 插入 body(支持修改body), 避免 request body 只能获取一次
|
|
|
+// BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
|
|
|
+// 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);
|
|
|
+//
|
|
|
+// return bodyInserter.insert(outputMessage,new BodyInserterContext())
|
|
|
+// .then(Mono.defer(() -> {
|
|
|
+//
|
|
|
+// // 重新封装请求
|
|
|
+// ServerHttpRequest decoratedRequest = requestDecorate(exchange, headers, outputMessage);
|
|
|
+//
|
|
|
+// // 记录响应日志
|
|
|
+// ServerHttpResponseDecorator decoratedResponse = recordResponseLog(exchange, gatewayLog);
|
|
|
+//
|
|
|
+// // 记录普通的
|
|
|
+// return chain.filter(exchange.mutate().request(decoratedRequest).response(decoratedResponse).build())
|
|
|
+// .doOnError(e->{
|
|
|
+// // 打印日志
|
|
|
+// writeBadAccessLog(gatewayLog, e);
|
|
|
+// })
|
|
|
+// .then(Mono.fromRunnable(() -> {
|
|
|
+// // 打印日志
|
|
|
+// writeAccessLog(gatewayLog);
|
|
|
+// }));
|
|
|
+// }));
|
|
|
+// }
|
|
|
+//
|
|
|
+// private void writeBadAccessLog(GatewayLog gatewayLog, Throwable e){
|
|
|
+// gatewayLog.setResponseTime(Calendar.getInstance().getTime());
|
|
|
+// gatewayLog.setExecuteTime(gatewayLog.getResponseTime().getTime()-gatewayLog.getRequestTime().getTime());
|
|
|
+// gatewayLog.setCode(ServerCode.SYSTEM_ERROR.code());
|
|
|
+// gatewayLog.setMessage(ServerCode.SYSTEM_ERROR.message());
|
|
|
+// gatewayLog.setResponseData(ExceptionUtil.stacktraceToString(e, 3000));
|
|
|
+// this.writeAccessLog(gatewayLog);
|
|
|
+//
|
|
|
+// }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 打印日志
|
|
|
+// * @param gatewayLog 网关日志
|
|
|
+// */
|
|
|
+// private void writeAccessLog(GatewayLog gatewayLog) {
|
|
|
+// log.info(JSON.toJSONString(gatewayLog));
|
|
|
+// //日志写入mongodb
|
|
|
+//// mongoTemplate.insert(gatewayLog, "gatewayLog");
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+//
|
|
|
+// private Route getGatewayRoute(ServerWebExchange exchange) {
|
|
|
+// return exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 请求装饰器,重新计算 headers
|
|
|
+// * @param exchange
|
|
|
+// * @param headers
|
|
|
+// * @param outputMessage
|
|
|
+// * @return
|
|
|
+// */
|
|
|
+// 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 {
|
|
|
+// httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
|
|
|
+// }
|
|
|
+// return httpHeaders;
|
|
|
+// }
|
|
|
+//
|
|
|
+// @Override
|
|
|
+// public Flux<DataBuffer> getBody() {
|
|
|
+// return outputMessage.getBody();
|
|
|
+// }
|
|
|
+// };
|
|
|
+// }
|
|
|
+//
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 记录响应日志
|
|
|
+// * 通过 DataBufferFactory 解决响应体分段传输问题。
|
|
|
+// */
|
|
|
+// private ServerHttpResponseDecorator recordResponseLog(ServerWebExchange exchange, GatewayLog gatewayLog) {
|
|
|
+// ServerHttpResponse response = exchange.getResponse();
|
|
|
+// DataBufferFactory bufferFactory = response.bufferFactory();
|
|
|
+//
|
|
|
+// return new ServerHttpResponseDecorator(response) {
|
|
|
+//
|
|
|
+// @Override
|
|
|
+// public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
|
|
|
+// if (body instanceof Flux) {
|
|
|
+// Date responseTime = Calendar.getInstance().getTime();
|
|
|
+// gatewayLog.setResponseTime(responseTime);
|
|
|
+// // 计算执行时间
|
|
|
+// long executeTime = (responseTime.getTime() - gatewayLog.getRequestTime().getTime());
|
|
|
+//
|
|
|
+// gatewayLog.setExecuteTime(executeTime);
|
|
|
+//
|
|
|
+// // 获取响应类型,如果是 json 就打印
|
|
|
+// String originalResponseContentType = exchange.getAttribute(ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);
|
|
|
+//
|
|
|
+// if (this.getStatusCode().equals(HttpStatus.OK)
|
|
|
+// && StrUtil.isNotBlank(originalResponseContentType)
|
|
|
+//// && originalResponseContentType.contains("application/json")
|
|
|
+// ) {
|
|
|
+//
|
|
|
+// Flux<? extends DataBuffer> fluxBody = Flux.from(body);
|
|
|
+// return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
|
|
|
+//
|
|
|
+// // 合并多个流集合,解决返回体分段传输
|
|
|
+// DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
|
|
|
+// DataBuffer join = dataBufferFactory.join(dataBuffers);
|
|
|
+// byte[] content = new byte[join.readableByteCount()];
|
|
|
+// join.read(content);
|
|
|
+//
|
|
|
+// // 释放掉内存
|
|
|
+// DataBufferUtils.release(join);
|
|
|
+// String responseResult = new String(content, StandardCharsets.UTF_8);
|
|
|
+//
|
|
|
+// HttpHeaders headers = response.getHeaders();
|
|
|
+// MediaType contentType = headers.getContentType();
|
|
|
+// if(MediaType.APPLICATION_JSON.isCompatibleWith(contentType)){
|
|
|
+// JSONObject result = JSON.parseObject(responseResult);
|
|
|
+// String message = result.getString("message");
|
|
|
+// if(StrUtil.isEmpty(message)){
|
|
|
+// message = result.getString("msg");
|
|
|
+// }
|
|
|
+// gatewayLog.setCode(result.getInteger("code"));
|
|
|
+// gatewayLog.setMessage(message);
|
|
|
+// gatewayLog.setResponseData(JSON.toJSONString(result.get("data")));
|
|
|
+// }
|
|
|
+//
|
|
|
+// return bufferFactory.wrap(content);
|
|
|
+// }));
|
|
|
+// }
|
|
|
+// }
|
|
|
+// // if body is not a flux. never got there.
|
|
|
+// return super.writeWith(body);
|
|
|
+// }
|
|
|
+// };
|
|
|
+// }
|
|
|
+//}
|