如何在gateway的过滤器中获取路由返回的页面内容?

发布于 2021-12-03 00:43:48 字数 6044 浏览 807 评论 4


package com.newland.bomc.micro.gateway.filter;

import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.UnpooledByteBufAllocator;
import org.apache.commons.io.IOUtils;
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.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.NettyDataBufferFactory;
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.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.ipc.netty.http.client.HttpClientResponse;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.StandardCharsets;


/**
 * Intercept the backend service html results, according to the page permissions configuration, hide the corresponding elements
 *
 * @author song
 * @date 2018/4/26
 * <p>
 */

@Component
public class HtmlContentVisibleFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return chain.filter(exchange).then(
                Mono.defer(() -> {
                    ServerHttpRequest request = exchange.getRequest();
                    ServerHttpResponse response = exchange.getResponse();
                    HttpClientResponse clientResponse = exchange.getAttribute(ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR);
                    if (clientResponse == null) {
                        return Mono.empty();
                    }
                    //FIXME I want to cache body and rewrite it
                    NettyDataBufferFactory factory = (NettyDataBufferFactory) response.bufferFactory();
                    Flux<DataBuffer> body = clientResponse.receive().retain().map(factory::wrap);
                    boolean isOkStatus = response.getStatusCode() == HttpStatus.OK;
                    boolean filterFlag = isOkStatus && clientResponse != null;
                    if (filterFlag) {
                        MediaType contentType = response.getHeaders().getContentType();
                        if (contentType != null && contentType.includes(MediaType.TEXT_HTML)) {
                            body.flatMap(dataBuffer -> rebuildFluxBody(exchange, dataBuffer));
                        }
                    }
//                    request = new ServerHttpRequestDecorator(request) {
//                        @Override
//                        public Flux<DataBuffer> getBody() {
//                            return Flux.just(stringBuffer(html));
//                        }
//                    };//封装我们的request
                    return chain.filter(exchange.mutate().request(request).build());
                })

        );

    }

    public Flux<DataBuffer> rebuildFluxBody(ServerWebExchange exchange, DataBuffer dataBuffer) {
        DataBuffer bodyDataBuffer = reBuildDataBuffer(dataBuffer);
        System.out.println("====>>>>>>>>>>>" + bodyDataBuffer);
        return Flux.just(bodyDataBuffer);
    }

    private DataBuffer reBuildDataBuffer(DataBuffer dataBuffer) {
        InputStream dataBufferStream = dataBuffer.asInputStream();
        ByteArrayOutputStream prepareBaos = cloneInputStream(dataBufferStream);
        DataBuffer bodyDataBuffer = null;
        InputStream insCopy = new ByteArrayInputStream(prepareBaos.toByteArray());
        try {
            byte[] bytes = IOUtils.toByteArray(insCopy);
            NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(new UnpooledByteBufAllocator(false));
            bodyDataBuffer = nettyDataBufferFactory.wrap(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bodyDataBuffer;
    }

    private ByteArrayOutputStream cloneInputStream(InputStream inputStream) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024 * 4];
        int n;
        try {
            while ((n = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, n);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out;
    }

    @Override
    public int getOrder() {
        //设置成在ForwardRoutingFilter前运行
        return 110023;
    }

    /**
     * ByteBuffer 转换 String
     */
    public static String getString(ByteBuffer buffer) {
        Charset charset = null;
        CharsetDecoder decoder = null;
        CharBuffer charBuffer = null;
        try {
            charset = Charset.forName("UTF-8");
            decoder = charset.newDecoder();
            // charBuffer = decoder.decode(buffer);//用这个的话,只能输出来一次结果,第二次显示为空
            charBuffer = decoder.decode(buffer.asReadOnlyBuffer());
            return charBuffer.toString();
        } catch (Exception ex) {
            ex.printStackTrace();
            return "";
        }
    }

    protected DataBuffer stringBuffer(String value) {
        byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
        NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
        DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
        buffer.write(bytes);
        return buffer;
    }
}

如代码中所示,目前无法或者服务返回的页面body,望大神不吝赐教!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

可是我不能没有你 2021-12-08 13:32:02

zuul无法返回html,只能转发rest接口

醉生梦死 2021-12-08 13:29:03

嗯 忘记了。你是页面。

能否归途做我良人 2021-12-08 02:44:25

回复
@石头捡到布 : 在zuul中可以获取html流的哈

浮生未歇 2021-12-05 23:36:55

换zuul吧。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文