Scenario:
I'm using the WSO2 EI 6.4.0. ESB to convert an incoming SOAP message to JSON and sending it out to our internal applications REST service.
Currently I'm using an inbound endpoint to handle the SOAP request (although I've tried Proxy service which gives me the same result). The incoming message is successfully received, the conversion seems fine as well, but the call to the internal rest is failing. For some reason, the ESB handles all the requests to this rest interface as follows:
/http:/InternalApp:8000/rest/xml_messages/iend_incoming
Notice that the actual URL that I provide in the SEND mediator is as follows:
http://InternalApp:8000/rest/xml_messages/
The last piece of the incorrect url (i.e. iend_incoming) is actually the name of the inbound endpoint on the ESB itself. I'm pretty confused as to how this ended up but it looks as though the ESB is considering this to be some sort of proxy call.
The following code is used on the ESB in the sequence tied to aforementioned inbound endpoint:
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="seq_send_soap_to_rest" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<property name="HTTP_METHOD" scope="axis2" type="STRING" value="POST"/>
<property name="FORCE_HTTP_1.0" scope="axis2" type="STRING" value="true"/>
<payloadFactory media-type="json">
<format>
{
"xml_content": "$1",
"sender": "$2",
"receiver": "$3"
}
</format>
<args>
<arg evaluator="xml" expression="base64Encode($env)"/>
<arg evaluator="xml" expression="$body//cac:ConsigneeParty/cac:PartyIdentification/cbc:ID" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"/>
<arg evaluator="xml" expression="$body//cac:ConsignorParty/cac:PartyIdentification/cbc:ID" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"/>
</args>
</payloadFactory>
<property expression="fn:concat('Basic ', base64Encode('USRNAME:PWD'))" name="Proxy-Authorization" scope="transport" type="STRING"/>
<property name="POST_TO_URI" scope="axis2" type="STRING" value="true"/>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<send>
<endpoint>
<address format="rest" uri="http://InternalApp:8000/rest/xml_messages/"/>
</endpoint>
</send>
</sequence>
Does anyone have any clue as to how that malformed URL ended up there and how I can fix it?
Apparently, it was this line:
<property name="POST_TO_URI" scope="axis2" type="STRING" value="true"/>
Setting it to false gave me a bad request but at least I knew where to look. The name of the variable might be a bit misleading.
Related
I have 2 api to request:
API get token
API request to work something (use OAuth2)
Below is code to call get token:
<?xml version="1.0" encoding="UTF-8"?>
<api context="/default" name="PostToken" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET">
<inSequence>
<payloadFactory description="Setting payload for GetAccessToken API" media-type="xml">
<format>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<root xmlns="">
<grant_type>$1</grant_type>
</root>
</soapenv:Body>
</soapenv:Envelope>
</format>
<args>
<arg value="client_credentials"/>
</args>
</payloadFactory>
<!-- Below configurations are required to send data as application/x-www-form-urlencoded -->
<header name="Content-Type" scope="transport" value="application/x-www-form-urlencoded"/>
<property name="messageType" scope="axis2" type="STRING" value="application/x-www-form-urlencoded"/>
<header name="Authorization" scope="transport" value="Basic xxxxxxxx"/>
<property name="POST_TO_URI" scope="axis2" type="STRING" value="true"/>
<call>
<endpoint>
<http method="post" uri-template="https://sample.com/token">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>-1</progressionFactor>
<maximumDuration>0</maximumDuration>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
How next step I can get token from response to apply the 2nd API with Bearer token?
Many thanks!
You can refer to the following blog regarding the Using OAuth2 Protected Back-ends With API Manager., This blog is regarding handling that in the WSO2 API Manager. But this is applicable in the EI as well.
[1] https://medium.com/#menakajayawardena/wso2-how-to-using-oauth2-protected-back-ends-with-api-manager-5d7e234c61c
I am using WSO2 APIM 3.0.0 version & I have published an API in WSO2 using an existing swagger definition.
I am using a hybrid gateway environment, with the "Production" & "Sandbox" URLs configured to different code environments (for testing purposes the "Production" URL hits our qa box and "Sandbox" hits my local environment). I have just noticed that WSO2 is always routing calls to the sandbox environment (my local) even when I use the "Production" access token.
Is there something else I need to do apart from simply generating different access tokens for prod & sandbox from the devportal for it to route to the desired environment?
And does this mean that I MUST always have different gateways for different environments?
I tested this using OAUTH & JWT token types, with different grant mechanisms, and it still does the same thing.
synapse-config attached as requested:
<?xml version="1.0" encoding="UTF-8"?><api xmlns="http://ws.apache.org/ns/synapse" name="admin--XXXBackendPlatform" context="/WSO2/1.0.0" version="1.0.0" version-type="context">
<resource methods="POST" url-mapping="xxxxx" faultSequence="fault">
<inSequence>
<property name="api.ut.backendRequestTime" expression="get-property('SYSTEM_TIME')"/>
<filter source="$ctx:AM_KEY_TYPE" regex="SANDBOX">
<then>
<send>
<endpoint key="XXXBackendPlatform--v1.0.0_APIsandboxEndpoint"/>
</send>
</then>
<else>
<sequence key="_production_key_error_"/>
</else>
</filter>
</inSequence>
<outSequence>
<class name="org.wso2.carbon.apimgt.gateway.handlers.analytics.APIMgtResponseHandler"/>
<send/>
</outSequence>
</resource>
<handlers>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.common.APIMgtLatencyStatsHandler">
<property name="apiUUID" value="6535a4b7-759b-4f0e-8980-eab80aaee847"/>
</handler>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler">
<property name="apiImplementationType" value="ENDPOINT"/>
<property name="AuthorizationHeader" value="WSO2_Auth"/>
</handler>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler">
<property name="RemoveOAuthHeadersFromOutMessage" value="true"/>
<property name="APILevelPolicy" value="Unlimited"/>
<property name="AuthorizationHeader" value="WSO2_Auth"/>
<property name="CertificateInformation" value="{}"/>
<property name="APISecurity" value="oauth2,oauth_basic_auth_api_key_mandatory"/>
<property name="apiUUID" value="6535a4b7-759b-4f0e-8980-eab80aaee847"/>
</handler>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.throttling.ThrottleHandler"/>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.analytics.APIMgtUsageHandler"/>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.analytics.APIMgtGoogleAnalyticsTrackingHandler">
<property name="configKey" value="gov:/apimgt/statistics/ga-config.xml"/>
</handler>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerExtensionHandler"/>
</handlers>
</api>
As per the below part, you have only configured a sandbox endpoint in your API. You should get an error if you use production keys to access the API.
<filter source="$ctx:AM_KEY_TYPE" regex="SANDBOX">
<then>
<send>
<endpoint key="XXXBackendPlatform--v1.0.0_APIsandboxEndpoint"/>
</send>
</then>
<else>
<sequence key="_production_key_error_"/>
</else>
</filter>
I've created an RESTful API in wso2-am 2.0.0. But I'm face a problem and a would some help.
I have a resource wiht GET http method which receive an url param and I made a SOAP payload to send via POST to backend (backend is soap11).
For this, I used a custom 'in' sequence:
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="JSONtoSOAP" trace="disable"
xmlns="http://ws.apache.org/ns/synapse">
<log description="Entrada" level="full" separator=",">
<property expression="get-property('uri.var.cpfCnpj')" name="cpfcnpj" />
<property name="trace"
value="IN LOG" />
</log>
<property name="HTTP_METHOD" value="POST" scope="axis2" type="STRING" />
<property name="messageType" scope="axis2" type="STRING"
value="application/soap+xml" />
<enrich>
<source type="inline">
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body />
</soap:Envelope>
</source>
<target action="replace" type="envelope" />
</enrich>
<payloadFactory media-type="xml">
<format>
<man:QueryCustomerDetailsRequestMessage
xmlns:man="http://www.algartelecom.com.br/SOA/Service/ManageCustomerInformationPortalClientesReqCS">
<man:documentNumber>$1</man:documentNumber>
<man:tagetCRM />
</man:QueryCustomerDetailsRequestMessage>
</format>
<args>
<arg evaluator="xml" expression="get-property('uri.var.cpfCnpj')" />
</args>
</payloadFactory>
<property name="REST_URL_POSTFIX" value="" scope="axis2" />
<header name="Action" scope="default" value="queryCustomerDetails" />
<log description="Saida" level="full" separator=",">
<property name="trace" value="DEBUG LOG" />
</log>
</sequence>
Until here, without problem.
But when I try to call the resource from any restClient (SOAPui for example or wso2-am store) result in Runtime exception, like this:
<?xml version='1.0' encoding='UTF-8'?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<am:fault xmlns:am="http://wso2.org/apimanager">
<am:code/>
<am:type>Status report</am:type>
<am:message>Runtime Error</am:message>
<am:description/>
</am:fault>
</soap:Body>
</soap:Envelope>
Note that code and description tags are empty, and when I checked the server's log I found:
[2016-09-30 16:53:44,603] INFO - LogMediator STATUS = Executing default 'fault' sequence, ERROR_CODE = null, ERROR_MESSAGE = null
This is the correct way to produces a restful API and call a SOAP backend?
Anybody knows about this issue? (I believe, this feature works on WSO2 ESB).
You can try the following:
In the publisher, set your endpoint type to HTTP/SOAP endpoint
In your sequence don't set the REST_URL_POSTFIX to "", but remove the property completely
I have a wsdl consisting of several operations.
I have created a proxy service using that wsdl and want to expose the operations in present in the wsdl.
Can we define operation specific flow in the proxy services?
To be more precise, In Oracle Service Bus, it has the concept of branching, can we implement the same in WSO2 esb proxy?
You can use filter or switch mediator to apply a mediation depending on the operation : look at the first node in the SOAP Body or at the SOAP Action if initialized.
Samples based on the message content (assuming this is a SOAP 11 message) :
<switch xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" source="local-name(soap:Body/*[1])">
<case regex="operation1">
<log level="custom">
<property name="operation" value="operation1"/>
</log>
</case>
<case regex="operation2">
<log level="custom">
<property name="operation" value="operation2"/>
</log>
</case>
<default/>
</switch>
<filter xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" source="local-name(soap:Body/*[1])" regex="postCustomer">
<then>
<log level="custom">
<property name="operation" value="operation1"/>
</log>
</then>
<else>
<log level="custom">
<property name="operation" value="not operation1"/>
</log>
</else>
</filter>
I want to download an XML file from a Web site using WSO2 ESB. Assume that the URL is static for the sake of simplicity.
I have tried VFS both as a proxy service and an individual sequence without success, and couldn't find any relevant material on the Internet.
Here is the sequence XML:
<sequence xmlns="http://ws.apache.org/ns/synapse" name="download">
<in>
<log level="headers">
<property name="?" value="[download] in: started"/>
</log>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<property name="transport.vfs.ContentType" value="text/xml" scope="transport" type="STRING"/>
<property name="transport.vfs.FileURI" value="http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-2013.xml" scope="transport" type="STRING"/>
<log level="headers">
<property name="?" value="[download] in: sending over vfs"/>
</log>
<send>
<endpoint>
<address uri="http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-2013.xml"/>
</endpoint>
</send>
<log level="headers">
<property name="?" value="[download] in: ended"/>
</log>
</in>
<out>
<log level="headers">
<property name="?" value="[download] out: started"/>
</log>
<send/>
<log level="headers">
<property name="?" value="[download] out: ended"/>
</log>
</out>
</sequence>
So, how to download a large file over HTTP with WSO2 ESB?
I have a similar problem, and by the moment I've solved it with an API and this code:
<api xmlns="http://ws.apache.org/ns/synapse" name="EcoRest" context="/services/ecorest">
<resource methods="GET" uri-template="/{idFile}">
<inSequence>
<send>
<endpoint>
<http method="get" uri-template="http://slx00012001:8888/repositoryfiles/{uri.var.idFile}">
<suspendOnFailure>
<errorCodes>101500,101510,101001,101000</errorCodes>
<initialDuration>10</initialDuration>
<progressionFactor>1.0</progressionFactor>
<maximumDuration>10</maximumDuration>
</suspendOnFailure>
</http>
</endpoint>
</send>
<property name="enableSwA" value="true" scope="axis2"></property>
</inSequence>
<faultSequence>
<log level="custom">
<property name="FAULT GETTING FILE" expression="get-property('uri.var.idFile')"></property>
</log>
<payloadFactory media-type="json">
<format> {"descError":"$1", "error": "true"} </format>
<args>
<arg evaluator="json" expression="$.descError"></arg>
</args>
</payloadFactory>
<property name="HTTP_SC" value="500" scope="axis2" type="STRING"></property>
<respond></respond>
</faultSequence>
</resource>
</api>
This API works perfectly and make a throught-pass with the files. But if I send an id_file doesn't exist, the backend service return an http 400 with a json-message, the process go into the faultsequence, but the payloadFactory in the faultsequence doesn't work, and I don't know why :(
Have a go with this configuration:
<proxy xmlns="http://ws.apache.org/ns/synapse" name="download" transports="https,http,vfs" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<property name="ClientApiNonBlocking" value="true" scope="axis2" action="remove"/>
<send>
<endpoint>
<address uri="vfs:file://home/secondary/file.xml"/>
</endpoint>
</send>
</inSequence>
</target>
<parameter name="transport.vfs.Streaming">true</parameter>
<parameter name="transport.vfs.FileURI">http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-2013.xml</parameter>
<parameter name="transport.vfs.Locking">disable</parameter>
<description></description>
</proxy>
You can initiate the download using:
curl -v http://localhost:8280/services/download
You can find out more about the VFS Transport specific parameters here: http://docs.wso2.org/wiki/display/ESB460/VFS+Transport. You can also find another VFS example here: http://docs.wso2.org/wiki/pages/viewpage.action?pageId=16846489. Hope this helps.