我需要更改 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;
}
}
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 添加适用于所有路由的过滤器。
这是我更新的工作代码
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 {}
}