Consuming a REST API
Mule Runtime Engine versions 3.5, 3.6, and 3.7 reached End of Life on or before January 25, 2020. For more information, contact your Customer Success Manager to determine how you can migrate to the latest Mule version. |
When you need to be able to consume a REST API from within a Mule application, you can do so by configuring an HTTP Request Connector. This document describes how to prepare a request, then call a REST API, and how to work with its response.
If your use case involves connecting to the same REST API many times, or if you are working with an API with complex authentication protocols, you may find that developing your own Anypoint Connector is a more effective, reusable solution. See Anypoint Connector DevKit for more details about building connectors.
Consider that perhaps a connector has already been developed for the API you wish to connect to. If so, look for it in Anypoint Exchange and download it into Studio.
Basic Anatomy
In its simplest incarnation, a Mule application set up to consume a REST API contains:
-
One or more message processors configured to build your request
-
An HTTP request connector configured to call the REST API
-
One or more message processors configured to accept and process the response
The portions of your application that build the request and process the response can be configured to meet the needs of your use case. This document focuses on the central step: calling the REST API with an HTTP connector.
Minimum Configuration
If the REST API you’re consuming doesn’t have a RAML file that describes it, you first need to know some minimum information, which you can generally acquire by visiting the API’s documentation.
-
Does the API require authentication?
If the API requires basic authentication, then configuring an HTTP endpoint to consume the API is possible. If the API uses complex authentication such as OAuth, consider building a custom connector with Anypoint Connector DevKit. -
What is its base URL?
You need the base URL to configure the outbound HTTP endpoint address to point to your API. -
What scope does the API allow you to access?
Based on your authentication credentials with the API, your application calls may be limited to only GET requests on certain resources, or limit you from accessing other resources at all. -
Which resources within that scope you want to access?
You need to know the exact path of the resources you want to access so that you can include them in the configuration of the outbound HTTP endpoint. -
What methods does the API support for each of those resources?
The default method for the HTTP outbound endpoint is POST, so you need to be aware of what methods are supported for the resource and, if necessary, change this default to the method you need to make a successful call. -
What input is the API expecting? (JSON, XML, etc.)
For POST and PUT calls, the API almost always requires a very specific input formatted according to its schema. -
What output will the API produce?
After the HTTP outbound endpoint in your flow, you need message processors to accept the response from the API and translate into a format that you can use. -
Does the API use redirects?
If it does, be sure to enable redirects in your HTTP outbound endpoint. -
What headers are required for the method you are using?
Note that GET requests may not need special headers, but POST, PUT, and DELETE requests almost always require headers. -
What error codes can you expect?
You might want to write the error codes into the subsequent steps of your application to deal with all possible responses from the API.
If you reference a RAML file that describes your API, then the HTTP connector will proactively present you with smart suggestions and options that are limited to only those supported by the API, so that you don’t need to investigate these things in advance. |
Simple Example
For example, if you want to consume the OpenWeatherMap API, access the documentation to determine the basic information that you need. In this example:
-
The API doesn’t require authentication
-
The base URL is http://api.openweathermap.org/data/2.5/
-
The scope is limited to a few resources, including weather, forecast, etc., and the only method that is available on those resource is GET
-
The sample API requests available in the documentation reveal that, if you want to retrieve the information about the current weather in London, UK, your API request looks like this:
http://api.openweathermap.org/data/2.5/weather?q=London,uk
This URL uses the following format:
Protocol | API Base URL | Resource Path | Query Parameters |
---|---|---|---|
|
|
|
|
To implement this call in your Mule application, configure your HTTP request connector as described below. (Note that this example shows only the configuration of this HTTP Connector. In order to make this example work, you would need to, at minimum, to configure an HTTP Listener to trigger a message in the flow and at least one message processor to accept the response. See the full examples for more information.)
Studio Visual Editor
-
Open the Properties Editor of the HTTP Connector.
-
Click on the green plus sign icon next to Connector Configuration to create a new global element that will encapsulate several configuration parameters for the connector.
-
Set the Host to api.openweathermap.org and the Port to 80
-
Click Ok to close this window. Back in the connector’s properties editor, set the Path to
/data/2.5/weather?q=London,uk
. Notice how putting the host you set in the global element together with the path you just set up makes up the full URL you wanted to reach. -
Select the Method you want to use from the drop-down list. This example uses GET.
-
Click any blank area of the canvas to Save your configuration changes.
Note that if the API you are calling requires Working with Security Requirements, involves redirects, or requires a specific Handling HTTP Content-Type and Encoding header be specified, the HTTP connector supports additional configuration to manage these details.
XML Editor
<http:request-config name="HTTP_Request_Configuration" host="api.openweathermap.org" port="80" doc:name="HTTP Request Configuration"/>
<flow name="basic_tutorialFlow1">
<...>
<http:request config-ref="HTTP_Request_Configuration" path="/data/2.5/weather?q=London,uk" method="GET" doc:name="HTTP"/>
</flow>
The response, in this example, is a JSON with the following structure:
{
"coord": {
"lon": -0.13,
"lat": 51.51
},
"sys": {
"message": 0.0506,
"country": "GB",
"sunrise": 1396589257,
"sunset": 1396636746
},
"weather": [
{
"id": 801,
"main": "Clouds",
"description": "few clouds",
"icon": "02d"
}
],
"base": "cmc stations",
"main": {
"temp": 287.46,
"pressure": 1010,
"temp_min": 285.93,
"temp_max": 289.26,
"humidity": 73
},
"wind": {
"speed": 2.06,
"gust": 4.11,
"deg": 310
},
"clouds": {
"all": 24
},
"dt": 1396633274,
"id": 2643743,
"name": "London",
"cod": 200
}
Depending on the needs of your application, you can use Transform Message component or a JSON-to-Object transformer to transform this response into another format from which you can extract information, route messages, etc.
If this API had and associated RAML file, you could reference it in the configuration element of the connector. With that in place, after you select what verb and what asset to call, Studio knows what the output is and expose the corresponding metadata, which can make integration to other elements in a flow a lot easier. |
Configuring Dynamic Requests with MEL Expressions
In the example above, the request was hardcoded in the URL:
http://api.openweathermap.org/data/2.5/weather?q=London,uk
Most use cases require that the call to the API change dynamically based on some data in the message. For example, in the following GET request example, the call instructs Mule to extract the city name from the payload of the message.
http://api.openweathermap.org/data/2.5/weather?q=#[payload.city]
Studio Visual Editor
-
In the HTTP connector’s properties editor, shorten the Path field to ony
/data/2.5/weather
-
Click the Add Parameter button, this will create a few new fields that correspond to a new query-param. For the query parameter’s name, type
q
and for its value typeLondon,uk
. This emulates the part of the string you removedq=London,uk
-
To take it a step further, replace the hard coded string you put in the field Value for a reference to a variable incoming element of the Mule message, for example
#[payload.city]
, assuming there is an element named city in the message payload.If you’re referencing a RAML file in your Connector Configuration, once you select the path and method, the required query-params for the type of request you want to make are automatically displayed.
XML Editor
<http:request-config name="HTTP_Request_Configuration" host="api.openweathermap.org" port="80" doc:name="HTTP Request Configuration"/>
<flow name="basic_tutorialFlow1">
<http:request config-ref="HTTP_Request_Configuration" path="/data/2.5/weather " method="GET" doc:name="HTTP">
<http:request-builder>
<http:query-param paramName="q" value="#[payload.city]"/>
</http:request-builder>
</http:request>
</flow>
In more complex cases, you might want to query a different resource depending on data in your message properties or in variables that you set earlier in your flow. For example:
http://api.someservice.com/#[flowVars['resource_path']]?#[flowVars['query_param']]=#[flowVars['query_param_value']]
Or, you might wish to dynamically configure the call’s method (GET, POST, etc.) based on logic performed earlier in your flow. To override the method set in the HTTP outbound endpoint, use a Property transformer before the endpoint to explicitly set the http.method
property (see instructions below).
Studio Visual Editor
Insert a Property transformer in your flow before your HTTP connector and configure it to set the http.method
property. If set, Mule uses this property to override the method attribute set on the HTTP connector.
This sample configuration assumes that you have configured a flow variable earlier in your flow called `method-override `with logic to populate the value of that variable with a valid method.
XML Editor or Standalone
Insert a set-property
element in your flow before your HTTP connector and configure it to set the http.method
property. If set, Mule uses this property to override the method attribute set on the HTTP connector.
<set-property propertyName="http.method" value="#[flowVars['method-override']]" doc:name="Property"/>
This sample configuration assumes that you have configured a flow variable earlier in your flow called method-override
with logic to populate the value of that variable with a valid method.
Handling HTTP Content-Type and Encoding
When you send a POST request body, Mule adheres to the following rules regarding Content-Type and encoding.
Sending
For a String, char[], Reader, or similar |
|
For binary content |
Encoding is not relevant. Mule sets
|
Working with Custom Headers
Many APIs require that you pass custom headers along with your requests, such as your developer key. Just like with the query parameters, you can also add headers to your request on the HTTP connector. For example, if the API you are consuming requires that you register for a developer key, then pass that key as a header on your requests using the header name accessKey
, you can add a property to set this header, as shown below.
Studio Visual Editor
-
In the HTTP connector’s properties editor click the Add Parameter button, this will create a few new fields that correspond to a new parameter. By default this will create a query-param, but you can pick other types of parameters from the dropdown menu, for this example pick header. For the header’s name, type
accessKey
and for its value, provide your key. -
To take it a step further, replace the hard coded string you put in the field Value for a reference to a variable incoming element of the Mule message, for example
#[payload.key]
, assuming there is an element named key in the message payload. -
You can also use a property placeholder, then define the value in your mule-app.properties file
If you’re referencing a RAML file in your Connector Configuration, once you select the path and method, the required headers for the type of request you want to make are automatically displayed
XML Editor
<http:request config-ref="HTTP_Request_Configuration" path="/data/2.5/weather " method="GET" doc:name="HTTP">
<http:request-builder>
<http:header headerName="accessKey" value="12341234"/>
</http:request-builder>
</http:request>
Note that you can also configure the value of the custom header using a MEL expression if you want to define the value dynamically (see image below).
<http:request config-ref="HTTP_Request_Configuration" path="/data/2.5/weather " method="GET" doc:name="HTTP">
<http:request-builder>
<http:header headerName="accessKey" value="#[payload.key]"/>
</http:request-builder>
</http:request>
You can also use a property placeholder, then define the value in your mule-app.properties file.
<http:request config-ref="HTTP_Request_Configuration" path="/data/2.5/weather " method="GET" doc:name="HTTP">
<http:request-builder>
<http:header headerName="accessKey" value="${access.key}"/>
</http:request-builder>
</http:request>
Working with Security Requirements
Note that if your use case involves working with an API with complex authentication protocols such as OAuth, you can build your own Anypoint Connector to consume the API. See Anypoint Connector DevKit for more details about building connectors. |
HTTPS
If the REST API you are consuming requires incoming requests arrive via HTTPS, you can configure a global HTTPS connector in your Mule application, then reference the connector in your outbound endpoint.
First, you must create a keystore file to certify the communication. This can be done using the keytool provided by Java, found in the bin directory of your Java installation. Navigate to this directory on your machine using the command line, then execute the following command to create a keystore file:
keytool -genkey -alias mule -keyalg RSA -keystore keystore.jks
You are prompted to create two passwords; remember the passwords! The command creates a jks
file in the local directory called keystore.jks
.
-
If you are using Mule Studio, drag this file into the `yourappname/src/main/resources `directory in Mule Studio’s Package Explorer.
-
If you are using Standalone, place this in the
MULE_HOME/conf
directory if to be used across multiple applications, or in theyourappname/src/main/resources
directory if you are using this just within this application.
Now, you can reference this keystore in a global HTTPS connector, which, in turn, is referenced by the HTTP outbound endpoint within your flow.
Studio Visual Editor
-
Open the Properties Editor of the HTTP connector, click the edit icon next to the connector configuration field, then select the TLS/SSL tab.
-
Select the radio button labeled Define an inline TLS Context.
-
Enter the Path, Key Password, and Store Password (the passwords your remembered when creating your keystore file) as per the example below, then click OK.
XML Editor or Standalone
<http:request-config name="HTTP_Request_Configuration" host="api.openweathermap.org" port="80" doc:name="HTTP Request Configuration">
<tls:context>
<tls:key-store path="keystore.jks" password="yourpassword" keyPassword="yourkeypassword"/>
</tls:context>
</http:request-config>
Note that if you placed your keystore in the yourappname/src/main/resources
directory then you can just specify the name of the keystore as the value of the path. Otherwise, if the keystore is located in the MULE_HOME/conf directory, specify "/keystore.jks"
as the path.
Basic Authentication
If the REST API that you are consuming requires that you pass basic authentication credentials, you can supply them within the outbound HTTP endpoint configuration.
Studio Visual Editor
-
Click the edit icon next to the connector configuration field, then select the Security tab.
-
Under Protocol, pick Basic.
-
Now the necessary fields for providing your username and password appear, your application passes these credentials with the API call at runtime.
-
Note that you can also replace these with property placeholders and define the properties in your
mule-app.properties
file. -
Navigate to your
mule-app.properties
file undersrc/main/app
in the Package Explorer. -
Define the placeholders here, as shown below.
XML Editor or Standalone
Add the user and password attributes to your http:outbound-endpoint
configuration, as shown below.
<http:request-config name="HTTP_Request_Configuration" host="api.openweathermap.org" port="80" doc:name="HTTP Request Configuration">
<http:basic-authentication username="myUsername" password="myPassword"/>
</http:request-config>
Rather than hardcode the values of your credentials, you can define them as property placeholders.
<http:request-config name="HTTP_Request_Configuration" host="api.openweathermap.org" port="80" doc:name="HTTP Request Configuration">
<http:basic-authentication username="${service.username}" password="${service.password}"/>
</http:request-config>
Open (or create, if you don’t have one) the mule-app.properties
file in your application’s src/main/app
folder, then define the properties in the file:
service.username=myusername
service.password=mypassword
Polling a REST API
Although the HTTP connector has built-in polling capabilities (described below), you can, instead, configure a Poll scope, then place your HTTP endpoint within it. Using a Poll scope allows you to take advantage of more robust polling functionality such as watermarking and scheduling with cron expressions. |
The HTTP connector supports polling an HTTP URL to invoke a REST API and generate messages from the result. This is useful for pull-only web services and situations where you want an API GET request to kick off processing in your flow.
To configure your application to poll a REST API, configure an inbound HTTP endpoint with a polling HTTP connector reference.
Studio Visual Editor
-
Open the Properties Editor of the HTTP endpoint. Click the green plus sign next to Connector Configuration.
-
In the Choose Global Type window, select HTTP Polling.
-
You can configure a polling connector with all the same optional attributes as a regular HTTP-HTTPS connector, with the addition of Polling Frequency (located in the Polling tab), and flags for processing the ETag header and Discarding Empty Content (both false by default).
The ETag, or entity tag, is HTTP’s cache control mechanism. APIs that support it will provide an HTTP header with an ETag value that represents a unique version of the resource located by the request URL. After successful processing when polling a resource, you might not want to process the same resource again if there are no changes. Activating the ETag checkbox instructs Mule not to send two requests with the same ETag.
XML Editor or Standalone
The following example illustrates how to configure a global http:polling-connector
.
<http:polling-connector name="HTTP_Polling" cookieSpec="netscape" validateConnections="true" pollingFrequency="1000" sendBufferSize="0" receiveBufferSize="0" receiveBacklog="0" clientSoTimeout="10000" serverSoTimeout="10000" socketSoLinger="0" checkEtag="false" discardEmptyContent="false" doc:name="HTTP Polling"/>
<flow name="Example_Flow1" doc:name="Example_Flow1">
<http:inbound-endpoint exchange-pattern="one-way" host="localhost" port="8081" doc:name="HTTP" connector-ref="HTTP_Polling"/>
Note that the checkEtag attribute (false by default) can be set to true if you want to enable HTTP’s cache control mechanism. APIs that support entity tags will provide an HTTP header with an ETag value that represents a unique version of the resource located by the request URL. After successful processing when polling a resource, you might not want to process the same resource again if there are no changes. Setting checkEtag to true instructs Mule not to send two requests with the same ETag.
Tips
-
Follow redirects: If you make a request to an API using GET, and the API responds with a
redirectLocation
header, configure your HTTP connector to follow redirects so as to push the request to the redirect URL. This only works for GET requests, as you cannot automatically follow redirects for a POST request.-
In Studio, click the Follow Redirects checkbox on the Advanced tab of the HTTP connector’s Properties Editor.
-
In XML, add the attribute
followRedirects=``"true"
.
-
-
POST requests and the API schema: If you are calling a REST API with a POST request, you need to obtain the API schema for the POST and match that format in the payload of the Mule message that you send to the API with your request. A good way to do this is to insert a Transform Message component before the HTTP outbound endpoint in your flow, then use the API’s schema in to define the output format.