Customize WSO2 gateway error messages - wso2

The WSO2 Gateway returns this format of error message:
{"fault":{"code":404,"type":"Status report","message":"Not Found",
"description":"The requested resource (/account-info/1.0/) is not available."}}
But we have a standard format for all error messages that our microservices (which implement the APIs served by WSO2) return. We return a simple JSON object with two fields, error & error_description. So that we can present a consistent interface to our users, in this particular case we would like to see the WSO2 Gateway return exactly this:
{"error":"SERVICE_UNAVAILABLE","error_description":
"The requested resource (/account-info/1.0/) is not available."}
and return the HTTP status code only in the header.
Can you please tell me what I need to do to achieve this. Thank you.

These error messages are generated from default sequences shipped with WSO2 API Manager.
If the requested resource is not found in API Manager, it will execute the main sequence ($AM_HOME/repository/deployment/server/synapse-configs/default/sequences/main.xml). If you open this file, you will see that the above default error message is generated using a payload factory mediator as shown below.
<payloadFactory>
<format>
<am:fault xmlns:am="http://wso2.org/apimanager">
<am:code>404</am:code>
<am:type>Status report</am:type>
<am:message>Not Found</am:message>
<am:description>The requested resource (/$1) is not available.</am:description>
</am:fault>
</format>
<args>
<arg expression="$axis2:REST_URL_POSTFIX" />
</args>
</payloadFactory>
So if you want to customize the error message, then you need to modify the above payload factory mediator according to your need.
Likewise, if there is any faults occur, the fault sequence ($AM_HOME/repository/deployment/server/synapse-configs/default/sequences/fault.xml) will be executed. You might want to change the message format there as well.

Related

Get users IP address that triggers a call from WSO2 API Manager

Is possible to get the users IP that triggered the API call on WSO2 API Manager and pass it on to the call?
Any help how to do this please
You can add following property before calling endpoint (before send mediator) to your api to get the ip of user
<property name="client_ip_address"
expression="get-property('axis2','REMOTE_ADDR')"
scope="transport"
type="STRING"/>
Since the scope is set to transport the client_ip_address is set as a header of outgoing message. You will be able to see something similar to below log when the wire is enabled.
[2016-01-21 15:44:10,187] DEBUG - wire << "client_ip_address: 172.22.99.122[\r][\n]"
Hope this will help you.

Wso2 API Manager ERROR_CODE = 101508, Error in Sender

I publised one test API on WSO2 API Manager as prototype API. But When I am trying to curl the API endpoint I am getting bellow error
curl http://localhost:8280/weather2/v1.0.0
<am:fault xmlns:am="http://wso2.org/apimanager">
<am:code>101508</am:code>
<am:type>Status report</am:type>
<am:message>Runtime Error</am:message>
<am:description>Error in Sender</am:description>
</am:fault>
I am getting the same error for Managed API as well.
There is existing issue which cause this behavior[]. However you can create a custom sequence as below and add it as a insequencefor the API in manage API phase. The issue was, without below sequence the host header going to endpoint asHost: api.mydubaitrip.com:80 which is not supported by that endpoint.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="remove_port_In">
<property name="REQUEST_HOST_HEADER" value="api.mydubaitrip.com" scope="axis2"/>
</sequence>
[1] https://wso2.org/jira/browse/APIMANAGER-4429

How to use WSO2 ESB to mediate fixed length text data

I have the needs to use WSO2 ESB to mediate the incoming fixed length text data as received via MQ, one line of text per message, into XML format and then send the transformed data onto an SOAP endpoint via HTTP.
I understand that I could use WSO2 ESB admin console to configure an InSequence to do the data parsing and mapping with substring function and then set up a proxy service to include this configured sequenece.
I would need helps about how to do all these in details in steps. Greatly appreciate if someone could provide some examples or links to some webpages about how-to.
Thanks!
You should have a look to smooks, I think this is the best solution :
CSV : http://wso2.com/library/blog-post/2013/09/csv-to-xml-transformation-with-wso2-esb-smooks-mediator/
Fixed Lengh text : http://vvratha.blogspot.fr/2014/05/processing-large-text-file-using-smooks.html
An other solution would be to write your own messageBuilder, search "org.apache.axis2.format.PlainTextBuilder" to find the source code...
I agree with Jean-Michel, that smooks would be a good solution. But, this is also possible to do within a single simple proxy service. Set up a simple pass-through proxy to your endpoint. Then, open it up in source view (or the wizard) and configure the insequence to add a PayloadMediator.
Here is an example of how to use Payload Mediator [1]
Here is an excerpted example of what that would look like with a few xpath expressions to extract fixed-length fields from your input:
<payloadFactory media-type="xml">
<format>
<m:body xmlns:m="http://services.samples">
<m:field1>$1</m:field1>
<m:field2>$2</m:field2>
</m:body>
</format>
<args>
<arg expression="substring(//*,0,10)"/>
<arg expression="substring(//*,10,10)"/>
</args>
</payloadFactory>
You may also need to use the content type property in your sequence, because you're changing the content type to xml:
<property name="ContentType" value="text/xml" scope="axis2"/>
Best of luck!
[1] https://docs.wso2.com/pages/viewpage.action?pageId=33136018
For those who are interested in a working solution, here is my smooks configuration:
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:fl="http://www.milyn.org/xsd/smooks/fixed-length-1.3.xsd">
<fl:reader fields="price[5]?trim,quantity[5]?trim,symbol[5]?trim.upper_case,comment[10]?trim" recordElementName="order">
<fl:listBinding beanId="order" class="test.Order" />
</fl:reader>
</smooks-resource-list>
Also, need to add the jar file of test.Order to the classpath of WSO2 ESB.

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.

Usage of SoapActionEndpointMapping in Spring-ws

I'm trying to create a WS based on a WSDL that defines one Request and one Response. The incoming request should be mapped to an endpoint depending on the SOAPAction defined in the SOAP message. To achieve this I'm trying to use the SoapActionEndpointMapping in my servlet.xml config file and define the mappings, as described in the Spring documentation.
<bean id="endpointMapping" class="org.springframework.ws.soap.server.endpoint.mapping.SoapActionEndpointMapping">
<property name="mappings">
<props>
<prop key="http://myCompany/MyService/MyRequest/mySoapActionOne">myFirstEndpoint</prop>
<prop key="http://myCompany/MyService/MyRequest/mySoapActionTwo">mySecondEndpoint</prop>
</props>
</property>
My endpoint extends AbstractMarshallingPayloadEndpoint and should be able to handle the requests.
The problem is that when I try to send a request (with SoapUI) i get the following error in the log:
WARN [EndpointNotFound] No endpoint mapping found for [SaajSoapMessage {http://schemas.mycompany/MyService}MyRequest]
I have used the PayloadRootQNameEndpointMapping with great success earlier but can not this to work.
Any help is appreciated.
Regards.
Do you have a handler adapter bean defined also? You'll need one in order to use a MarshallingPayloadEndpoint, so that spring knows how to perform the marshalling. The adapter is called something like MarshallingEndpointHandlerAdapter, or similar.
In your SOAP client (SOAPUI), you'll need to add the SOAPAction header to your request, to supply spring with the SOAP action to use in its mapping.
E.g. SOAPAction=http://myCompany/MyService/MyRequest/mySoapActionOne
It shouldn't make any difference what type of Endpoint you're using, because currently, you're receiving a 404 response - your request isn't finding its way to any endpoint.