Reverse Proxy or Web Proxy

Sample Number

102

Level

Advanced

Description

This sample demonstrates the usage of UltraESB as a Reverse Proxy or a Web Proxy and the usage of scripts in mediation

Use Case

I have some random content, (could be a web site or anything that can be transferred on the network) and I want the ESB to act as a reverse proxy and possibly mediate the requests/response with any scripting language. Any response going with HTTP "Location" headers from the back end server needs to be switched to ESB, so that all traffic to the back end goes through the ESB. In other words I want my ESB to act as a web proxy for my web site.

web proxy

As shown in the above diagram, instead of directly talking to the back-end server, UltraESB acts as the proxy for all the requests going to the back-end server.

Service interactions vs HTML responses
Although the UltraESB is mainly targetted towards service interactions, sometimes services return HTML content, which is not typically well handled by an ESB. This example shows the ability of the UltraESB to proxy HTML responses, acting as a Reverse Proxy

Sample Configuration

The configuration for a web proxy is again a proxy service within the UltraESB configuration, but it is a special type of a proxy service which specifies its URL to the transport. The proxy service is accepting any request over the transport and forwarding it to the target server. The transport property "ultra.transport.url" specifies a URL pattern over which the proxy service will accept messages, which defaults to the "/service/<proxy-id>" if the per said property is not specified.

Sample web proxy for the local back-end servlet

 1<u:proxy id="web-proxy-1">
 2  <u:transport id="http-8280">
 3    <u:property name="ultra.transport.url" value="*"/>
 4  </u:transport>
 5  <u:target>
 6    <u:inDestination>
 7      <u:address type="prefix">http://localhost:9000</u:address>
 8      <u:property name="ultra.endpoint.switch_location_headers_to" value="http://localhost:8280/"/>
 9    </u:inDestination>
10    <u:outDestination>
11      <u:address type="response"/>
12    </u:outDestination>
13  </u:target>
14</u:proxy>

The above configuration exposes a proxy service named "web-proxy-1" which listens on any request comes into the ESB and forwards them to the back-end server running at port 9000. Also note the property "ultra.endpoint.switch_location_headers_to" in the in destination which specifies the value of the location headers, in this case to the ESB allowing all the traffic to go through the ESB.

While the above configuration is for a straight reverse proxy, you could also mediate the request, response or both with UltraESB. The following configuration uses JavaScript to mediate the request message to include/change query parameters of the request.

UltraESB as a web-proxy with mediation

 1<u:proxy id="web-proxy-2">
 2  <u:transport id="http-8281">
 3    <u:property name="ultra.transport.url" value="/vpath"/>
 4    <u:property name="ultra.http.strip_url_prefix" value="/vpath"/>
 5  </u:transport>
 6  <u:target>
 7    <u:inSequence>
 8      <u:script ><![CDATA[
 9        var map = msg.getMessageProperty("ultra.http.query_param_map");
10        var val = map.remove('x');
11        if (val != null) map.put('a', val);
12        val = map.remove('y');
13        if (val != null) map.put('b', val);
14        val = map.remove('z');
15        if (val != null) map.put('c', val);
16      ]]></u:script>
17    </u:inSequence>
18    <u:inDestination>
19      <u:address type="prefix">http://localhost:9000/service/HtmlServlet</u:address>
20      <u:property name="ultra.endpoint.switch_location_headers_to" value="http://localhost:8280/vpath"/>
21    </u:inDestination>
22    <u:outDestination>
23      <u:address type="response"/>
24    </u:outDestination>
25  </u:target>
26</u:proxy>

This proxy service is hosted over HTTP port 8281, and it also shows how multiple transport instances can be configured with the UltraESB. This allows an UltraESB instance for example to show one SSL certificate to one set of users, and another for another set of users! It also makes the implementation of HTTP Basic or Digest authentication simpler across multiple services. It also states that it should use "/vpath" as its URL. In addition, its advised to drop this same prefix, so that the request could be forwarded to the actual service using the prefix URL http://localhost:9000/service/HtmlServlet. However, responses returned to the client maybe advised to re-write certain headers such as the "Location" header - so that clients will always be exposed only to the proxy service.

The in sequence of the proxy service will substitue parameters such as "?x=1&y=2&z=3" to "?a=1&b=2&c=3" using a Javascript snippet, which is the mediation in this particular case. Javascript is the default JSR 223 scripting language bundled with the JDK. You may select ANY scripting language [e.g. Groovy, Ruby, FreeMarker, Python, Velocity erc - See https://en.wikipedia.org/wiki/List_of_JVM_languages for a complete list support by the JDK 7 after placing the necessary library JAR files into the UltraESB library directories.

While this proxy service identified as "web-proxy-2" uses JavaScript as the language for mediation the proxy service configuration "web-proxy-3" shows the usage of Groovy as the language to do the same mediation.

In Action

To try out this sample, start the ToolBox and the sample Jetty server within it. The sample server hosts a servlet that outputs HTML content. One can issue a GET request to the URL http://localhost:9000/service/HtmlServlet from a browser to get this response directly from the servlet as shown below. Any optional parameters passed to the servlet will be displayed within the response body as shown below.

web proxy 1

Now, start the sample configuration 102 of the UltraESB through the ToolBox, or the command line as follows

$ cd /opt/ultraesb-2.6.1/bin
$ ./ultraesb.sh -sample 102 

Now issue the same request, after replacing the port from 9000 to 8280 - which is the port use by UltraESB. Thus the full URL would be something like http://localhost:8280/service/HtmlServlet?a=1&b=2 and will yield the following result.

html proxy 2

You can now see the UltraESB acting as a web proxy for the simple back end servlet. Next we will see how the UltraESB can even mediate such requests through it with the "web-proxy-2" configuration discussed earlier. As pointed out in the configuration the "web-proxy-2" is running over a different HTTP transport configured with port 8281 so request to the URL http://localhost:8281/vpath?x=1&y=2&z=3 will now be handled by the "web-proxy-2".

html proxy 3

If you observe the HTML response on the browser, you will see that "/vpath" context has been dropped and the request has been directed to the back-end servlet with query parameters x, y, z changed into a, b, c consecutively, meaning that the mediation has taken place before the request is forwarded to the servlet.

Advance Analysis

If you would like to try out further examples, try commenting the "web-proxy-1" and uncommenting the "web-proxy" and restarting the UltraESB. Now directing your browser to URL http://localhost:8280/ will instead take you to the MIT home page as shown below. Notice that the links within the web page body have been re-written to point back at the proxy instead of the MIT pages!

mit

The configuration driving this is the proxy service given below.Note that the response is read into a String, and a simple '’replaceAll'’ call has been made in this example to perform the mediation - although much more advanced and useful mediation is available for use.

Configuration for a web proxy for the MIT web site

 1<u:proxy id="web-proxy">
 2  <u:transport id="http-8280">
 3    <u:property name="ultra.transport.url" value="*"/>
 4  </u:transport>
 5  <u:target>
 6    <u:inDestination>
 7      <u:address type="prefix">http://web.mit.edu</u:address>
 8      <u:property name="ultra.endpoint.switch_location_headers_to" value="http://localhost:8280/"/>
 9    </u:inDestination>
10    <u:outSequence>
11      <u:java><![CDATA[
12        String original = mediation.readPayloadAsString(msg);
13        if (original != null) {
14          mediation.setPayloadFromString(msg, original.replaceAll("web.mit.edu", "localhost:8280"));
15        }
16      ]]></u:java>
17    </u:outSequence>
18    <u:outDestination>
19      <u:address type="response"/>
20    </u:outDestination>
21  </u:target>
22</u:proxy>

You have just seen the advance content handling capabilities of the UltraESB, which most of the other ESBs fail to handle.

Related Samples

Sample Number

Sample Title

101

Restful Proxy Services

In this topic
In this topic
Contact Us