美文网首页
spring cloud gateway acquire res

spring cloud gateway acquire res

作者: 毛里求疵 | 来源:发表于2019-12-11 16:20 被阅读0次
    import io.netty.buffer.ByteBufAllocator;
    import lombok.extern.slf4j.Slf4j;
    import org.reactivestreams.Publisher;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.core.Ordered;
    import org.springframework.core.io.buffer.DataBuffer;
    import org.springframework.core.io.buffer.DataBufferUtils;
    import org.springframework.core.io.buffer.NettyDataBufferFactory;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.http.server.reactive.ServerHttpResponse;
    import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
    import org.springframework.stereotype.Component;
    import org.springframework.util.CollectionUtils;
    import org.springframework.util.MultiValueMap;
    import org.springframework.web.server.ServerWebExchange;
    import org.springframework.web.server.WebFilter;
    import org.springframework.web.server.WebFilterChain;
    import reactor.core.publisher.Flux;
    import reactor.core.publisher.Mono;
    
    import javax.annotation.PostConstruct;
    import java.nio.charset.StandardCharsets;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    @Component
    @Slf4j
    public class LogFilter implements WebFilter, Ordered {
        private NettyDataBufferFactory bufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
            final ServerHttpRequest request = exchange.getRequest();
            final String sid = SessionHolder.generateSessionId();
            final String url = WebHelper.getReqeustUri(request);
            final String method = request.getMethodValue();
            final String remoteAddr = WebHelper.getIpAddr(request);
    
            final Map<String, Object> headers = new HashMap<>();
            final long reqTime = System.currentTimeMillis();
         
            // At 2019-11-28,fix the following issue{@code doOnError}
            // use sid for trace exception.asynchronous call will cause some trace issue.consider it.
            // SessionHolder.useSessionId(new ServerLogger.LogBase(remoteAddr, method, url, sid).toString());
    
            // dump req
            dump(remoteAddr, method, url, sid, headers.toString(), exchange);
    
            // normal response
            ServerHttpResponse originalResponse = exchange.getResponse();
            ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
                @Override
                public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                    if (body instanceof Flux) {
                        Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
                        return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
                            // dump resp
                            String responseData = dumpBody(dataBuffers);
                            byte[] uppedContent = new String(responseData.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8).getBytes();
                            long costTime = System.currentTimeMillis() - reqTime;
                            HttpStatus httpStatus = getStatusCode();
                            Integer respCode = httpStatus == null ? -1 : httpStatus.value();
                            ServerLogger.logHttpResp(new ServerLogger.LogHttpResp(remoteAddr, method, url, sid, costTime, respCode, responseData == null ? "" : responseData, false));
                            return bufferFactory.wrap(uppedContent);
                        }));
                    }
                    return super.writeWith(body);
                }
            };
            return chain.filter(exchange.mutate().request(request).response(decoratedResponse).build()).doOnError(
                    // dump error
                    error -> {
                        if (logWrite.pringLog(url, null))
                            ServerLogger.logHttpErr(new ServerLogger.LogHttpErr(remoteAddr, method, url, sid, error.getMessage()));
                    });
        }
    
        @Override
        public int getOrder() {
            return LOWEST_PRECEDENCE;
        }
    
        private String dumpParam(final ServerHttpRequest request) {
            String reqParam = null;
            MultiValueMap<String, String> multiValueMap = request.getQueryParams();
            Map<String, String> paramsMap = multiValueMap.toSingleValueMap();
            if (!CollectionUtils.isEmpty(paramsMap)) {
                StringBuilder sb = new StringBuilder();
                for (String key : paramsMap.keySet()) {
                    sb.append(key);
                    sb.append("=");
                    sb.append(paramsMap.get(key));
                    sb.append("&");
                }
                reqParam = sb.toString();
                if (reqParam != null && reqParam.endsWith("&"))
                    reqParam = reqParam.substring(0, reqParam.lastIndexOf('&') - 1);
            }
            return reqParam;
        }
    
    
        private String dumpBody(List<? extends DataBuffer> dataBuffers) {
            DataBuffer join = bufferFactory.join(dataBuffers);
            byte[] content = new byte[join.readableByteCount()];
            join.read(content);
            DataBufferUtils.release(join);
            return new String(content, StandardCharsets.UTF_8);
            /*
            // Tip : the way cause messy code
            List<String> list = Lists.newArrayList();
            dataBuffers.forEach(dataBuffer -> {
                byte[] content = new byte[dataBuffer.readableByteCount()];
                dataBuffer.read(content);
                DataBufferUtils.release(dataBuffer);
                list.add(new String(content, StandardCharsets.UTF_8));
            });
            return joiner.join(list);
             */
        }
    
        private void dump(String remoteAddr, String method, String url, String sid, String headers, ServerWebExchange exchange) {
            // dump param
            final ServerLogger.LogHttpReq logHttpReq = new ServerLogger.LogHttpReq(remoteAddr, method, url, sid, headers);
            ServerHttpRequest request = exchange.getRequest();
            String reqParam = dumpParam(request);
            logHttpReq.setReqParam(reqParam == null ? "" : reqParam);
    
            switch (request.getMethod()) {
                case GET:
                    ServerLogger.logHttpReq(logHttpReq);
                    break;
                default:
                    // dump body
                    /**{@link CacheReqBodyFilter#filter(ServerWebExchange, WebFilterChain)}*/
                    Object cachedBody = exchange.getAttribute(SystemConstants.CACHED_REQ_BODY);
                    logHttpReq.setReqBody(cachedBody == null ? "" : cachedBody.toString());
                    ServerLogger.logHttpReq(logHttpReq);
                    // remove buf
                    exchange.getAttributes().remove(SystemConstants.CACHED_REQ_BODY);
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:spring cloud gateway acquire res

          本文链接:https://www.haomeiwen.com/subject/sktagctx.html