摘要:一開始搜索讀取參數的文章,方法大多是從里讀一次,轉成字符串,然后再把字符串轉成重新放到里,如上面的方法我試過可以,但是是的時候會報錯不知道是不是我姿勢不對。
(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 Monofilter(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 extends DataBuffer> body) { if (body instanceof Flux) { Flux extends DataBuffer> fluxBody = (Flux extends DataBuffer>) 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
摘要:歡迎訪問我的歡迎訪問我的內容所有原創文章分類匯總及配套源碼,涉及等本篇概覽本篇概覽作為實戰系列的第九篇,咱們聊聊如何用修改原始請求和響應內容,以及修改過程中遇到的問題首先是修改請求,如下圖,瀏覽器是請求發起方,真實參數只有,經過網關時被塞歡迎訪問我的GitHubhttps://github.com/zq2599/blog_demos內容:所有原創文章分類匯總及配套源碼,涉及Java、Dock...
摘要:公司要做自己的網關,于是先把的過了一遍,然后把源碼在看了一遍,這樣公司的需求就搞定了。包括動態路由,多緯度限流,記錄請求參數及返回參數也可修改。至此,流程就走完了。 公司要做自己的網關,于是先把github的issue過了一遍,然后把gateway源碼在看了一遍,這樣公司的需求就搞定了。包括動態路由,多緯度限流,記錄請求參數及返回參數(也可修改)。先從請求進入網關說起吧: 請求先進...
摘要:將請求封裝成將請求封裝成的接口定義是但是最外層傳進來的參數是和,需要將他們封裝成,這個工作就是在中做的。其實主要任務就是將各種參數封裝成除了和本次請求相關的和,還有會話管理器,編碼解碼器配置,國際化配置還有用于擴展。本系列代碼地址:https://github.com/JoJoTec/spring-cloud-parent接下來,將進入我們升級之路的又一大模塊,即網關模塊。網關模塊我們廢棄了...
摘要:歡迎訪問我的歡迎訪問我的內容所有原創文章分類匯總及配套源碼,涉及等本篇概覽本篇概覽作為實戰系列的第五篇,是時候了解過濾器的作用了,本篇咱們一起來了解內置好的過濾器,真是種類繁多功能強大過濾器顧名思義,就是在請求頭部添加指定的內容帶有的完整配歡迎訪問我的GitHubhttps://github.com/zq2599/blog_demos內容:所有原創文章分類匯總及配套源碼,涉及Java、Doc...
閱讀 555·2021-11-25 09:44
閱讀 2645·2021-11-24 09:39
閱讀 2315·2021-11-22 15:29
閱讀 3529·2021-11-15 11:37
閱讀 3395·2021-09-24 10:36
閱讀 2523·2021-09-04 16:41
閱讀 1005·2021-09-03 10:28
閱讀 1860·2019-08-30 15:55