Camel REST - Path based routing - rest

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

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&throwExceptionOnFailure=false&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.

Related

Exception communicating with endpoint

I am implementing an application which would be exposed using RESTful web service. This application would firstly consume a RESTful web service to get the JSON file and would return this JSON file to the requestor (application which would consume my service). I am facing issues consuming the web service.
ERROR:
org.apache.camel.component.restlet.RestletOperationException: Restlet operation failed invoking https:// <--url-->
with statusCode: 1001 /n responseBody:HTTPS/1.1 - Communication Error (1001) -
The connector failed to complete the communication with the server
at org.apache.camel.component.restlet.RestletProducer.populateRestletProducerException(RestletProducer.java:233)
CODE:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext id="camelcontext" xmlns="http://camel.apache.org/schema/spring">
<restConfiguration component="restlet" port="9091"/>
<rest path="/say">
<get uri="/hello" consumes="application/json" produces="application/json">
<to uri="direct:hello" />
</get>
</rest>
<route>
<from uri="direct:hello"/>
<to uri="restlet:https:// <--URL--> ?restletMethod=POST" />
</route>
</camelContext>
</beans>
Maby incoming request has additional headers, for example as in this issue Apache camel jetty RestletOperationException on invoking request 1001 when mocked restlet endpoint ("org.restlet.http.headers"). You can check and remove unnecessary headers from the request. Also, error may occur while the response by the same reason, check our service for set headers.

How to remove soap namespace from Envelope using Apache CXF

I am trying to access a 3rd party web service using Apache CXF 3.1. When I call the service with the wsdl2java generated code or curl the service returns an exception indicating the message is not a valid SOAP message. See the message below.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<connectivityTest xmlns="urn:cdc:iisb:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="connectivityTest">
<echoBack>Hello IIS!</echoBack>
</connectivityTest>
</soap:Body>
</soap:Envelope>
When I remove the namespace (soap:) and call the service using curl the service works. See working message below.
<?xml version="1.0" encoding="utf-8"?>
<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope">
<Body>
<connectivityTest xmlns="urn:cdc:iisb:2011" xmlns:ns2="http://www.w3.org/2003/05/soap-envelope">
<echoBack>Hello IIS V2!</echoBack>
</connectivityTest>
</Body>
How do I remove the namespace from the Envelope and Body elements of my SOAP message before it sent? Based on searching the web it looks like I may need to create an interceptor. If some one can provide an example of an interceptor to remove the namespace from the Envelope and Body elements it would be much appreciated.
Thanks in advance!
JR
No Interceptor is required for this. You can configure the namespace in your jaxws properties.
<jaxws:properties>
<entry key="soap.env.ns.map">
<map>
<entry key="" value="http://schemas.xmlsoap.org/soap/envelope/"/>
</map>
</entry>
<entry key="disable.outputstream.optimization" value="true"/>
</jaxws:properties>

Expose a Pass-Through proxy with Jboss Fuse

I am an newbie with JBoss Fuse and I would like to expose a Pass-Through proxy with Jboss Fuse.
I am using JBoss EAP 6.4 in which I have installed the JBoss Fuse 6.3.
Also I have downloaded Red Hat JBoss Developer Studio 10.4.0.GA and I have started some new Fuse Integration Projects in Spring DSL.
The main idea is to create a Fuse which will work as a front layer of a SOAP Web Service in order to use the throttling and some others features of Fuse.
Could you please advise me, if this is feasible?
Thanks you in advance!
EDIT:
I was looking something like the following:
<beans xmlns="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.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext id="_camelContext1" xmlns="http://camel.apache.org/schema/spring">
<route id="_route1">
<from id="_from1" uri="cxf:beanId:address"/>
<to id="_to1" uri="cxf:beanId:address"/>
</route>
</camelContext>
</beans>
But I need to implement the SOAP (CXF) Web Service which will be stand before the Camel route. Am I wrong?
You can try experimenting with Apache Camel.
Listen from some port and route incoming requests to the SOAP web service, here's an example:
<camelContext xmlns="http://camel.apache.org/schema/blueprint" id="PassThroughProxy" >
<route id="ProxyRoute">
<from uri="jetty:http://0.0.0.0:8080?matchOnUriPrefix=true"/>
<log message="Incoming message - headers: ${headers}" />
<log message="Incoming message - payload: ${body}" />
<to uri="bean:someProcessorHere" />
<to uri="http://soap.somewhere.net:80?bridgeEndpoint=true&throwExceptionOnFailure=false"/>
</route>
</camelContext>
Use Jetty component as input, process HTTP headers and/or body using Camel (processor, routes, ...), then use HTTP component as a client to the real web service.
You can configure SSL support, custom headers handling and so on.
If I were you, I'd use some dedicated piece of software to do this job, like Nginx.

Magento - Custom REST API giving 404

I've followed a tutorial online on how to create a custom REST API endpoint for Magento 1.9.2. However, after completing the oauth process and getting a secret and key I always get a 404 trying to call the endpoint.
I think my problem is coming from the api.xml file as I don't quite understand the values that can be used for the various options. The file is below:
<config>
<api2>
<resource_groups>
<categories translate="title" module="EG_Categories">
<title>Categories API</title>
<sort_order>10</sort_order>
</categories>
</resource_groups>
<resources>
<categories translate="title" module="EG_Categories">
<group>categories</group>
<model>categories/api2_categoriesapi</model>
<title>Category API</title>
<sort_order>10</sort_order>
<privileges>
<admin>
<create>1</create>
<retrieve>1</retrieve>
</admin>
<guest>
<retrieve>1</retrieve>
</guest>
</privileges>
<attributes>
<name>Category Name</name>
<parent>Parent ID</parent>
</attributes>
<routes>
<route>
<route>/categories/retrieve</route>
<action_type>collection</action_type>
</route>
</routes>
<versions>1</versions>
</categories>
</resources>
</api2>
</config>
In particular, I haven't been able to find out if collection is the correct value for the action type to activate the _retrieveCollection method in the class file.
I have one class file located at app/code/local/EG/Categories/Model/Api2/Categories.php.
Also in APi2 is /Categories/Rest/Admin/V1.php.
Any advice would be much appreciated.

Camel https web service consumer

I am trying to build a camel https web service consumer and I am not successful in calling this web service. This web service is currently using API-Key authentication and I have the API key. Below is my code that I have tried. Can someone give me some direction as to what I need to do to be able to do api key authentication with this remote web service?
<?xml version="1.0" encoding="UTF-8"?>
<!-- Configures the Camel Context-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-http.xsd">
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:start"/>
<setHeader headerName="CamelHttpMethod">
<constant>POST</constant>
</setHeader>
<to uri="https://api.url.com/api/v3.1/site/query/site/<apikeyhere>"/>
<log message="Message Recieved"/>
<to uri="file:target/messages/message"/>
</route>
</camelContext>
</beans>
All I needed here was the following code:
<to uri="https://api.url.com/api/v3.1/site/query/site/?apiKeyabcd1234"/>
And then I was able to get the data flowing.