簡體   English   中英

Spring 雲網關 - 如何修改后過濾器中的響應正文

[英]Spring Cloud Gateway - How To Modify Response Body In Post Filter

到目前為止,我還沒有看到任何對我有用的解決方案。 我試過這個這個

這是我的自定義過濾器:

@Component
public class TestFilter implements GlobalFilter, Ordered {

    @Autowired
    private ModifyResponseBodyGatewayFilterFactory modifyFilter;
    
    @Autowired
    private rewriteBody bodyRewrite;
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        return chain.filter(exchange).map(ex -> {
            GatewayFilter delegate = modifyFilter.apply(new ModifyResponseBodyGatewayFilterFactory.Config()
                    .setRewriteFunction(byte[].class, byte[].class, bodyRewrite));
            delegate.filter(exchange, chain);

            return ex;
        });
    }

    @Override
    public int getOrder() {
        return -1;
    }
    
    @Component
    public class rewriteBody implements RewriteFunction<byte[], byte[]> {
        
        @Override
        public Publisher<byte[]> apply(ServerWebExchange exchange, byte[] body) {
            byte[] newBody = "New response".getBytes();
            
            return Mono.just(newBody);
        }
    }
}

如果我在前置過濾器中實現ModifyResponseBodyGatewayFilterFactory ,它可以工作,但是如何在后置過濾器中修改它。

回答關於修改后過濾器響應的問題。 首先需要了解Spring雲網關中開發的前置過濾器和后置過濾器。

Spring 雲網關中的前置過濾器和后置過濾器沒有通過任何接口或任何其他組件進行特定分離。 它只是“如何為同一個過濾器編寫邏輯”。

如果在運行另一個“鏈中過濾器”或“調用目標服務端點”之前執行了在chain.filter(exchange)方法調用之前編寫的任何邏輯。 因為,在調用另一個過濾器或目標端點之前運行的邏輯/代碼,它被稱為預過濾器並用於預處理,如添加額外的標頭、安全斷言、速率限制等。

如果在chain.filter(exchange)方法中處理完成后執行chain.filter(exchange) chain.filter(exchange)方法調用之后編寫的任何邏輯,則意味着“目標服務端點”已經完成,然后在chain.filter(exchange)正在執行。 因此,它被稱為后過濾器。

因為,這只是一種編寫方式,代碼的位置決定了它是用於前置/后置,兩者都可以在單個過濾器中編寫。

            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                return Mono.just(exchange)
                        .map(it -> {
                            it.getRequest().getHeaders().add("x-pre-header", "value");
                            return it;
                        })
                        .doOnNext(it -> {
                            logger.debug("Pre-Processing/PreFilter");
                        })
                        .map(it -> chain.filter(it))
                        .then()
                        .map(it -> {
                            exchange.getResponse().getHeaders().add("x-post-header", "value");
                            return it;
                        })
                        .doOnNext(it -> {
                            logger.debug("Post-Processing/PostFilter");
                        });
            }

此外,過濾器的執行順序由過濾器的排序控制。

現在,當出現修改響應正文的問題時,很明顯,只有在調用需要chain.filter(exchange)的“目標服務端點”時才會提供響應。

這里有一個轉折,稱為“響應提交”。 當響應已經提交時,響應主體不能更改,並且一旦chain.filter(exchange) ,將需要微/毫秒來將響應寫入客戶端並提交響應。 意味着,如果在then()方法之后編寫的任何代碼對響應主體進行更改,它將拋出異常“響應已提交”。

為避免這種情況,在進行chain.filter(exchange)調用時,響應主體總是被修改。 例如,考慮用ModifyResponseBodyGatewayFilterFactory的方法filter(...)編寫的代碼為:

        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            return chain.filter(exchange.mutate()
                    .response(new ModifiedServerHttpResponse(exchange, config)).build());
        }

在這里,exchange 發生了變化,並且同時設置了響應體。 它將修改響應並調用鏈中的其他過濾器,如果鏈中沒有任何剩余的過濾器,則它將響應提供給客戶端。

因此,從概念上講,響應主體修改作為后期活動發生,只有過濾器在鏈中稍后出現。 響應體修改后不應執行其他過濾器的需求/響應體修改后需要執行某些特定過濾器需要由過濾器的排序管理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM