Nav
You are viewing an older version of this section. Click here to navigate to the latest version.

Consuming a REST API

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

Consume+REST+basic+anatomy

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: 


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

This URL uses the following format:

REST-api-address-format

Protocol API Base URL Resource Path Query Parameters

http://

api.openweathermap.org/data/2.5/

/weather

?q=London,uk

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

  1. Open the Properties Editor of the HTTP Connector.

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

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

    ge

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

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

    http2

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


    
             
          
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 response, in this example, is a JSON with 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
}

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: 


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


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

  2. 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 type London,uk. This emulates the part of the string you removed q=London,uk

    query+params+dissappearing

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

    http3

    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.


    
            
         
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 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:


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

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.

set+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.

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.


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

Sending

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

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

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

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

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

For binary content

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

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

  • If the Content-Type property is not set on the message, Mule 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

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.

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

    header1

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

    header2

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

    header3

    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


    
            
         
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>

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


    
            
         
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

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:


          
       
1
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 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, click the edit icon next to the connector configuration field, then select the TLS/SSL tab.

  2. Select the radio button labeled Define an inline TLS Context.

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

    keystore


    
             
          
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>

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.

  1. Click the edit icon next to the connector configuration field, then select the Security tab.

  2. Under Protocol, pick Basic.

  3. Now the necessary fields for providing your username and password appear, your application passes these credentials with the API call at runtime.

    basic+auth-1

  4. Note that you can also replace these with property placeholders and define the properties in your mule-app.properties file.

    basic+auth+placeholders

  5. Navigate to your mule-app.properties file under src/main/app in the Package Explorer.

    src-main-app-propertiesfile

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

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.

  1. Open the Properties Editor of the HTTP endpoint. Click the green plus sign next to Connector Configuration.

    rest-http-4

  2. In the Choose Global Type window, select HTTP Polling.

    http-polling

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

    global_polling

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.

The following example illustrates how to configure a global http:polling-connector.


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

      follow+redirects

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