国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

spring cloud gateway 源碼解析(3)記錄請求參數及返回的json

MangoGoing / 3386人閱讀

摘要:一開始搜索讀取參數的文章,方法大多是從里讀一次,轉成字符串,然后再把字符串轉成重新放到里,如上面的方法我試過可以,但是是的時候會報錯不知道是不是我姿勢不對。

(1)一開始搜索讀取參數的文章,方法大多是從body里讀一次DataBuffer,轉成字符串,然后再把字符串轉成DataBuffer重新放到body里,如:
http://www.cnblogs.com/cafeba...

(2)

上面的方法我試過可以,但是Content-Type是multipart/form-data的時候會報錯
java.lang.IllegalStateException: Only one connection receive subscriber allowed.
不知道是不是我姿勢不對。
而且如果我們在代理到第三方服務的時候才讀取body,這樣效率應該會高一些
看NettyRoutingFilter類里的filter方法
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ·······

        Mono responseMono = this.httpClient.request(method, url, req -> {
            final HttpClientRequest proxyRequest = req.options(NettyPipeline.SendOptions::flushOnEach)
                    .headers(httpHeaders)
                    .chunkedTransfer(chunkedTransfer)
                    .failOnServerError(false)
                    .failOnClientError(false);

            if (preserveHost) {
                String host = request.getHeaders().getFirst(HttpHeaders.HOST);
                proxyRequest.header(HttpHeaders.HOST, host);
            }

            if (properties.getResponseTimeout() != null) {
                proxyRequest.context(ctx -> ctx.addHandlerFirst(
                        new ReadTimeoutHandler(properties.getResponseTimeout().toMillis(), TimeUnit.MILLISECONDS)));
            }

            return proxyRequest.sendHeaders() 
                    //這里的是ReactorServerHttpRequest調用了getBody()方法,
                    //所以我們只要重寫ReactorServerHttpRequest的getbody方法,加上我們讀取的邏輯就行了,
                    //gateway給我們提供了裝飾類ServerHttpRequestDecorator,我們只需把過濾器的優先級設置高于NettyRoutingFilter(實際他已經是倒數第二的優先級了),且把ReactorServerHttpRequest替換成ServerHttpRequestDecorator就行了
                    .send(request.getBody().map(dataBuffer ->
                            ((NettyDataBuffer) dataBuffer).getNativeBuffer()));
        });
給個stackoverflow的偽代碼
ServerHttpRequestDecorator decoratedRequest = new ServerHttpRequestDecorator(request) {
             @Override
            public Flux getBody() { 
                 StringBuilder sb=new StringBuilder();
                  return  super.getBody().map(dataBuffer -> {
                    // probably should reuse buffers 
                    byte[] content = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(content);
                    byte[] uppedContent = new String(content, Charset.forName("UTF-8")).toUpperCase().getBytes();
                    return bufferFactory.wrap(uppedContent);
                }) ; 
            }
};

            //再說說記錄返回的json,在NettyRoutingFilter類的154行,請求第三方服務反回后,
            // Defer committing the response until all route filters have run
            // Put client response as ServerWebExchange attribute and write response later NettyWriteResponseFilter
            //注釋說了把返回結果放進ServerWebExchange 的參數里了,并且在NettyWriteResponseFilter讀取
            exchange.getAttributes().put(CLIENT_RESPONSE_ATTR, res);


看NettyWriteResponseFilter的讀取代碼,
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
       return chain.filter(exchange).then(Mono.defer(() -> {
           //拿出NettyRoutingFilter放進去的Response 
            HttpClientResponse clientResponse = exchange.getAttribute(CLIENT_RESPONSE_ATTR);

            if (clientResponse == null) {//空的就不過直接到下一個過濾器
                return Mono.empty();
            }
            log.trace("NettyWriteResponseFilter start");
            ServerHttpResponse response = exchange.getResponse();

            NettyDataBufferFactory factory = (NettyDataBufferFactory) response.bufferFactory();
            //TODO: what if it"s not netty

            final Flux body = clientResponse.receive()
                    .retain() //TODO: needed?
                    .map(factory::wrap);

            MediaType contentType = null;
            try {
                contentType = response.getHeaders().getContentType();
            } catch (Exception e) {
                log.trace("invalid media type", e);
            }
            //判斷contentType是不是text/event-stream或者application/stream+json
            //反正上面兩種類型的結果我們肯定不用記錄,所以我們重寫response的writeWith方法就好,
            //跟上面一樣gateway也提供了個裝飾器類ServerHttpResponseDecorator
            return (isStreamingMediaType(contentType) ?
                    response.writeAndFlushWith(body.map(Flux::just)) : response.writeWith(body));
        }));
    }
上stackoverflow的偽代碼
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
      ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
        @Override
        public Mono writeWith(Publisher body) {
            if (body instanceof Flux) {
                Flux fluxBody = (Flux) body;
                return super.writeWith(fluxBody.map(dataBuffer -> {
                    // probably should reuse buffers 
                    byte[] content = new byte[dataBuffer.readableByteCount()];
                    dataBuffer.read(content);
                    byte[] uppedContent = new String(content, Charset.forName("UTF-8")).toUpperCase().getBytes();
                    return bufferFactory.wrap(uppedContent);
                }));
            }
            return super.writeWith(body); // if body is not a flux. never got there.
        }           
      }; 

參考:
https://stackoverflow.com/que...

該如果返回的數據長度很長的話,數據可能會讀不完全,如果出現讀取時截取了中文字符,導致長度變多1位,進而json的右括號消失,也可參考下面鏈接
參考解決方案:
https://stackoverflow.com/que...

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/77398.html

相關文章

  • Spring Cloud Gateway修改請求和響應body內容

    摘要:歡迎訪問我的歡迎訪問我的內容所有原創文章分類匯總及配套源碼,涉及等本篇概覽本篇概覽作為實戰系列的第九篇,咱們聊聊如何用修改原始請求和響應內容,以及修改過程中遇到的問題首先是修改請求,如下圖,瀏覽器是請求發起方,真實參數只有,經過網關時被塞歡迎訪問我的GitHubhttps://github.com/zq2599/blog_demos內容:所有原創文章分類匯總及配套源碼,涉及Java、Dock...

    ivyzhang 評論0 收藏0
  • spring cloud gateway 源碼解析(1)整體流程

    摘要:公司要做自己的網關,于是先把的過了一遍,然后把源碼在看了一遍,這樣公司的需求就搞定了。包括動態路由,多緯度限流,記錄請求參數及返回參數也可修改。至此,流程就走完了。 公司要做自己的網關,于是先把github的issue過了一遍,然后把gateway源碼在看了一遍,這樣公司的需求就搞定了。包括動態路由,多緯度限流,記錄請求參數及返回參數(也可修改)。先從請求進入網關說起吧: 請求先進...

    miqt 評論0 收藏0
  • SpringCloud升級之路2020.0.x版-41. SpringCloudGateway 基本

    摘要:將請求封裝成將請求封裝成的接口定義是但是最外層傳進來的參數是和,需要將他們封裝成,這個工作就是在中做的。其實主要任務就是將各種參數封裝成除了和本次請求相關的和,還有會話管理器,編碼解碼器配置,國際化配置還有用于擴展。本系列代碼地址:https://github.com/JoJoTec/spring-cloud-parent接下來,將進入我們升級之路的又一大模塊,即網關模塊。網關模塊我們廢棄了...

    不知名網友 評論0 收藏0
  • Spring Cloud Gateway實戰之五:內置filter

    摘要:歡迎訪問我的歡迎訪問我的內容所有原創文章分類匯總及配套源碼,涉及等本篇概覽本篇概覽作為實戰系列的第五篇,是時候了解過濾器的作用了,本篇咱們一起來了解內置好的過濾器,真是種類繁多功能強大過濾器顧名思義,就是在請求頭部添加指定的內容帶有的完整配歡迎訪問我的GitHubhttps://github.com/zq2599/blog_demos內容:所有原創文章分類匯總及配套源碼,涉及Java、Doc...

    reclay 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<