I am using wso2esb 4.8.0,I am trying to connect my legacy systems which can accept rest calls with post method.
I am sending the same to them but soap envelope is adding by wso2 .
current message :
<?xml version='1.0' encoding='UTF-8'?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.comapny.org/" xmlns:env="http://com.comany.inn/Envelope"><soap:Header xmlns:p="http://webservices.usedin.com/PService">
</soap:Header><soap:Body>
<requested id="12345">
<authen login="username" password="password">
<parm name="COMPANY" value="myname"/>
</authen>
<actionReq production="doctor" id="1234" type="TINGS">
<parm name="name" value="12345"/>
</actionReq>
</requested>
</soap:Body></soap:Envelope>
Expected one:
<requested id="12345">
<authen login="username" password="password">
<parm name="COMPANY" value="myname"/>
</authen>
<actionReq production="doctor" id="1234" type="TINGS">
<parm name="name" value="12345"/>
</actionReq>
</requested>
Since this rest cal i can't use format also "format=pox" like in soap services.
my code is like this.
</xquery>
<send>
<http uri-template="http://******/webservices/***.php" method="post">
</send>
Do I need to add any property to remove soap envelope for esb out request.
Try to add this property before send mediator :
<property name="messageType" value="application/xml" scope="axis2"/>
Related
There is a legacy Rest service which has its own authentication architecture (self-owned db to store user information and using basic auth). Other rest services are all using Keycloak as IdP (with OpenID as token).
I'm trying to use WSO2 API manager before the legacy Rest API that it can authenticate calls using OpenID just as other api services. I found there's a guide saying how to pass the end user attributes to the back-end service and also how to pass a custom authorization token to the back-end service.
And now, I want to know whether it is possible to retrieve the caller's id (viz., the end user id) in a sequence or not? It means I can get the end user's id from a property, modify it and then set it to the Authorization header.
Thus, the complete process seems as:
An end user generates a JWT token from Keycloak
The end user calls an api published by API Manager with the token
API Manager retrieves the end user's userid and sets it into the Authorization header
API Manager calls the back-end service with the changed Authorization header
You can try implementing the following sequence as an in-sequence to your API. The following sequence retrieves the End User ID using the Synapse Properties and assigns it to the Authorization Header.
<?xml version="1.0" encoding="UTF-8"?><sequence xmlns="http://ws.apache.org/ns/synapse" name="username-header">
<property name="userid" expression="$ctx:api.ut.userName"/>
<!-- property name="userid" expression="$ctx:api.ut.userId"/ -->
<log level="custom">
<property name="User ID" expression="$ctx:userid" />
</log>
<property name="Authorization" expression="$ctx:userid" scope="transport" action="set" />
</sequence>
Furthermore, you can also try using the following Synapse properties, if the above doesn't fulfil your requirement.
api.ut.username
api.ut.userId
If you are trying to read the end user's ID from the Backend JWT token that is generated by the API Manager during the API invocation, then it is required to come up with an extended mediation sequence, to read and decode the Token, and then to extract the information. Given below is a sample (not complete) if the requirement is as described above
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="admin--AssertionAPI:v1.0.0--In">
<property name="assertion" expression="$trp:X-JWT-Assertion" />
<log level="custom">
<property name="Assertion" expression="$trp:X-JWT-Assertion" />
</log>
<property name="Body" expression="base64Decode(fn:substring-before(fn:substring-after($ctx:assertion, '.'), '.'))" />
<log level="custom">
<property name="body" expression="$ctx:Body" />
</log>
<!-- use script mediator to access required properties -->
<!-- and set the value as a header -->
</sequence>
I'm pretty new on WSO2 IE and I'm trying to use a SOAP request to call a REST API.
This first part is OK but one of my API's needs to receive an attribute into its PATH or QUERY parameters. The attribute is sent by the soap call in it's body.
The question is, how can i get this body attribute and pass it in the PATH/QUERY param of the URL dynamically before i send it?
Picture of my architecture
Your requirement is to construct a dynamic URL. This can be easily done with the ESB Server. Here we have different options to construct this dynamic URL. Following is a sample proxy service that was created to achieve this.
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="sample_proxy"
startOnLoad="true"
statistics="disable"
trace="disable"
transports="http,https">
<target>
<inSequence>
<log level="custom">
<property expression="$body//target" name="Target endpoint"/>
</log>
<property name="uri.var.host" value="http://localhost:8280"/>
<property name="uri.var.context" value="services"/>
<property expression="$body//target" name="uri.var.resourcepath"/>
<call>
<endpoint>
<http method="GET"
uri-template="{uri.var.host}/{uri.var.context}/{uri.var.resourcepath}"/>
</endpoint>
</call>
<respond/>
</inSequence>
</target>
<description/>
</proxy>
We are sending the following request to this proxy service.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<target>sample_path</target>
</soapenv:Body>
</soapenv:Envelope>
In the above proxy service what we have done is construct the dynamic URL with the parameters from the soap message please refer to the blog post [1] to further clarify regarding dynamic URLs.
Here in order to extract the parameters from the body, we have used XPaths. Please refer to the documentation [2] to further clarify regarding XPaths. We have extracted the value inside the target element and added it to the end of the URL. Thus this will invoke the http://localhost:8280/services/sample_path from the ESB server.
If you are interested in constructing the URL with query parameters you can do that by concatenating the required URL and using an address endpoint [1].
[1]-https://dzone.com/articles/constructing-dynamic-endpoint-urls-in-wso2-esb
[2]-https://docs.wso2.com/display/EI6xx/Accessing+Properties+with+XPath#AccessingPropertieswithXPath-$ctx
I have a special requirement.
I want to access WSO2 backen API.
So,I want to publish it on WSO2.
So that,my service can access WSO2'API.
Can someone tell me how to do it?
WSO2 API Manager exposes a REST API to for operations like publish and subscribe. You can see the list of all the services here: https://docs.wso2.com/display/AM200/Published+APIs.
It also offers Swagger definition files for those same APIs: https://raw.githubusercontent.com/wso2/carbon-apimgt/v6.0.4/components/apimgt/org.wso2.carbon.apimgt.rest.api.publisher/src/main/resources/publisher-api.yaml.
I haven't tried it, but given the fact that all you need to publish a managed API in WSO2 is a Swagger file and an existing endpoint, there is nothing preventing you to create an API for WSO2 APIM inside itself.
Theoretically, this should be fine.
WSO2 API manger plays the middleware role for its own APIs just as for any other third party API.
Let's say that you want to publish any of the Admin APIs of the api manager through the api manager itself. You just need to add endpoint information just as you would do for any other api.
Then, once a user wants to access the api, they have to first get a access token by calling the token endpoint, then use that token to execute the published api.
Access you API-Manager on: http://localhost:9443/publisher
Click on your api
Click on tab "Lifecycle"
Click on "Publish"
WS02 API means are you referring to Wso2 API manager?
Because you can also implement API's using Wso2 ESB.
You can have more control over the code of API using Wso2 ESB but you cannot have throttling and other control using ESB you have to use APIM.
You shoould have an endpoint to connect your API.
Then follow the below steps
Login in your API Manager (Publisher) Instance.
+ Add new API
If you have an endpoint: Click on Design a new Rest API
Fill the values like name, context, version and description.
Add a new API Specification. (i.e: GET /test)
Click on Next:Implement
Select Managed API
Endpoint Type: HTTP/REST Endpoint
Endpoint: Fill your endpoint's url without context.
Click on Next: Manage
Fill values like type of subscription.
If you have a public API, don't forget change the second column of your API specification resources. Change the value for: None
Click on Save & Publish
Go to WSO2 Store and check
While going through the answers and the replies that you have provided, I believe you know how to publish an API with a WSO2 API as an endpoint. However, your concern is how to handle the authorization since the backend itself needs a valid OAuth token to be invoked? Please correct me if my understanding is wrong.
If that is the case, I believe you can simply achieve it with a help of a custom mediation. The below sample mediation is to invoke the token endpoint and generate a token. Once the token is generated you can simply add that to the request header.
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="simple-token-gen" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<property description="access_token" expression="get-property('registry', 'local:/api-backend-credentials/pizzaOrderingAPI/access_Token')" name="access_token" scope="default" type="STRING"/>
<property description="generated_time" expression="get-property('registry','local:/api-backend-credentials/pizzaOrderingAPI/generated_Time')" name="generated-time" scope="default" type="LONG"/>
<property description="client_credentials" name="app-client-auth" scope="default" type="STRING" value="{base64encoded(clientKey:clientSecret)}"/>
<property expression="json-eval($)" name="message-body" scope="default" type="STRING"/>
<property expression="get-property('axis2','REST_URL_POSTFIX')" name="resource" scope="default" type="STRING"/>
<filter description="" xpath="get-property('SYSTEM_TIME') - get-property('generated-time') > 3600000 or get-property('access_token') = ''">
<then>
<payloadFactory media-type="xml">
<format>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<root xmlns="">
<grant_type>client_credentials</grant_type>
</root>
</soapenv:Body>
</soapenv:Envelope>
</format>
<args/>
</payloadFactory>
<header expression="fn:concat('Basic ', get-property('app-client-auth'))" name="Authorization" scope="transport"/>
<header name="Content-Type" scope="transport" value="application/x-www-form-urlencoded"/>
<property description="messageType" name="messageType" scope="axis2" type="STRING" value="application/x-www-form-urlencoded"/>
<property description="REST_URL_POSTFIx" name="REST_URL_POSTFIX" scope="axis2" type="STRING" value=""/>
<call blocking="true">
<endpoint name="token">
<http method="post" uri-template="{token-endpoint-url}"/>
</endpoint>
</call>
<property expression="get-property('resource')" name="REST_URL_POSTFIX" scope="axis2" type="STRING"/>
<property description="generated Time Setter" expression="get-property('SYSTEM_TIME')" name="local:/api-backend-credentials/pizzaOrderingAPI/generated_Time" scope="registry" type="LONG"/>
<property description="generated_token" expression="json-eval($.access_token)" name="generated-access-token" scope="default" type="STRING"/>
<property description="new Token setter" expression="get-property('generated-access-token')" name="local:/api-backend-credentials/pizzaOrderingAPI/access_Token" scope="registry" type="STRING"/>
<header expression="fn:concat('Bearer ', get-property('generated-access-token'))" name="Authorization" scope="transport"/>
<payloadFactory media-type="json">
<format>
$1
</format>
<args>
<arg evaluator="xml" expression="get-property('message-body')"/>
</args>
</payloadFactory>
</then>
<else>
<header expression="fn:concat('Bearer ', get-property('access_token'))" name="Authorization" scope="transport"/>
</else>
</filter>
</sequence>
Replace the placeholders with corresponding values.
{base64encoded(clientKey:clientSecret)} - The client key and client
secret, separated by a colon and base64 encoded. {token-endpoint-url}
The token endpoint URL of the backend authorization server.
I believe this helps you with your concern.
If I understood correctly, It has no sense to publish WSO2 AM APIs in the API Manager. First reason is that WSO2 AM APIs are accesed by Basic Auth, that it is not implemented by default in WSO2 AM. The default security for APIs en WSO2 is OAuth2, so you would have to do a extension for that. You may check here: https://docs.wso2.com/display/AM260/apidocs/publisher/#guide
Also, these internal APIs for WSO2 AM are meant to be accesed by an admin or so, so it has no sense to expose these as an API to be consumed for other suscriptors.
Anyway, if you implemented an authenticator to run with Basic Auth, you may expose this APIs in API Manager, or expose these APIs disabling default OAuth2 security.
BR
We´re getting this error:
The endpoint reference (EPR) for the Operation not found is [OUR ENDPOINT] and the WSA Action = . If this EPR was previously reachable, please contact the server administrator.
Our SOAPActions are declared as "", as allowed by specification.
The following answer explains why it´s happening: https://stackoverflow.com/a/15556669/1553243. However, we can´t afford the suggested workarounds, 1 and 3. We can´t have our vendors declare their SOAPActions, and we can´t have our clients always append the operation name. Workaround 2 doesn´t work when SOAPAction = "", either.
The answer also states they were in a process of fixing this limitation, but I´m using a one year later release and nothing.
Is there any other workaround?
Our proxy is defined like:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="TEST"
transports="https,http"
statistics="enable"
trace="enable"
startOnLoad="true">
<target>
<inSequence>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence>
<log/>
</faultSequence>
<endpoint>
<wsdl service="TESTService"
port="TESTServicePort"
uri="http://localhost:8080/test?wsdl"/>
</endpoint>
</target>
<publishWSDL uri="http://localhost:8080/test?wsdl"/>
<description/>
</proxy>
Since ESB v4.8, using pass-through http transport, you can add this parameter to your proxy def :
<parameter name="disableOperationValidation" locked="false">true</parameter>
In your webservice implementation class add the annotation #WebMethod to define the SOAP Action for individual operations. for example
#WebService
#SOAPBinding(style=Style.RPC)
public class BookingServiceWS {
#WebMethod(action="getBooking",operationName="getBooking")
public BookingServiceResponse getBooking(String pnr){
}
This will generate the WSDL with SOAP Action defined as
<operation name="getBooking">
<soap:operation soapAction="getBooking"/>
<input>...</input>
<output>...</output>
</operation>
This should be able to resolve the issue
Then you have control at ESB level? If so, you define the SOAPAction property at ESB level.
That is, when request hits the sequence, if you are sure where to route the request, at that time set SOAPAction property before the send mediator
<property name="SOAPAction" value="urn:OPERATION NAME"
scope="transport"/>
Workaround 2: You can specify the SOAPAction in the client side code. Specify it in the options as shown below.
options.setAction("urn:SOAPAction");
Can some one point me to a working example of xsl transformation using the proxy services xslt mediator option.
Basically, my requirement is, i will have a request where i will get some data which determines the routing and after that from other elements of requested data i have to re frame soap request to trigger another bpel service.
Please let me know the better approach to this.
You can very well use XSLT transformation in your sequence, using XSLT Mediator.
In your sequence file you can specify the XSLT file to tranform the request. Sample sequence code snippet:
<sequence xmlns="http://ws.apache.org/ns/synapse" name="SampleInterceptorSequence">
<in>
<log level="full" category="DEBUG">
<property name="sequence" value="inSequence-Request Before XSLT" />
</log>
<xslt key="RequestTranformerXSLT" />
<log level="full" category="DEBUG">
<property name="sequence" value="inSequence-Request After XSLT" />
</log>
<send>
<endpoint key="MyActualServiceEPR" />
</send>
</in>
Your xslt would contain the style for the actual request to be formed for hitting the end point reference.
Further if you can check this nice article of web service chaining to get a real time idea of xslt mediation.
Web Service Chaining from WSO2 ESB Developers
Hope this helps.
Thanks.
Find the sample below..
http://wso2.org/project/esb/java/4.0.0/docs/samples/message_mediation_samples.html#Sample8