From 0f747f362a2d81ff676d73c6c8772e79d7dfceba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6rdes?= Date: Fri, 6 Sep 2024 13:07:43 +0200 Subject: [PATCH] Enhance ShadowingInterceptor to include header in request cloning - Add header parameter to cloneRequestAndSend and buildExchange methods - Capture request headers for shadowing functionality - Update tests to verify header handling during shadow requests --- .../shadowing/ShadowingInterceptor.java | 11 ++++--- .../shadowing/ShadowingInterceptorTest.java | 33 ++++++++++++++++--- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/shadowing/ShadowingInterceptor.java b/core/src/main/java/com/predic8/membrane/core/interceptor/shadowing/ShadowingInterceptor.java index 7e0d1df3b..929db9a66 100644 --- a/core/src/main/java/com/predic8/membrane/core/interceptor/shadowing/ShadowingInterceptor.java +++ b/core/src/main/java/com/predic8/membrane/core/interceptor/shadowing/ShadowingInterceptor.java @@ -31,6 +31,7 @@ public class ShadowingInterceptor extends AbstractInterceptor { @Override public Outcome handleRequest(Exchange exc) throws Exception { + Header header = new Header(exc.getRequest().getHeader()); exc.getRequest().getBody().getObservers().add(new MessageObserver() { @Override public void bodyRequested(AbstractBody body) {} @@ -41,7 +42,7 @@ public void bodyChunk(byte[] buffer, int offset, int length) {} @Override public void bodyComplete(AbstractBody body) { - cloneRequestAndSend(body, exc); + cloneRequestAndSend(body, exc, header); } }); return CONTINUE; @@ -52,12 +53,12 @@ public String getShortDescription() { return "Sends requests to shadow hosts (processed in the background)."; } - public void cloneRequestAndSend(AbstractBody body, Exchange exchange) { + public void cloneRequestAndSend(AbstractBody body, Exchange exchange, Header header) { ExecutorService executor = newCachedThreadPool(); for (Target target : targets) { Exchange exc; try { - exc = buildExchange(body, exchange, target); + exc = buildExchange(body, exchange, target, header); } catch (Exception e) { log.error("Error creating request for target {}", target, e); continue; @@ -75,10 +76,10 @@ public void cloneRequestAndSend(AbstractBody body, Exchange exchange) { } } - static Exchange buildExchange(AbstractBody body, Exchange exchange, Target target) throws URISyntaxException, IOException { + static Exchange buildExchange(AbstractBody body, Exchange exchange, Target target, Header header) throws URISyntaxException, IOException { return new Request.Builder() .body(body.getContent()) - .header(new Header(exchange.getRequest().getHeader())) + .header(header) .method(exchange.getRequest().getMethod()) .url( new URIFactory(), diff --git a/core/src/test/java/com/predic8/membrane/core/interceptor/shadowing/ShadowingInterceptorTest.java b/core/src/test/java/com/predic8/membrane/core/interceptor/shadowing/ShadowingInterceptorTest.java index 66b870108..31d057c64 100644 --- a/core/src/test/java/com/predic8/membrane/core/interceptor/shadowing/ShadowingInterceptorTest.java +++ b/core/src/test/java/com/predic8/membrane/core/interceptor/shadowing/ShadowingInterceptorTest.java @@ -7,6 +7,7 @@ import com.predic8.membrane.core.http.Header; import com.predic8.membrane.core.http.Request; import com.predic8.membrane.core.interceptor.misc.ReturnInterceptor; +import com.predic8.membrane.core.interceptor.misc.SetHeaderInterceptor; import com.predic8.membrane.core.rules.AbstractServiceProxy.Target; import com.predic8.membrane.core.rules.Rule; import com.predic8.membrane.core.rules.ServiceProxy; @@ -16,6 +17,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import java.util.List; @@ -24,8 +26,7 @@ import static io.restassured.RestAssured.given; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.*; class ShadowingInterceptorTest { @@ -55,7 +56,8 @@ void setUp() throws Exception { .buildExchange(), new Target() {{ setUrl("https://www.predic8.com:9000/foo"); - }} + }}, + header ); } @@ -72,7 +74,14 @@ static void startup() throws Exception { setHost("localhost"); setPort(3000); }})); - interceptorRule.setInterceptors(List.of(shadowingInterceptor, new ReturnInterceptor())); + interceptorRule.setInterceptors(List.of( + shadowingInterceptor, + new SetHeaderInterceptor() {{ + setName("foo"); + setValue("bar"); + }}, + new ReturnInterceptor() + )); interceptorRouter.getRuleManager().addProxyAndOpenPortIfNew(interceptorRule); interceptorRouter.init(); @@ -109,10 +118,24 @@ void testIfShadowTargetIsCalled() throws Exception { verify(returnInterceptorMock, times(1)).handleRequest(any(Exchange.class)); } + /** + * Verifies that the shadow target is called and the ReturnInterceptor's + * handleRequest() is invoked with an Exchange object not containing the "foo" header. + */ + @Test + void testIfShadowTargetHasFooHeader() throws Exception { + given().when().get("http://localhost:2000").then().statusCode(200); + + ArgumentCaptor exchangeCaptor = ArgumentCaptor.forClass(Exchange.class); + verify(returnInterceptorMock, atLeastOnce()).handleRequest(exchangeCaptor.capture()); + + assertNull(exchangeCaptor.getValue().getRequest().getHeader().getFirstValue("foo")); + } + + @Test void buildExchangeTest() { assertNotNull(exc); - assertNotSame(header, exc.getRequest().getHeader()); assertEquals("POST", exc.getRequest().getMethod()); assertEquals("/foo", exc.getRequest().getUri()); assertEquals("https://www.predic8.com:9000/foo", exc.getDestinations().get(0));