From cd5a10f50b2be5c3a43029d539df53d4d5a159e2 Mon Sep 17 00:00:00 2001 From: Thomas Bayer Date: Fri, 20 Feb 2026 15:38:45 +0100 Subject: [PATCH] Add SOAP routing tutorials: tests for SOAPAction and wrapper element, and corresponding YAML configurations --- .../soap/RoutingBySOAPActionTutorialTest.java | 67 ++++++++++++++++++ .../RoutingByWrapperElementTutorialTest.java | 70 +++++++++++++++++++ .../soap/70-Routing-by-Wrapper-Element.yaml | 38 ++++++++++ .../soap/75-Routing-by-SOAPAction.yaml | 42 +++++++++++ 4 files changed, 217 insertions(+) create mode 100644 distribution/src/test/java/com/predic8/membrane/tutorials/soap/RoutingBySOAPActionTutorialTest.java create mode 100644 distribution/src/test/java/com/predic8/membrane/tutorials/soap/RoutingByWrapperElementTutorialTest.java create mode 100644 distribution/tutorials/soap/70-Routing-by-Wrapper-Element.yaml create mode 100644 distribution/tutorials/soap/75-Routing-by-SOAPAction.yaml diff --git a/distribution/src/test/java/com/predic8/membrane/tutorials/soap/RoutingBySOAPActionTutorialTest.java b/distribution/src/test/java/com/predic8/membrane/tutorials/soap/RoutingBySOAPActionTutorialTest.java new file mode 100644 index 0000000000..c4593c7be6 --- /dev/null +++ b/distribution/src/test/java/com/predic8/membrane/tutorials/soap/RoutingBySOAPActionTutorialTest.java @@ -0,0 +1,67 @@ +/* Copyright 2026 predic8 GmbH, www.predic8.com + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ + +package com.predic8.membrane.tutorials.soap; + +import org.junit.jupiter.api.*; + +import static io.restassured.RestAssured.*; +import static org.hamcrest.Matchers.*; + +public class RoutingBySOAPActionTutorialTest extends AbstractSOAPTutorialTest { + + @Override + protected String getTutorialYaml() { + return "75-Routing-by-SOAPAction.yaml"; + } + + @Test + void routesToGetCityBySOAPAction() { + // @formatter:off + given() + .header("SOAPAction", "https://predic8.de/city-service/get") + .when() + .post("http://localhost:2000") + .then() + .statusCode(200) + .body(equalTo("getCity")); + // @formatter:on + } + + @Test + void routesToCreateCityBySOAPAction() { + // @formatter:off + given() + .header("SOAPAction", "https://predic8.de/city-service/create") + .when() + .post("http://localhost:2000") + .then() + .statusCode(200) + .body(equalTo("createCity")); + // @formatter:on + } + + @Test + void fallbackRouteForUnknownSOAPAction() { + // @formatter:off + given() + .header("SOAPAction", "https://predic8.de/city-service/unknown") + .when() + .post("http://localhost:2000") + .then() + .statusCode(404); + // @formatter:on + } + +} diff --git a/distribution/src/test/java/com/predic8/membrane/tutorials/soap/RoutingByWrapperElementTutorialTest.java b/distribution/src/test/java/com/predic8/membrane/tutorials/soap/RoutingByWrapperElementTutorialTest.java new file mode 100644 index 0000000000..751f1117e8 --- /dev/null +++ b/distribution/src/test/java/com/predic8/membrane/tutorials/soap/RoutingByWrapperElementTutorialTest.java @@ -0,0 +1,70 @@ +/* Copyright 2026 predic8 GmbH, www.predic8.com + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ + +package com.predic8.membrane.tutorials.soap; + +import org.junit.jupiter.api.*; + +import java.io.*; + +import static io.restassured.RestAssured.*; +import static org.hamcrest.Matchers.*; + +public class RoutingByWrapperElementTutorialTest extends AbstractSOAPTutorialTest { + + @Override + protected String getTutorialYaml() { + return "70-Routing-by-Wrapper-Element.yaml"; + } + + @Test + void routesToGetCityByWrapperElement() throws IOException { + // @formatter:off + given() + .contentType("text/xml") + .body(readFileFromBaseDir("city.soap.xml")) + .when() + .post("http://localhost:2000") + .then() + .statusCode(200) + .body(equalTo("getCity")); + // @formatter:on + } + + @Test + void fallbackRouteForNonMatchingBody() { + // @formatter:off + given() + .contentType("text/xml") + .body("" + + "" + + "") + .when() + .post("http://localhost:2000") + .then() + .statusCode(404); + // @formatter:on + } + + @Test + void fallbackRouteWithoutBody() { + // @formatter:off + given() + .when() + .post("http://localhost:2000") + .then() + .statusCode(404); + // @formatter:on + } +} diff --git a/distribution/tutorials/soap/70-Routing-by-Wrapper-Element.yaml b/distribution/tutorials/soap/70-Routing-by-Wrapper-Element.yaml new file mode 100644 index 0000000000..5cddf66856 --- /dev/null +++ b/distribution/tutorials/soap/70-Routing-by-Wrapper-Element.yaml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=https://www.membrane-api.io/v7.1.0.json +# +# Tutorial: SOAP Routing by Wrapper Element +# +# Routes SOAP requests by inspecting the wrapper element inside the SOAP Body. +# Some SOAP stacks route using the SOAPAction header instead +# (see 75-Routing-by-SOAPAction.yaml). +# +# Try: +# curl localhost:2000 +# curl localhost:2000 -H "Content-Type: text/xml" -d @city.soap.xml -v + +components: + ns: + xmlConfig: + namespaces: + - prefix: c + uri: https://predic8.de/cities + +--- +api: + port: 2000 + test: //c:getCity + language: xpath + flow: + - setBody: + value: getCity + - return: + status: 200 + +--- +api: + port: 2000 + flow: + - log: + message: "Missed!" + - return: + status: 404 \ No newline at end of file diff --git a/distribution/tutorials/soap/75-Routing-by-SOAPAction.yaml b/distribution/tutorials/soap/75-Routing-by-SOAPAction.yaml new file mode 100644 index 0000000000..d3b584850c --- /dev/null +++ b/distribution/tutorials/soap/75-Routing-by-SOAPAction.yaml @@ -0,0 +1,42 @@ +# yaml-language-server: $schema=https://www.membrane-api.io/v7.1.0.json +# +# Tutorial: SOAP Routing by SOAPAction +# +# Routes SOAP requests based on the SOAPAction header. +# A more common approach is routing by the SOAPBody child element +# (see sample 70-Routing-by-Wrapper-Element.yaml). +# +# Try: +# curl localhost:2000 -H "SOAPAction: https://predic8.de/city-service/get" +# curl localhost:2000 -H "SOAPAction: https://predic8.de/city-service/create" +# +# Notes: +# - Some SOAP stacks send SOAPAction with quotes, e.g. "https://.../get" + +api: + port: 2000 + test: header.SOAPAction == 'https://predic8.de/city-service/get' + flow: + - setBody: + value: getCity + - return: + status: 200 + +--- +api: + port: 2000 + test: header.SOAPAction == 'https://predic8.de/city-service/create' + flow: + - setBody: + value: createCity + - return: + status: 200 + +--- +api: + port: 2000 + flow: + - log: + message: "Not supported: ${header.SOAPAction}" + - return: + status: 404 \ No newline at end of file