Programmatically add custom handler in WSO2 API Manager - wso2

I create and subscribe new APIs through an automated process that uses WSO2 API Manager's Publisher and Store HTTP APIs respectively. I have custom handlers that I then map to my APIs by editing the XML files in <APIM_HOME>/repository/deployment/server/synapse-configs/default/api.
Is there a way to programmatically map the handlers to the newly created APIs so that I don't have to edit the XML manually? In other words, an API or other method to see the current handlers for an API, and add/remove?

I assume you do not want to edit API XML manually for all the APIs to engage a custom handler. Instead, you want to be able to engage a handler to all the APIs automatically when you publish the APIs. You can do it by editing the $APIM_HOME/repository/resources/api_templates/velocity_template.xml. This is the template file which decides which handlers to be engaged with APIs by default. In this file, at the end, you will find a handlers section. You need to edit this file and add your handler there, as shown below.
## print the handlers
#if($handlers.size() > 0)
<handlers xmlns="http://ws.apache.org/ns/synapse">
<handler class="org.wso2.carbon.samples.handlers.MyCustomHandler"/>
#foreach($handler in $handlers)
<handler xmlns="http://ws.apache.org/ns/synapse" class="$handler.className">
#if($handler.hasProperties())
#set ($map = $handler.getProperties() )
#foreach($property in $map.entrySet())
<property name="$!property.key" value="$!property.value"/>
#end
#end
</handler>
#end
</handlers>
#end
As you can see, I have added my handler org.wso2.carbon.samples.handlers.MyCustomHandler. That's it you should do. If you create and publish an API now, MyCustomHandler will be engaged with your API automatically. However, already published APIs won't have an effect even if you update velocity_templates.xml. You need to republish them in order to get the effect.

In my case, I have many handlers and many APIs. Not all handlers apply to all APIs and no handler is applicable to all APIs.
I solved this by creating a standalone HTTP API in a WAR file that I deployed to API Manager's Carbon instance. The same service that calls the WSO2 Publisher API calls my HTTP API afterward. The API takes in handler class names as parameters, and injects the appropriate elements into the API definition XML files on the local filesystem (I used JDOM). API Manager automatically detects and reloads the modified XML and it's good to go.

Related

Can I add a basic auth in only 1 resource in a API?

I am using wso2ei6.6.0 and I am trying to secure only one resource in my API file.
Can I secure only 1 resource without creating another API file?
<handlers>
<handler class="org.wso2.rest.BasicAuthHandler"/>
</handlers>
This option only work securing all the resources in an API file.
Thank you
You can improve the BasicAuthHandler implementation to perform the validation check only for that particular resource by introducing a filter. Or, you can convert the same logic which is in the handler to a class mediator and engage it to the respective API resource's in-sequence section.
With either of the mentioned approach, you will be able to achieve your requirement.

WSO2 api manager mediation

I'm using apim 2 and I need to route client call to the back end service dynamically at runtime.
I have added a custom sequence in the folder WSOAM_HOME\repository\resources\customsequences\in
<sequence xmlns="http://ws.apache.org/ns/synapse" name="mySeq">
<class name="org.wso2.carbon.env.EnvironmentResolver"/>
</sequence>
I have added the jar containing my implementation under repository/component/lib.
I have configured my API to use this custom sequence throught the publisher portal,but The problem is that the EnvironmentResolver is not being called!!
Did i miss any thing?

WSO2 API Manager - Replace URLs in response body

I'm trying to setup a proxy for my RESTful API using WSO2 API Manager. My problem is that the responses from the backend API are left untouched so all the urls that connect to other endpoints still reference the backend server rather than the proxy. I need a way to replace those url values in the response body to point to the proxied api. I understand this can be accomplished via Mediation Extensions, using ESB Mediators.
I'm not familiar enough with them to pick the one better suited for the job. URLRewrite mediator looks pretty straightforward, but it doesn't seem to apply to the message body but the headers. Payload Factory seems to require a fixed structure for the message, which is not very convenient for me, since I need it to work on the different responses that my API provides (and I wouldn't want to maintain those structures in the mediator definition).
I've managed to solve it by setting the headers my application checks to build its urls:X-Forwarded-Host and X-Forwarded-Proto.
So I've created a Header Mediator that looks like:
<sequence xmlns="http://ws.apache.org/ns/synapse" name="WSO2AM--Ext--In">
<header name="X-Forwarded-Host" expression="get-property('transport','Host')" scope="transport"/>
<header name="X-Forwarded-Proto" value="https" scope="transport"/>
</sequence>
And that did the trick.

URI templates in WSO2 API Publisher

Is it possible to register endpoints with URI templates in the API Publisher that ships with WSO2 API Manager version 1.4.0? For example, I would like to register an endpoint such as:
/jobs/{jobid}/pems
After saving an API, I can see this bit in the API config file:
<resource methods="GET" url-mapping="/jobs/{jobid}/pems">
I have tried manually changing the XML file from url-mapping to uri-template, i.e., to:
<resource methods="GET" uri-template="/jobs/{jobid}/pems">
but I still get "No matching resource found in the API for the given request". In any case, this is not a good work around since we need developers to be able to register these endpoints from the publisher application. Whenever changes are saved to an API from within the API Publisher interface, 'uri-template' gets reverted back to 'url-mapping'.
Thanks in advance.
This is due to APIPublisher app only supports URL-Mappings when defining API resources.
If you want to define a uri-template ,instead of a url-mapping,you can achieve this from changing the api xml manually.
But before that make sure,when creating the API,you have define the API with a valid url-mapping.So in your trying API,first please edit the API from APIPublisher as keeping a valid url-mapping pattern for API resources and then change its xml to match with your mentioned uri-template pattern.
Thanks;
we don't currently support uri-template patterns. We support only url-mappings.
Even , if you edit the backend API configuration (that is, api configuration file ) to url-mappings, it wont work, because we validate request before the request get hits the mediation engine.
You can use ESB RESTApi as your backend service endpoint.That is, define the RESTAPI in wso2esb, with uri-templates(it is supported out of the in ESB) and point that API as the service endpoint from wso2APIManager with url-mappings pattern.
I would like to add some more points.As I mentioned earlier,WSO2 APIManager supports uri-templates.Only api-publisher app UI is not allowing to add uri-templates.
When creating the API from the Publisher UI, you have to give the resource mapping as /* or valid url-mapping. Then when the synapse api is created, you have to change that xml file to uri-template and then change the /* to the uri-template pattern.
Hope above will help you to resolve your issue.
Thanks;

Getting WSO2 ESB endpoint meta data programmatically

I am trying to programmatically retrieve the meta data of the end points configured to WSO2 ESB (Eg: ServiceName, WebMethods, Input/Output Parameters with Return types etc). Can someone direct me to some way/docs which could help me fetch this data.
Unfortunately it's not really clear what you want to do. Here some examples how to access properties (Meta-Data?)
inside a proxy/sequence access properties:
<property name="some name" expression="get-property('registry','conf:resource/path')"/>
<property name="some name" expression="get-property('registry',gov:resource/path')"/>
<property name="some name" expression="get-property('registry','resourceName')"/>
Or inside a Custom Mediator:
String property = (String)messageContext.getProperty("nameOfThePropery");
Or inside a Custom Mediator (getting the filename from the Transport Layer):
org.apache.axis2.context.MessageContext axis2messageContext = ((Axis2MessageContext) messageContext).getAxis2MessageContext();
// print the filename of the current transport
myLog.info("FileName: " + axis2messageContext.getTransportIn().getName());
Hope this helps you a little bit further, otherwise improve you question.
To further improve on Abdul's question, we are developing a web-service gateway between a legacy client on side and on the other side are external web-services. We have created a template/sequences in WSo2 where we trap the legacy client request and redirect it to the correct web-service based on a internal protocol.
The external web services are registered in WSo2 as endpoints. So far we have been configuring these endpoints manually using the admin console. We are looking at automating this step so that our gateway will hit WSo2 and provide the WSDL URL. A class mediator would then invoke the WSo2 / Synapse APIs to save this endpoint in the Synapse configuration. We have not been successful in this.
We have also read the docs which say that changing synapse config thru mediator is not recommended, hence would like to see if there are other options that would do this job for us.
One workaround would be to create those endpoints from the client side itself. This can be done by calling the AdminService APIs exposed by the carbon framework. In carbon, a front end of any carbon component talks to its back end through Admin Services. For example, if we take endpoints related functionalities, when you use the management console to create/delete or to do any functionalities, it would in turn call the respective back end via the "EndPointAdmin" admin service. Therefore I believe, if you want to programmatically create those endpoints, you can call the EndPointAdmin backend admin service (via EndPointAdminStub - it is the client stub corresponding to the aforesaid back end service) directly from your client side and get your requirement fulfilled.
Regards,
Prabath