0
votes

I have to develop a Camel REST route with path-based routing. The scenario is as follows: we have a business partner which provided a REST web service for displaying documents. The REST web service is deployed on 3 different servers, depending on the geographic location. So we basically have 3 server like these:

http://north.acme.com/flowdocv2/rest/repository/attachment/{id}/findById
http://center.acme.com/flowdocv2/rest/repository/attachment/{id}/findById
http://south.acme.com/flowdocv2/rest/repository/attachment/{id}/findById

My aim is to develop a single Camel route to map these server, accepting the name of the server in the path. Something like this:

http://my.camel.com/center/repository/attachment/{id}/findById
http://my.camel.com/north/repository/attachment/{id}/findById
http://my.camel.com/south/repository/attachment/{id}/findById

My (simplified and not working) blueprint.xml:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
    xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      
    xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0    
    https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd  
    http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">

<cm:property-placeholder persistent-id="my.config.file"/>

<reference id="sharedNettyHttpServer" interface="org.apache.camel.component.netty4.http.NettySharedHttpServer"/>

<camelContext id="my_context" xmlns="http://camel.apache.org/schema/blueprint">
    <restConfiguration component="netty4-http">
        <endpointProperty key="nettySharedHttpServer" value="#sharedNettyHttpServer"/>
    </restConfiguration>
    <rest path="/center/repository">
        <get uri="/attachment/{attachmentId}/findById">
            <route streamCache="true" trace="true">
                <to uri="http://center.acme.com/flowdocv2/rest?bridgeEndpoint=true"/>
            </route>
        </get>            
    </rest>
    <rest path="/north/repository">
        <get uri="/attachment/{attachmentId}/findById">
            <route streamCache="true" trace="true">
                <to uri="http://north.acme.com/flowdocv2/rest?bridgeEndpoint=true"/>
            </route>
        </get>            
    </rest>
</camelContext>
</blueprint>

The problem is that I don't know how to remove /center, /north or /south from the path, so the header is forwared to the destination service, which doesn't know how to deal with it. Invoking:

http://my.camel.com/center/repository/attachment/{id}/findById

results in the following URL being invoked on the destination server:

http://center.acme.com/flowdocv2/rest/center/repository/attachment/{id}/findById

How to get rid of center? I don't want to deploy 3 camel routes on different ports.

Thank you

1

1 Answers

0
votes

I think it is actually a bit easier. As long as you do not hang onto netty and you are using Camel 2.11+ you can use camel-urlrewrite

Basically, you define a single rewrite rule in a configuration and add this to your route bundle.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN"
    "http://www.tuckey.org/res/dtds/urlrewrite4.0.dtd">
    <urlrewrite>
        <rule>
            <name>Generic Proxy</name>
            <note>
                This rule completely rewrites the url to call.
                Basically, in Camel's "to", you could write whatever you want
            </note>
            <from>^/(.*?)/(.*)</from>
            <to>http://$1.acme.com/flowdocv2/rest/$2</to>
        </rule>
    </urlrewrite>

Now, you can utilize a rather simple route:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0" xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0    
    https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd  
    http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">

    <bean id="myRewrite" class="org.apache.camel.component.urlrewrite.HttpUrlRewrite">
        <property name="configFile" value="class/path/to/proxyrewrite.xml" />
    </bean>

    <camelContext id="my_context" xmlns="http://camel.apache.org/schema/blueprint">
        <route id="proxyRoute">
            <from uri="jetty:http://localhost:9090/proxy" />
            <to uri="jetty:http://somewhere/myapp2?bridgeEndpoint=true&amp;throwExceptionOnFailure=false&amp;urlRewrite=#myRewrite" />
        </route>
    </camelContext>
</blueprint>

However, netty is not supported, so I chose the next best thing.

When you call http://localhost:9090/proxy/north/foo, the rewrite will actually change the url to call to http://north.acme.com/flowdoc2/rest/foo.

There are a few caveats with this. First, you have to use one of the supported components for UrlRewrite. Second, it seems that you have to have the rewrite config file in you classpath - so no blueprint-only route. Third: I did not test it, but I think you get the gist. I make this a community wiki answer, so that others, more capable than me, can expand on this answer.