Nav

Consuming a REST API

To consume a REST API from within a Mule application, you can configure an HTTP Request Connector. This document describes how to prepare a request, call a REST API, and work with its response.

If you connect to the same REST API many times, or work with an API having complex authentication protocols, consider developing your own Anypoint Connector. Check whether a connector already exists in Anypoint Exchange for the API you want to connect to. If so, download it into Anypoint Studio.

Basic Anatomy

In its simplest incarnation, a Mule application for consuming a REST API consists of the following things:

  • 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

consuming-a-rest-api-cd210AA

You can configure portions of the application that build the request and process the response. This document focuses on calling the REST API with an HTTP connector.

Minimum Configuration

The REST API you’re consuming needs to have a RAML file that describes it. In the RAML, you can define the following things:

  • Authentication

  • A base URI for configuring the outbound HTTP endpoint

  • Scope

    Based on authentication credentials, the application can limit calls to only GET requests on certain resources, for example, or otherwise limit access to a resource.

  • Resources

    You need configure the path of the resources for the outbound HTTP endpoint.

  • Methods

    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. 

  • Input validation

    For POST and PUT calls, the API almost always requires that input format, such as JSON and XML match its schema. 

If you reference a RAML file that describes your API, then the HTTP connector proactively presents you with smart suggestions.

In Mule 3.8.0 runtime, you can define or configure the following things:

  • Output format

    After the HTTP outbound endpoint in your flow, you need message processors to accept the response from the API and translate the response into a useable format.

  • Redirects If the API uses redirects, enable redirects in your HTTP outbound endpoint.

  • Headers for methods

    POST, PUT, and DELETE requests almost always require headers.

  • Error handling

Simple Example

This example consumes the OpenWeatherMap API. 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 and forecast. The only method that is available on those resource is GET.

  • The sample API requests available in the documentation show that to retrieve the information about the current weather in London, UK, your API request needs to look like this: 

http://api.openweathermap.org/data/2.5/weather?q=London,uk

This URL uses the following format:

consuming-a-rest-api-0f4ca

To implement this call in your Mule application, configure your HTTP request connector as described below. This example shows only the configuration of this HTTP Connector. 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.

  1. Open the Properties Editor of the HTTP Connector.

  2. Click add next to Connector Configuration to create a new global element that encapsulates configuration parameters for the connector.

  3. Set the Host to api.openweathermap.org and the Port to 80.

    consuming a rest api add1e
  4. Click OK.

  5. In the connector properties editor, set the Path to /data/2.5/weather?q=London,uk.

    When you specify the host you set in the global element together with the path to comprise the entire URL you want to reach.

  6. Select the Method you want to use from the drop-down list. This example uses GET.

    consuming-a-rest-api-b33ed
  7. Click any blank area of the canvas to Save your configuration changes.

    If the API you are calling requires working with security requirements, involves redirects, or requires a specifying an HTTP content-type and encoding header, the HTTP connector supports additional configuration options to manage these details.


    
             
          
1
2
3
4
5
6
7
8
<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 JSON response, in this example, has the following structure:


          
       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
  "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
}

You can use the Transform Message component or a JSON-to-Object transformer to transform this response into another format from which you can extract information, such as route messages.

If this API has an associated RAML file, you can reference it in the configuration element of the connector. With that in place, after you select the verb and asset to call, Studio exposes the metadata corresponding to the output. Integration with other elements in a flow is simplified.

Configuring Dynamic Requests with MEL Expressions

In the previous example, 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 runtime to extract the city name from the payload of the message. 

http://api.openweathermap.org/data/2.5/weather?q=#[payload.city]
  1. In the HTTP connector properties editor, shorten the Path field to only /data/2.5/weather

  2. Click Add Parameter to create a few new fields that correspond to a new query-param. For the query parameter name, type q and for its value type London,uk. This matches the part of the string you removed q=London,uk.

    consuming-a-rest-api-52bdc
  3. Replace the hard-coded string in the Parameters Value London,uk to a variable incoming element of the Mule message: #[payload.city].

    Using this variable assumes there is an element named city in the message payload.

    consuming a rest api 10816

    If you’re referencing a RAML file in your Connector Configuration, after selecting the path and method, the required query-params for the request type are displayed.


    
            
         
1
2
3
4
5
6
7
8
<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 some 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']]

You might want to dynamically configure the method, such as GET or POST, 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.

Insert a Property transformer in your flow before your HTTP connector and configure it to set the http.method property. Mule runtime uses this property to override the method attribute set on the HTTP connector.

consuming-a-rest-api-e27b0

This sample configuration assumes that you have configured a flow variable earlier in your flow called method-override that populates the value of that variable with a valid method.

Insert a set-property element in your flow before your HTTP connector and configure it to set the http.method property. If set, Mule runtime uses this property to override the method attribute set on the HTTP connector.


    
            
         
1
<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, Mule runtime adheres to the following rules regarding Content-Type and encoding of the body.

Sending

For a String, char[], Reader, or similar

  • If the endpoint has explicitly-set encoding, Mule runtime uses this encoding.

  • If the endpoint does not have explicitly-set encoding, Mule runtime determines the encoding from the message property Content-Type.

  • If the Content-Type message property is not set, Mule runtime uses the Mule Context default configuration.

  • For Content-Type, Mule runtime sends the message property Content-Type, but with the actual encoding set.

For binary content

Encoding is not relevant. Mule runtime sets Content-Type as follows:

  • If the Content-Type property is set on the message, Mule runtime uses the defined content-type.

  • If the Content-Type property is not set on the message, Mule runtime sets "application/octet-stream" as Content-Type.

Receiving

When receiving HTTP responses, the payload of the Mule message is typically the InputStream of the HTTP response.

Working with Custom Headers

APIs, such as the OpenWeatherMap, 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.

In the HTTP connector’s properties editor click the Add Parameter button, this creates a few new fields that correspond to a new parameter. By default this creates 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.

consuming a rest api 6147d

Alternatively, you can use the field Value to reference a variable incoming element of the Mule message, for example #[payload.key], assuming there is an element named key in the message payload.

+ image::consuming-a-rest-api-a9a95.png[consuming-a-rest-api-a9a95]

You can also use a property placeholder, then define the value in your mule-app.properties file

consuming-a-rest-api-ee3ac

If you’re referencing a RAML file in your Connector Configuration, after you select the path and method, the required headers for the type of request you want to make are displayed


    
            
         
1
2
3
4
5
<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>

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).


    
            
         
1
2
3
4
5
<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.


    
            
         
1
2
3
4
5
<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

If you work with complex authentication protocols such as OAuth, you can build your own Anypoint Connector to consume the API.

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. In this example, you create a Java keystore file (JKS) and configure TLS.

First, configure the HTTP connector for HTTPS:

consuming-a-rest-api-ba463

Next, create a keystore file to certify the communication. This can be done using the Java keytool in the bin directory of the 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 Studio, drag keystore.jks into the  appname/src/main/resources directory in Studio Package Explorer.

  • If you use a standalone XML in Mule Runtime, place this in the MULE_HOME/conf directory if to be used across multiple applications, or in the yourappname/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.

  1. Open the Properties Editor of the HTTP connector that you have configured to use HTTPS, and click consuming-a-rest-api-3467e next to the connector configuration field.

  2. On the TLS/SSL tab, select Use TLS Config.

  3. In Key Store Configuration, select a type of key store configuration from the drop-down. For example, select JKS (Java Key Store).

    The default type is JKS (Java Key Store).

  4. Enter the passwords you created when creating your keystore file in Path, Key Password, and Password, then click OK.

    If you placed your keystore in the appname/src/main/resources directory, 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.

    consuming-a-rest-api-b0370

    
             
          
1
2
3
4
5
<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>

Basic Authentication

If the REST API that you are consuming requires that you pass basic authentication credentials, you can provide them within the outbound HTTP endpoint configuration.

  1. Click consuming-a-rest-api-3467e next to the connector configuration field, then select the Authentication tab.

  2. Under Protocol, select Basic.

    The fields for providing your username and password appear. Your application passes these credentials with the API call at runtime.

    consuming-a-rest-api-4f8c3

    You can use property placeholders for credentials and define the properties in your mule-app.properties file.

    consuming-a-rest-api-c1749
  3. Navigate to your mule-app.properties file under src/main/app in the Package Explorer.

    consuming-a-rest-api-ba942
  4. Define the placeholders here, as shown below.

    define-props

Add the user and password attributes to your http:outbound-endpoint configuration, as shown below.


    
             
          
1
2
3
<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.


    
             
          
1
2
3
<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:


    
             
          
1
2
service.username=myusername
service.password=mypassword

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, pushing the request to the redirect URL. This applies to GET requests only, 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".

    consuming-a-rest-api-b88bf

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 define the output format in the properties editor.

consuming-a-rest-api-b372e