This site contains the documentation that is relevant to older WSO2 product versions and offerings.
For the latest WSO2 documentation, visit https://wso2.com/documentation/.
Sample Mediation Sequences
The following is a list of examples, explaining how you can use mediation sequences with your APIs in WSO2 API Cloud.
The custom sequences given below can be added to your API through the Publisher UI. See Add a Custom Sequence to your API, for instructions on how to do this.
Changing the content type
The following are two examples on how to convert your message.
Convert an XML message to JSON
To convert an XML message to JSON, add the messageType
property to the custom sequence as shown in the sample below.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="xml_to_json_message"> <property name="messageType" value="application/json" scope="axis2"/> </sequence>
This sequence can be added in the In flow and the Out flow.
The following sequences are available in WSO2 API Cloud by default. See Add a Custom Sequence to your API for instructions on adding this to your API.
- In Flow - xml_json_in_message
- Out Flow - xml_json_out_message
The diagram below shows how this fits into an API call as a custom sequence.
Convert a JSON message to XML
To convert a JSON message to XML, add the messageType property to the custom sequence as shown in the sample below.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="json_to_xml_message"> <property name="messageType" value="application/xml" scope="axis2"/> </sequence>
This sequence can be added in the In flow and the Out flow.
The following sequences are available in WSO2 API Cloud by default. See Add a Custom Sequence to your API for instructions on adding this to your API.
- In Flow - json_xml_in_message
- Out Flow - json_xml_out_message
The diagram below shows how this fits into an API call as a custom sequence.
Extracting, transforming or replacing the contents of a message
This example shows how to use custom sequences to
Change the existing attributes of a message
Create a new message
Add new attributes to a message.
Remove attributes from a message
For more information, see PayloadFactory Mediator.
Manipulating an XML message
This sequence can be added to your In flow as well as your Out flow. A sample custom sequence is given below.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="message_transform_xml"> <!-- Here you specify the format of the json message you need to output --> <payloadFactory media-type="xml"> <format> <userdata> <username>$1</username> <age>$2</age> </userdata> </format> <!-- Used to extract the elements from the XML payload and then assigns them to the variables $1 and $2 respectively. First argument is assigned to the variable $1 and the second to $2--> <args> <arg expression="//user/name" evaluator="xml"/> <arg expression="//user/age" evaluator="xml"/> </args> </payloadFactory> <property name="messageType" value="application/xml" scope="axis2"/> </sequence>
The diagram below shows how this sequence fits in to the Out flow.
Manipulating a JSON message
This sequence can be added to your In flow as well as your Out flow. A sample custom sequence is given below.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="message_transform_json"> <payloadFactory media-type="json"> <!-- Here you specify the format of the json message you need to output --> <format> { "userdata": { "username": "$1", "age": "$2" } } </format> <!-- Used to extract the elements from the JSON payload and then assigns them to the variables $1 and $2 respectively. First argument is assigned to the variable $1 and the second to $2--> <args> <arg expression="$.user.name" evaluator="json"/> <arg expression="$.user.age" evaluator="json"/> </args> </payloadFactory> <property name="messageType" value="application/json" scope="axis2"/> </sequence>
The diagram below shows how this sequence fits in to the Out flow.
Adding headers
You can add custom headers to your sequences.
Adding a custom header
Headers are added to the sequence using the header mediator. You can set a name
for the header and the scope
as transport
, as shown in the example below.
<header name="customHeader" scope="transport" value="test"/>
To add this custom header to your sequence, save the following code as an xml file. For instructions on adding this custom sequence to your API, see Add a Custom Sequence to your API.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="header_sequence"> <header name="customHeader" scope="transport" value="test"/> </sequence>
Passing an authorization header to your backend
You cannot directly create an authorization header with the name Authorization, in the API Cloud as the keyword Authorization is a reserved header name. The following is an alternative to add a header with this name.
- Pass the value you need to be set as the Authorization header in a property named
X-Authorization
. - Extract the value of
X-Authorization
and set it as the Authorization property inside your custom sequence. - Drop the additional
X-Authorization
header,
Now the Authorization property will be received by your backend with the value you initially passed in the X-Authorization
header. The sample is given below.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="authorization_header_exchange"> <property name="X-Authorization" expression="get-property('transport', 'X-Authorization')" scope="default" type="STRING"/> <property name="Authorization" expression="get-property('X-Authorization')" scope="transport" type="STRING" description=""/> <property name="X-Authorization" scope="transport" action="remove"/> </sequence>
The following sequence is available in WSO2 API Cloud by default. See Add a Custom Sequence to your API for instructions on adding this to your API.
- In Flow - authorization_header_exchange
Filtering messages
Filtering messages using a single condition
The Filter Mediator can be used to filter messages based on an XPath, JSONPath or a regular expression. If the test succeeds, the Filter mediator executes other mediators enclosed in the sequence. This acts as an if-else condition in java.
<filter (source="[XPath|json-eval(JSONPath)]" regex="string") | xpath="[XPath|json-eval(JSONPath)]"> mediator+ </filter>
This example shows how to check if the request parameter matches a certain string and print a message if it matches correctly (the path parameter countryCode,
passed in a request)
https:/gateway.api.cloud.wso2.com:443/t/wso2cloud/countries/us
Save the following code as an xml file. For instructions on adding this custom sequence to your API, see Add a Custom Sequence to your API.
<filter source="get-property('uri.var.countryCode')" regex=".*us"> <then> <log level="custom"> <property name="country" value="Details of USA are requested"/> </log> </then> <else> <log level="custom"> <property name="service" value="Details of a different country is requested"/> </log> </else> </filter>
Filtering messages using a series of conditions
Using custom sequences, you can evaluate a value passed through the API or check against a series of multiple conditions and then execute the relevant logic. This custom mediation behaves in the same way as a switch statement in java. This string is matched against the regular expression in each switch case mediator, in the specified order. If a matching case is found, it will be executed, and the remaining switch case mediators are not processed. If none of the case statements are matching, and a default case is specified, the default will be executed.
<switch source="[XPath|json-eval(JSON Path)]"> <case regex="string"> mediator+ </case>+ <default> mediator+ </default>? </switch>
The following example shows how to switch based on the request URI invoked through your API. If the particular condition is satisfied it will print a log message to the live log viewer. Save the following code as an xml file. For instructions on adding this custom sequence to your API, see Add a Custom Sequence to your API.
<sequence name="switch_conditions" trace="disable" xmlns="http://ws.apache.org/ns/synapse"> <switch source="get-property('To')"> <case regex=".*/countries/.*"> <log level = "custom"> <property name="value" value="countries operation is executed"/> </log> <!-- logic if it satisfies this condition ie if the request is for the request uri /countries --> </case> <case regex=".*/regions/.*"> <log level = "custom"> <property name="value" value="regions operation is executed"/> </log> <!-- logic if it satisfies this condition ie if the request is for the request uri /region --> </case> <case regex=".*/capital/.*"> <log level = "custom"> <property name="value" value="capital operation is executed"/> </log> <!-- logic if it satisfies this condition ie if the request is for the request uri /capital --> </case> <!– add endpoints as needed –> <default> <log level = "custom"> <property name="value" value="default operation is executed"/> </log> <!-- logic if it satisfies this condition ie if the request is for the default request uri --> </switch> </sequence>
Routing to different backends
Resource-based routing
You can route to different backends based on the resource which the APIs is invoked with. The logic being applied is similar to the Filtering based on a series of conditions.
In this example we set backend endpoints based on the resource of the API invocation. Save the following code as an xml file. For instructions on adding this custom sequence to your API, see Add a Custom Sequence to your API. The steps are explained within the comments.
<sequence name="dynamic_ep" trace="disable" xmlns="http://ws.apache.org/ns/synapse"> <!-- The property which is retrieved as get-property('To')" stores the request URI for the API. Based on this value we will determine the endpoint which the request needs to be routed to.--> <switch source="get-property('To')"> <case regex=".*/countries/.*"> <!-- We are then assigning the endpoint which we need to route to in a property named service_ep in this step --> <property name="service_ep" value="https//first.backend.url"/> </case> <case regex=".*/regions/.*"> <property name="service_ep" value="https://something.different.url"/> </case> <!– add endpoints as needed –> <default> <property name="service_ep" value="http://some.default.url"/> <!–default endpoint if required. However there should be a matching resource–> </default> </switch> <!-- Next we need to store this endpoint in a header named To as shown below --> <header name="To" expression="get-property('service_ep')"></header> <property expression="get-property('service_ep')" name="ENDPOINT_ADDRESS"></property> <!–Please note that "ENDPOINT_ADDRESS" (additional) property is defined here in order to populate destination address for statistics (API Usage by Destination). –> </sequence>
When using this sequence you need to provide the endpoint type in the Implement section as the Dynamic Endpoint, before uploading this sequence into your In Flow under mediation extensions.
Header-based routing
You can route you API to different endpoints based on an incoming header.
This example shows how to create a single API and call multiple endpoints based on a version header passed in the request. You do not need to create an API for each backend endpoint version. You can easily use a custom sequence for the API to route to the required destination. The sample sequence is given below. Save the following code as an xml file. For instructions on adding this custom sequence to your API, see Add a Custom Sequence to your API.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="VersionManagerSequence"> <!-- Property name is the parameter name that we added as a parameter when defining the endpoint url --> <!-- Property expression is how we will be retrieving the version passed as a header, i defined the header as Version when invoking using curl--> <property name="uri.var.version" expression="get-property('transport','Version')"/> <!-- Here we are checking if a header named as Version is available or not.--> <filter source="boolean(get-property('uri.var.version'))" regex="false"> <then> <!-- If no header mentioned as version is passed we will assign the version as our default version for the endpoint. So in the value you need to specify your default version of the endpoint --> <property name="uri.var.version" value="customerservice-default-version"/> <then> <else/> </filter> </sequence>
When specifying the endpoint for your API you need to provide is as mentioned below. So that the version which is passed through the header will be read inside the custom sequence and the backend endpoint will be populated accordingly.
http://backend_service/1.0.0/customerservice
When you invoke this API then you will be using a format similar to the cURL command given below. The request will be made to the specific version of the endpoint you pass as a header in your API call.
curl -k -v -X GET --header "Accept: application/json" --header "Version: customerservice-1.1.0" --header "Authorization: Bearer access_token" "https://gateway.api.cloud.wso2.com/t/tenant/customer/1.0/customerservice/customers/123"
Alternate Method
You can do the same using a dynamic sequence as well. For that you will need to make the below changes to the sequence explained in Resource-based routing. However all the versions needs to be defined and handled separately whereas the above sequence will dynamically populate any version which you pass in the header.
Working with properties
The Property Mediator has no direct impact on the message, but rather on the message context flowing through Synapse.
<property name="string" [action=set|remove] [type="string"] (value="literal" | expression="xpath") [scope=default|transport|axis2|axis2-client] [pattern="regex" [group="integer"]]> <xml-element/>? </property>
Setting properties within your custom mediation
For a list of the types of properties which you are able to work with, see Properties Reference. All properties which need to be set follow the same basic syntax. The following are some examples of setting properties.
Setting a content type
<sequence xmlns="http://ws.apache.org/ns/synapse" name="property_sequence"> <property name="ContentType" value="text/xml" scope="axis2"/> </sequence>
Setting a message type
<sequence xmlns="http://ws.apache.org/ns/synapse" name="property_sequence"> <property name="messageType" value="text/xml" scope="axis2"/> </sequence>
Preserve SOAP headers
<sequence xmlns="http://ws.apache.org/ns/synapse" name="property_sequence"> <property name="preserveProcessedHeaders" value="true" scope="default"/> </sequence>
Make POST requests without a payload
<sequence xmlns="http://ws.apache.org/ns/synapse" name="no_body_for_post_sequence"> <property name="NO_ENTITY_BODY" action="remove" scope="axis2"/> </sequence>
Get HTTP status code
<sequence xmlns="http://ws.apache.org/ns/synapse" name="status_code_property_sequence"> <property name="HTTP_SC" value="500" scope="axis2"/> </sequence>
Retrieving information about an API call
Following are some properties which are available to retrieve information regarding an API.
Property name | Description |
---|---|
| The name of the API. e.g., MyAPI |
| The type of the oauth key used for invoking the API. e.g., Production/Sandbox |
| Retrieves the version of the API. E.g., 1.0.0. |
| Retrieves the sub request with path and query parameters. e.g.,"/CheckPhoneNumber?PhoneNumber=1234567&LicenseKey=0". |
| Retrieves the context of the API in the form /t/tenantDomain/context/version for an API. e.g., "/t/tenant/new/1.0.0". |
| Retrieves the entire request path. e.g., "/t/tenant/new/1.0.0/CheckPhoneNumber?PhoneNumber=1234567&LicenseKey=0". |
| For example, "context". |
| Retrieves the transport. (e.g., "https") |
| Retrieves the name of the API. (e.g., "admin-AT-tenant.com--NewAPI:v1.0.0") |
| The HTTP method which was used for the invocation. (e.g., GET/POST) |
| The name of the OAuth2 application used for the invocation. (e.g., DefaultApplication) |
| The name of the person who published the API. (e.g., clouduser@gmail.com@wso2cloud) |
| The user who invoked the API. (e.g., subuser@gmail.com@wso2cloud) |
<sequence xmlns="http://ws.apache.org/ns/synapse" name="api_info_sequence"> <log level="custom"> <property name="ApiName" scope="transport" expression="$ctx:API_NAME"/> </log> </sequence>
Reading path and query parameters inside the sequence
You can read your input parameters to your API using custom sequences.
Difference between the path and query parameter
Path parameters are the parameters which are provided inline in the request URL. Query parameters are passed after a “?” character and concatenated with an “&” operand.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="api_info_sequence"> <log level="custom"> <!-- Retrieving the path parameter--> <property name="countryCode" scope="transport" expression="uri.var.code"/> <!-- Retrieving the query parameter--> <property name="id" scope="transport" expression="query.param.id"/> </log> </sequence>
Moving query parameters to the REST path
Your API backend often does not match the desired frontend representation. For example, it might have extra parameters (such as API keys) that you do not want to expose and have some query parameters that you now want to just include in the REST path. You might want to do a transformation like shown in the diagram below. To do this, you need to retrieve the parameter useful-param from the end user and then add it to the URL.
For a similar usecase, see this blog post.
In this example, the original request which we make through our WSO2 gateway with be in the following format.
https://gateway.api.cloud.wso2.com/t/wso2cloud/resource?useful-param=foo&aux=bar
When we map it to the backend which we have defined the request will be sent as follows.
https://new.api/foo?useful-param=foo&aux=bar
Since what we really need to send to the backend is https://new.api/foo
and we need to remove of the query parameters which are appended with the request URI defined in the original request. We need to add a sequence which drop the original request parameters from the request.The REST_URI_POSTFIX
property removes the parameters in the request. Save the following code as an xml file. For instructions on adding this custom sequence to your API, see Add a Custom Sequence to your API.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="drop_uri_sequence" > <property name="REST_URL_POSTFIX" scope="axis2" action="remove"/> </sequence>
Disable chunking
Some back-end servers do not accept chunked content. You need to disable chunking of the API requests made through the API Cloud. Save the following code as an xml file. For instructions on adding this custom sequence to your API, see Add a Custom Sequence to your API.
<?xml version="1.0" encoding="UTF-8"?> <sequence xmlns="http://ws.apache.org/ns/synapse" name="disable-chunking"> <property name="DISABLE_CHUNKING" value="true" scope="axis2" /> </sequence>
Debugging your requests
When making API requests it may be required to log certain attributes in the API request to verify the correctness of the requests. You can do this using the log mediator. This will log specific information which is requested through the sequence to the live log viewer.
There are four main levels of logging in the API Cloud
Full: If this is selected, all the standard headers logged at the Simple level as well as the full payload of the message will be logged. This log level causes the message content to be parsed and hence incurs a performance overhead.
Simple: If this is selected, the standard headers (i.e. To, From, WSAction, SOAPAction, ReplyTo, and MessageID) will be logged.
Headers: If this is selected, all the SOAP header blocks are logged.
Custom: If this is selected, only the properties added to the Log mediator configuration will be logged.
<log [level="string"] [separator="string"]> <property name="string" (value="literal" | expression="[XPath|json-eval(JSON Path)]")/>* </log>
See Retrieving information about an API call for a list of details regarding API calls.
Debugging requests
<?xml version="1.0" encoding="UTF-8"?> <sequence name="debug_in_flow" xmlns="http://ws.apache.org/ns/synapse"> <!-- All the standard headers as well as the full payload of the message will be logged --> <log level="full" /> <log level="custom"> <!-- Logs the host --> <property name="Host" expression="get-property('transport', 'Host')"/> <!-- Logs the context of the API --> <property name="Context" expression="get-property('To')"/> <!-- Logs the HTTP Method used for invoking the API --> <property name="HTTP_METHOD" expression="get-property('axis2', 'HTTP_METHOD')"/> <!-- logs the request URI--> <property name="Resource" expression="$axis2:REST_URL_POSTFIX"/> <!-- Logs the origin of the request --> <property name="Origin" expression="get-property('transport', 'Origin')"/> <!-- Logs the content type of the request --> <property name="Content-Type" expression="get-property('transport', 'Content-Type')"/> </log> </sequence>
The following sequence is available in WSO2 API Cloud by default. See Add a Custom Sequence to your API for instructions on adding this to your API.
- In Flow - debug_in_flow
Debugging responses
<?xml version="1.0" encoding="UTF-8"?> <sequence name="debug_out_flow" xmlns="http://ws.apache.org/ns/synapse"> <!-- All the standard headers as well as the full payload of the message will be logged --> <log level="full" /> <log level="custom"> <property name="EndPoint" expression="get-property('ENDPOINT_PREFIX')"/> <property name="Content-Type" expression="get-property('transport', 'Content-Type')"/> </log> </sequence>
The following sequence is available in WSO2 API Cloud by default. See Add a Custom Sequence to your API for instructions on adding this to your API.
- Out Flow - debug_out_flow
Service Chaining with API Cloud
If you need to invoke multiple other endpoints in order to get data to make the actual request of the API then you need to use a concept of service chaining. This sequence can be used if you need the response of calling one service to be used as the input to call the other service.
In this example we get the country name from the user and pass is to a backend to display the statistics for that country. The statistics backend requires the country ID to be passed and not the country name. The country ID which maps to the input country name should be obtained from an intermediate service.
If you have a similar service chaining requirement with WSO2 API Cloud please contact our support team on cloud@wso2.com for us to provide you the steps and assist you with this usecase.
Other custom mediation scenarios
If the custom mediation flow you are looking for is not listed in the examples above, contact us via support or by simply send an email to cloud@wso2.com with your use case.
Viewing sequences uploaded to APIs
To view the sequences which have already been uploaded to the APIs or to view the default sequences available in API Cloud follow the instructions given here.