Merge branch '4.2.x'

This commit is contained in:
Ryan Baxter
2025-05-13 09:56:25 -04:00
2 changed files with 53 additions and 27 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013-2020 the original author or authors.
* Copyright 2013-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,6 @@ import java.util.List;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import reactor.core.publisher.Mono;
@@ -34,6 +33,7 @@ import org.springframework.http.MediaType;
/**
* @author Marta Medio
* @author raccoonback
*/
public class RemoveJsonAttributesResponseBodyGatewayFilterFactory extends
AbstractGatewayFilterFactory<RemoveJsonAttributesResponseBodyGatewayFilterFactory.FieldListConfiguration> {
@@ -72,14 +72,14 @@ public class RemoveJsonAttributesResponseBodyGatewayFilterFactory extends
RewriteFunction<String, String> rewriteFunction = (exchange, body) -> {
if (MediaType.APPLICATION_JSON.isCompatibleWith(exchange.getResponse().getHeaders().getContentType())) {
try {
JsonNode jsonBodyContent = mapper.readValue(body, JsonNode.class);
JsonNode jsonNode = mapper.readValue(body, JsonNode.class);
removeJsonAttribute(jsonBodyContent, config.getFieldList(), config.isDeleteRecursively());
removeJsonAttributes(jsonNode, config.getFieldList(), config.isDeleteRecursively());
body = mapper.writeValueAsString(jsonBodyContent);
body = mapper.writeValueAsString(jsonNode);
}
catch (JsonProcessingException e) {
throw new RuntimeException(e);
return Mono.error(new IllegalStateException("Failed to process JSON of response body.", e));
}
}
return Mono.just(body);
@@ -93,22 +93,12 @@ public class RemoveJsonAttributesResponseBodyGatewayFilterFactory extends
private ObjectMapper mapper = new ObjectMapper();
private void removeJsonAttribute(JsonNode jsonBodyContent, List<String> fieldsToRemove, boolean deleteRecursively) {
if (deleteRecursively) {
for (JsonNode jsonNode : jsonBodyContent) {
if (jsonNode instanceof ObjectNode) {
((ObjectNode) jsonNode).remove(fieldsToRemove);
removeJsonAttribute(jsonNode, fieldsToRemove, true);
}
if (jsonNode instanceof ArrayNode) {
for (JsonNode node : jsonNode) {
removeJsonAttribute(node, fieldsToRemove, true);
}
}
}
private void removeJsonAttributes(JsonNode jsonNode, List<String> fieldNames, boolean deleteRecursively) {
if (jsonNode instanceof ObjectNode objectNode) {
objectNode.remove(fieldNames);
}
if (jsonBodyContent instanceof ObjectNode) {
((ObjectNode) jsonBodyContent).remove(fieldsToRemove);
if (deleteRecursively) {
jsonNode.forEach(childNode -> removeJsonAttributes(childNode, fieldNames, true));
}
}

View File

@@ -19,6 +19,7 @@ package org.springframework.cloud.gateway.filter.factory;
import java.util.Map;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringBootConfiguration;
@@ -30,8 +31,12 @@ import org.springframework.cloud.gateway.test.BaseWebClientTests;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@@ -42,10 +47,10 @@ import static org.springframework.cloud.gateway.test.TestUtils.getMap;
*/
@SpringBootTest(webEnvironment = RANDOM_PORT)
@DirtiesContext
public class RemoveJsonAttributesResponseBodyGatewayFilterFactoryTests extends BaseWebClientTests {
class RemoveJsonAttributesResponseBodyGatewayFilterFactoryTests extends BaseWebClientTests {
@Test
public void removeJsonAttributeRootWorks() {
void removeJsonAttributeRootWorks() {
testClient.post()
.uri("/post")
.header("Host", "www.removejsonattributes.org")
@@ -70,8 +75,7 @@ public class RemoveJsonAttributesResponseBodyGatewayFilterFactoryTests extends B
}
@Test
public void removeJsonAttributeRecursivelyWorks() {
void removeJsonAttributeRecursivelyWorks() {
testClient.post()
.uri("/post")
.header("Host", "www.removejsonattributesrecursively.org")
@@ -93,8 +97,7 @@ public class RemoveJsonAttributesResponseBodyGatewayFilterFactoryTests extends B
}
@Test
public void removeJsonAttributeNoMatchesWorks() {
void removeJsonAttributeNoMatchesWorks() {
testClient.post()
.uri("/post")
.header("Host", "www.removejsonattributesnomatches.org")
@@ -113,6 +116,21 @@ public class RemoveJsonAttributesResponseBodyGatewayFilterFactoryTests extends B
});
}
@Test
void raisedWhenRemoveJsonAttributes() {
testClient.post()
.uri("/post")
.header("Host", "www.raisederrorwhenremovejsonattributes.org")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.exchange()
.expectStatus()
.is5xxServerError()
.expectBody(String.class)
.consumeWith(result -> {
assertThat(result.getResponseBody()).isEqualTo("Failed to process JSON of response body.");
});
}
@EnableAutoConfiguration
@SpringBootConfiguration
@Import(DefaultTestConfig.class)
@@ -142,9 +160,27 @@ public class RemoveJsonAttributesResponseBodyGatewayFilterFactoryTests extends B
.host("{sub}.removejsonattributesnomatches.org")
.filters(f -> f.removeJsonAttributes("test"))
.uri(uri))
.route("raised_error_when_remove_json_attributes",
r -> r.path("/post")
.and()
.host("{sub}.raisederrorwhenremovejsonattributes.org")
.filters(f -> f.removeJsonAttributes("test")
.modifyResponseBody(String.class, String.class,
(exchange, response) -> Mono.just("{\"invalid_json\": test")))
.uri(uri))
.build();
}
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(IllegalStateException.class)
public ResponseEntity<String> handleIllegalException(IllegalStateException ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getMessage());
}
}
}
}