Skip to content

Commit

Permalink
Internal proxy example fix (#1421)
Browse files Browse the repository at this point in the history
* Initial

* Fix service proxy configuration and update tests for internal proxy

- Change configuration file reference in `service-proxy.sh` from `proxies_soap.xml` to `proxies.xml`.
- Update copyright year in `InternalProxyTest.java` from 2022 to 2024.
- Refactor test methods to enhance readability and consistency.
- Modify the test for express order processing to use RestAssured for HTTP requests.
- Add tests for regular order scenarios to ensure they fall through correctly.

* express sample

* Update README and tests for internal proxy example

Clarify instructions for running the internal proxy example in the README file. Adjust the base URL in `InternalProxyTest` to match the correct port. Modify the assertions to reflect expected responses, ensuring they align with the newly defined processing routes for express and normal orders.

---------

Co-authored-by: Thomas Bayer <[email protected]>
  • Loading branch information
t-burch and predic8 authored Dec 18, 2024
1 parent bfa4901 commit d3fbf28
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 194 deletions.
133 changes: 35 additions & 98 deletions distribution/examples/internalproxy/README.md
Original file line number Diff line number Diff line change
@@ -1,117 +1,54 @@
# Internal Proxy

This example explains how to realize complex message flows and how to break an api or serviceProxy into smaller units. Instead of an external target a request can be routed to an internal proxy. The internal proxy can offer reusable functionality that is shared by multiple APIs.

## SOAP Example
Route requests to internal proxies for reusable functionality across multiple APIs and content-based routing.

## Running the Example

Let's start first example with the `<soapProxy>`

1. Go to the `examples/internalProxy` directory

2. Execute `service-proxy.sh`

3. Go to [http://localhost:2000/axis2/services/BLZService](http://localhost:2000/axis2/services/BLZService)

4. Observe that `soapProxy` takes the `WSDL` file from `<internalProxy>` and populates and serves the webpage
## How it is done

The following part describes the `<soapProxy>` example in detail.

Let's take a look at the `proxies_soap.xml` file.

In below line you can see definition of `<soapProxy>`

`<soapProxy wsdl="service:mysoapbackend/axis2/services/BLZService?wsdl" port="2000">`

When we put `URL`s starting with `service:` scheme in `wsdl` attribute, these URLs are resolved for `<internalProxy>` with the name that comes after
`service:` part until next `/`.

In this example our `<soapProxy>` looks at value of `wsdl` attribute, parses `URL` and fetches the `WSDL` file from `<internalProxy>` defined in line below.
***Note:*** *You can test these requests using the provided HTTP file or cURL snippets.*

```<internalProxy name="mysoapbackend">```
1. **Navigate** to the `examples/internalproxy` directory.
2. **Start** Membrane by executing `service-proxy.sh` (Linux/Mac) or `service-proxy.bat` (Windows).
3. **Execute the following requests** (alternatively, use the `requests.http` file):
- **Normal Processing**:
```bash
curl http://localhost:2020
```
Response: `Normal processing!`

As you can see our `<soapProxy>` knows which `<internalProxy>` it connects to, through the `name` attribute of `<internalProxy>`.

You can also run below command and create valid `SOAP` request that would go through `<soapProxy>` and `<internalProxy>` we defined
in `proxies_soap.xml` file. Don't forget to run it in the `examples/internalproxy` folder.
```
curl -d @soap_request.xml http://localhost:2000/axis2/services/BLZService --header "Content-Type: text/xml;charset=UTF-8" --header "SOAPAction:Get"
```

It is also possible to use interceptors in `<internalProxy>` like other proxies. This is useful when you have tasks that are common for other proxies.
You can put them in `<internalProxy>` and route other proxies using `service:` URL scheme.
If you ran above command you can see `X-Example-Header: true` header in the console you have run Membrane.
In our example we use `<groovy>` interceptor for putting header and printing it. Have a look at `examples/groovy` folder if you are interested.

### SERVICE PROXY EXAMPLE

#### RUNNING THE EXAMPLE

This section explains how to run the example with `<serviceProxy>`

1. Go to the `examples/internalProxy` directory

2. Go to the `service-proxy.sh` file and change below line to second line below

```
java -classpath "$CLASSPATH" com.predic8.membrane.core.Starter -c proxies_soap.xml
java -classpath "$CLASSPATH" com.predic8.membrane.core.Starter -c proxies_service.xml
```
3. Execute `service-proxy.sh`
- **Express Processing**:
```bash
curl -X POST -d @express.xml http://localhost:2020
```
Response: `Express processing!`

4. Execute `curl localhost:2000` in another console
## How it works

5. Take a look at the output of the console that you are running Membrane. You should see the line: `"Inside proxy example_main."`
The main API endpoint configuration uses a `<switch>` element to change the url of `<target>` conditionally.
In this instance, we use internal proxies to encapsulate our plugins in separate routines,
this makes them reusable and cleans up our APIs:

6. Now execute below command

```curl -d @express.xml localhost:2000```

7.Observe that additionally to above output we got `Inside proxy mybackend.`

#### HOW IT IS DONE

The following part describes the `<serviceProxy>` example in detail.

Open `proxies_service.xml` in text editor.

First we define a `<serviceProxy>` with like below.

```
<serviceProxy port="2000" name="example_main">
```

When we run first command in step 4 from a command line, `<groovy>` interceptor we defined prints to the console

```
<groovy>
println("Inside proxy example_main.")
</groovy>
```

You can see in file we have `<switch>` element. This is a `XPathCBRInterceptor`.

```
```xml
<api port="2020">
<switch>
<case xPath="//order[@express='yes']" service="mybackend" />
<case xPath="//order[@express='yes']" service="express" />
</switch>
<target url="service:normal" />
</api>
```

`XPathCBRInterceptor` changes the target of exchange based on XPath expressions.

In our example when we run the command from step 6, our `XPathCBRInterceptor` checks the `express.xml` file we put into request for given `XPath` expression and
sends the exchange to `mybackend` service if the condition is true.
***Note:*** InternalProxies can only be called from other proxies and APIs, not from external sources.

Two internal proxies handle different processing paths:

`XPathCBRInterceptor` knows which proxy to send exchange to through `service` attribute.
Since our `internalProxy` has the name `mybackend`, Membrane sends the exchange to `<internalProxy>` defined like below.
```xml
<internalProxy name="express">
<static>Express processing!</static>
<return/>
</internalProxy>

<internalProxy name="normal">
<static>Normal processing!</static>
<return/>
</internalProxy>
```
<internalProxy name="mybackend">
```

---
See:
- [internalProxy](https://membrane-soa.org/api-gateway-doc/current/configuration/reference/internalProxy.htm) reference
7 changes: 7 additions & 0 deletions distribution/examples/internalproxy/normal.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<order>
<items>
<item id="3" count="1"/>
<item id="5" count="1"/>
<item id="2" count="1"/>
</items>
</order>
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,26 @@
http://membrane-soa.org/proxies/1/ http://membrane-soa.org/schemas/proxies-1.xsd">

<router>
<api port="2000" name="example_main">

<api port="2020">
<switch>
<!-- If the case is true the message is routed to the mybackend internalProxy below -->
<case xPath="//order[@express='yes']" service="mybackend" />
<!-- In case of 'true' set destination to internalProxy -->
<case xPath="//order[@express='yes']" service="express" />
</switch>
<groovy>
println("Inside proxy example_main.")
</groovy>
<target url="http://www.predic8.de"/>
<target url="service:normal" />
</api>

<!-- An internalProxy is like a function or subroutine for an API. -->
<internalProxy name="mybackend">
<groovy>
println("Inside proxy mybackend.")
</groovy>
<target url="http://www.predic8.de"/>
<internalProxy name="express">
<static>Express processing!</static>
<return/>
</internalProxy>

<internalProxy name="normal">
<static>Normal processing!</static>
<return/>
</internalProxy>

</router>

</spring:beans>
43 changes: 0 additions & 43 deletions distribution/examples/internalproxy/proxies_soap.xml

This file was deleted.

11 changes: 11 additions & 0 deletions distribution/examples/internalproxy/requests.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
POST http://localhost:2000
Content-Type: text/xml

<order express='no'/>

###

POST http://localhost:2000
Content-Type: text/xml

<order express='yes'/>
2 changes: 1 addition & 1 deletion distribution/examples/internalproxy/service-proxy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ homeSet() {
CLASSPATH="$CLASSPATH:$MEMBRANE_HOME/starter.jar"
export CLASSPATH
echo Membrane Router running...
java -classpath "$CLASSPATH" com.predic8.membrane.core.Starter -c proxies_soap.xml
java -classpath "$CLASSPATH" com.predic8.membrane.core.Starter -c proxies.xml

}

Expand Down
8 changes: 0 additions & 8 deletions distribution/examples/internalproxy/soap_request.xml

This file was deleted.

37 changes: 37 additions & 0 deletions distribution/examples/soap/secured-wsdl/proxies.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

<spring:beans xmlns="http://membrane-soa.org/proxies/1/"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://membrane-soa.org/proxies/1/ http://membrane-soa.org/schemas/proxies-1.xsd">


<router>

<!-- Access to some WSDL documents is protected by TLS or password.
Because there are so many authentication mechanisms soapProxy
does not provide one. Instead route the WSDL requests to an
internal Proxy where you can use any authentication that is needed.
-->

<soapProxy port="2010" wsdl="service:wsdl/?wsdl">
</soapProxy>

<internalProxy name="wsdl">
<sampleSoapService/>
<!--
Replace <sampleSoapService/> with a target pointing to a protected WSDL
<target host="sample" port="443">
<ssl>
<keystore ...>
<truststore ...>
</ssl>
</target>
-->
</internalProxy>

</router>

</spring:beans>
Loading

0 comments on commit d3fbf28

Please sign in to comment.