Spring Gateway 在 isError 上改变响应主体

问题描述 投票:0回答:1

我需要更改 4xx 和 5xx 响应的响应正文。

传入的响应看起来像

{
  "reason": "sample reason"
}

我需要将其更改为

{
  "userMessage": "sample reason"
}

这是我的尝试

public class ErrorResponseFilter implements GlobalFilter, Ordered {
    private static final String REASON = "reason";
    private static final String USER_MESSAGE = "userMessage";
    private final ModifyResponseBodyGatewayFilterFactory modifyResponseBodyGatewayFilterFactory;

    public ErrorResponseFilter(ModifyResponseBodyGatewayFilterFactory modifyResponseBodyGatewayFilterFactory) {
        this.modifyResponseBodyGatewayFilterFactory = modifyResponseBodyGatewayFilterFactory;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return modifyResponseBodyGatewayFilterFactory
                .apply(c -> c.setInClass(JsonNode.class)
                        .setOutClass(JsonNode.class)
                        .setRewriteFunction((RewriteFunction<JsonNode, JsonNode>) (exchange1, body) -> {
                            if (null == body) return Mono.empty();

                            var originalResponse = exchange1.getResponse();
                            log.info("COOOODEDDDE: " + originalResponse.getStatusCode());
                            HttpStatusCode statusCode = originalResponse.getStatusCode();

                            if (statusCode != null && !statusCode.isError()) {
                                if (body.isObject()) {
                                    ObjectNode node = (ObjectNode) body;
                                    node.set(USER_MESSAGE, node.get(REASON));
                                    node.remove(REASON);
                                }
                            }
                            return Mono.just(body);
                        })
                )
                .filter(exchange, chain);
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

但是,这不起作用,HTTP 代码始终是
200 OK

更新1:

我曾尝试使用豆子

 @Bean
    public RouteLocator routes(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("rewrite_response_user_message", r -> r.alwaysTrue()
                        .filters(f -> f.modifyResponseBody(JsonNode.class, JsonNode.class, (exchange, u) -> {
                            var originalResponse = exchange.getResponse();
                            HttpStatusCode statusCode = originalResponse.getStatusCode();
                            log.info("HTTP CODE: " + originalResponse.getStatusCode());
                            if(u == null) return Mono.empty();
                            if (statusCode != null && statusCode.isError()) {
                                if (u.isObject()) {
                                    ObjectNode node = (ObjectNode) u;
                                    node.set("userMessage", node.get("response"));
                                    node.remove("response");
                                }
                            }
                            return Mono.just(u);
                        }))
                        .uri(uri))
                .build();
    }

如果没有 bean,路由会返回

204 NO CONTENT
,但是当启用 bean 时,会在上面的代码中打印相同的
404

更新2:

看起来,无法通过 Java DSL 添加适用于所有路由的过滤器。

java spring spring-cloud gateway spring-cloud-gateway
1个回答
0
投票

这是我更新的工作代码

public class ErrorReasonToUserMessageGatewayFilterFactory
        extends AbstractGatewayFilterFactory<ErrorReasonToUserMessageGatewayFilterFactory.Config> implements Ordered {
    private static final String REASON = "reason";
    private static final String USER_MESSAGE = "userMessage";
    private final ModifyResponseBodyGatewayFilterFactory modifyResponseBodyFilterFactory;

    public ErrorReasonToUserMessageGatewayFilterFactory(
            ModifyResponseBodyGatewayFilterFactory modifyResponseBodyFilterFactory) {
        super(Config.class);
        this.modifyResponseBodyFilterFactory = modifyResponseBodyFilterFactory;
    }

    @Override
    public GatewayFilter apply(Config config) {
        return modifyResponseBodyFilterFactory.apply(
                c -> c.setRewriteFunction(JsonNode.class, JsonNode.class, (swe, body) -> Optional.ofNullable(body)
                        .map(rewriteReasonToUserMessageFunction(swe, body))
                        .orElseGet(Mono::empty)));
    }

    private Function<JsonNode, Mono<JsonNode>> rewriteReasonToUserMessageFunction(
            ServerWebExchange swe, JsonNode body) {
        return s -> {
            HttpStatusCode statusCode = swe.getResponse().getStatusCode();
            if (statusCode != null && statusCode.isError() && body instanceof ObjectNode obj && body.has(REASON)) {
                obj.set(USER_MESSAGE, obj.get(REASON));
                obj.remove(REASON);
                return Mono.just(obj);
            }
            return Mono.just(body);
        };
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }

    public static class Config {}
}
© www.soinside.com 2019 - 2024. All rights reserved.