Spring cloud 仅对某些内容类型应用modifyResponseBody

Spring cloud 仅对某些内容类型应用modifyResponseBody,spring-cloud,spring-cloud-gateway,Spring Cloud,Spring Cloud Gateway,我正在使用GatewayFilterSpec.modifyResponseBody(标记为“BETA”功能)重写JSON有效负载。只要响应有效负载实际上是内容类型application/json,这就可以很好地工作。在我的例子中,不幸的是,这并不总是可以保证的,我希望它只应用modifyResponseBody,如果响应具有内容类型:application/json头,否则跳过过滤器。SpringCloudGateway是否可以实现这一点,以及如何做到这一点?多谢各位 现在我明白了: org.s

我正在使用
GatewayFilterSpec.modifyResponseBody
(标记为“BETA”功能)重写JSON有效负载。只要响应有效负载实际上是内容类型
application/json
,这就可以很好地工作。在我的例子中,不幸的是,这并不总是可以保证的,我希望它只应用
modifyResponseBody
,如果响应具有
内容类型:application/json
头,否则跳过过滤器。SpringCloudGateway是否可以实现这一点,以及如何做到这一点?多谢各位

现在我明白了:

org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'text/html' not supported
    at org.springframework.web.reactive.function.BodyInserters.lambda$null$11(BodyInserters.java:329)
    at java.util.Optional.orElseGet(Optional.java:267)
    at org.springframework.web.reactive.function.BodyInserters.lambda$bodyInserterFor$12(BodyInserters.java:325)
这里有一个“解决方案”,它有各种各样的问题:

package my_package;

import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import static org.springframework.http.MediaType.APPLICATION_JSON;

@Component
@Primary
public class JsonOnlyModifyResponseBodyGatewayFilterFactory extends ModifyResponseBodyGatewayFilterFactory {
    public JsonOnlyModifyResponseBodyGatewayFilterFactory(ServerCodecConfigurer codecConfigurer) {
        super(codecConfigurer);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return new MyModifyResponseGatewayFilter(config);
    }

    public class MyModifyResponseGatewayFilter extends ModifyResponseGatewayFilter {
        MyModifyResponseGatewayFilter(Config config) {
            super(config);
        }

        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            ServerHttpResponse serverHttpResponse = getServerHttpResponseFromSuper(exchange);
            ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) {
                @Override
                public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                    if (APPLICATION_JSON.isCompatibleWith(getDelegate().getHeaders().getContentType())) {
                        return serverHttpResponse.writeWith(body);
                    }
                    return super.writeWith(body);
                }
            };
            return chain.filter(exchange.mutate().response(responseDecorator).build());
        }

        private ServerHttpResponse getServerHttpResponseFromSuper(ServerWebExchange exchange) {
            ServerHttpResponse[] serverHttpResponse = new ServerHttpResponse[1];
            //noinspection UnassignedFluxMonoInstance
            super.filter(exchange, chain -> {
                serverHttpResponse[0] = chain.getResponse(); // capture the response when the super sets it
                return null;
            });
            return serverHttpResponse[0];
        }
    }
}
package my_package;
导入org.reactivestreams.Publisher;
导入org.springframework.cloud.gateway.filter.GatewayFilter;
导入org.springframework.cloud.gateway.filter.GatewayFilterChain;
导入org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory;
导入org.springframework.context.annotation.Primary;
导入org.springframework.core.io.buffer.DataBuffer;
导入org.springframework.http.codec.servercodeconfigurer;
导入org.springframework.http.server.reactive.ServerHttpResponse;
导入org.springframework.http.server.reactive.ServerHttpResponseDecorator;
导入org.springframework.stereotype.Component;
导入org.springframework.web.server.ServerWebExchange;
导入reactor.core.publisher.Mono;
导入静态org.springframework.http.MediaType.APPLICATION_JSON;
@组成部分
@初级的
公共类JSONONOnlyModifyResponseBodyGatewayFilterFactory扩展了ModifyResponseBodyGatewayFilterFactory{
公共JSONONOnlyModifyResponseBodyGatewayFilterFactory(ServerCodeConfigurer CodeConfigurer){
超级(编解码器配置器);
}
@凌驾
公共网关筛选器应用(配置){
返回新的MyModifyResponseGatewayFilter(配置);
}
公共类MyModifyResponseGatewayFilter扩展了ModifyResponseGatewayFilter{
MyModifyResponseGatewayFilter(配置){
超级(配置);
}
@凌驾
公共Mono筛选器(服务器WebExchange exchange、网关筛选器链){
ServerHttpResponse ServerHttpResponse=getServerHttpResponseFromSuper(exchange);
ServerHttpResponseDecorator responseDecorator=新的ServerHttpResponseDecorator(exchange.getResponse()){
@凌驾

公共单写(发布了一个检查内容类型标题的前置谓词?你的意思是像
predictspec.header
?这是对请求的检查,不是吗?我说的是
content-type
,响应是决定因素。我知道请求上可能有一个相应的
Accept
,但我不期望客户可以可靠地设置标题。(我可能被误导了,我相信你会告诉我…)啊,回复。目前不可能。谢谢,我很感谢您的回复。但是,您能告诉我实现所需结果的其他方法吗,即使这意味着不使用
网关过滤器spec.modifyResponseBody