---
schema_version: "1"
id: eec986159370ca8ee4f2c7b558465e624559dc6fd4b56377458daed4567e3482
title: HTTP-Based Connectors
collection: mulesoft
version: current
locale: en-us
portal_url: https://docs.salesforce.com/mulesoft/current/en-us/mule-sdk/latest/http-based-connectors.md
canonical_url: https://docs.mulesoft.com/mule-sdk/latest/http-based-connectors
source_site: docs.mulesoft.com
content_type: documentation
content_hash: b62800248ceb359b80ae317fea751780c3fec6280b9687a44a3b64fa161bcbe9
description: MuleSoft Documentation Site
release: "1.13"
latest: true
---
---
product: Mule SDK
version: 1.13
is-latest-version: true
---

# HTTP-Based Connectors

> For the full documentation index, see: https://docs.mulesoft.com/llms.txt

There is a special set of considerations for connectors that access a remote system by either
issuing HTTP requests or exposing HTTP endpoints.

## Use the Mule HTTP Client

The Mule HTTP Client **must** be used for making HTTP requests. Other HTTP clients (such as the
Jersey client, Apache HTTP Client, Jetty, Netty, and so on) **should not** be used in favor of the
Mule HTTP client.

The only exception to this rule is when the remote system vendor already provides a client library
that has some level of added value that would be too difficult to replicate with the use of the Mule
HTTP Client.

For example, the Amazon AWS connectors work by consuming an HTTP API that requires custom message
signing. Amazon provides a client library that encapsulates the logic necessary to make such
signing.

However, a client library that does nothing but wrap an HTTP client for convenience (like the Google
clients) is not a valid exception to this rule.

### Create the HTTP Client

There are two APIs for creating a Mule `HttpClient`:

- The `org.mule.sdk.api.http` API (recommended). Its entry point is
  `HttpService.client(Consumer<HttpClientConfigurer>)`. Because `mule-sdk-api` is bundled with your
  connector and isn’t coupled to the Mule Runtime lifecycle, a connector can use this API to consume
  newer HTTP features without raising its Minimum Mule Version. Use this API for new connectors and
  when migrating an existing connector that needs newer HTTP capabilities. See
  [SDK Forward Compatibility](https://docs.mulesoft.com/mule-sdk/latest/forward-compatibility) for more about forward compatibility.

- The legacy `org.mule.runtime.http.api` API, whose `HttpClient` is created from an
  `HttpClientConfiguration` builder through `httpService.getClientFactory().create(…​)`. This API
  remains fully supported and is a valid choice when your connector’s Minimum Mule Version already
  permits it. See [Use the Legacy org.mule.runtime.http.api HTTP Client](#legacy-http-client).

#### Use the org.mule.sdk.api HTTP Client

Inject the `org.mule.sdk.api.http.HttpService` and call `client(…​)` with a callback that configures
the client through an `HttpClientConfigurer`:

```java
@Inject
private HttpService httpService;

HttpClient client = httpService.client(configurer -> configurer
    .setName("client-name")
    // other setters...
);
```

The `HttpService.client(…​)` method returns an `org.mule.sdk.api.http.client.HttpClient` and throws
a `ClientCreationException` if the client can’t be created.

#### Configure the Client

The `HttpClientConfigurer` passed to the callback exposes these methods. Each one returns the same
configurer, so you can chain the calls:

<table><colgroup><col> <col></colgroup><thead><tr><th>Method</th><th>Description</th></tr></thead><tbody><tr><td><p><code>setName(String)</code></p></td><td><p>Sets the name of the <code>HttpClient</code>. Base it on the name of the owning configuration (see <a href="#set-the-http-client-name">[set-the-http-client-name]</a>).</p></td></tr><tr><td><p><code>setTlsContextFactory(TlsContextFactory)</code></p></td><td><p>Required for HTTPS. Provides the TLS data used to establish secure connections.</p></td></tr><tr><td><p><code>setMaxConnections(int)</code></p></td><td><p>Maximum number of outbound connections kept open at the same time. Unlimited by default.</p></td></tr><tr><td><p><code>setUsePersistentConnections(boolean)</code></p></td><td><p>Whether connections are kept open after a request completes. <code>true</code> by default.</p></td></tr><tr><td><p><code>setConnectionIdleTimeout(int)</code></p></td><td><p>Number of milliseconds a connection can remain idle before being closed.</p></td></tr><tr><td><p><code>setResponseBufferSize(int)</code></p></td><td><p>Size, in bytes, of the buffer used to store the HTTP response. Defaults to 10 KB.</p></td></tr><tr><td><p><code>setStreaming(boolean)</code></p></td><td><p>Whether the HTTP response is streamed, so processing continues as the body arrives.</p></td></tr><tr><td><p><code>setDecompress(Boolean)</code></p></td><td><p>Whether responses are decompressed automatically. <code>false</code> by default.</p></td></tr><tr><td><p><code>configProxy(Consumer&lt;ProxyConfigurer&gt;)</code></p></td><td><p>Configures a proxy for the client. See <a href="#provide-http-proxy-configuration">[provide-http-proxy-configuration]</a>.</p></td></tr><tr><td><p><code>configHttp1(Consumer&lt;Http1ProtocolConfigurer&gt;)</code></p></td><td><p>Enables, disables, and configures HTTP/1-specific parameters.</p></td></tr><tr><td><p><code>configHttp2(Consumer&lt;Http2ProtocolConfigurer&gt;)</code></p></td><td><p>Enables, disables, and configures HTTP/2-specific parameters.</p></td></tr><tr><td><p><code>configClientSocketProperties(Consumer&lt;TcpSocketPropertiesConfigurer&gt;)</code></p></td><td><p>Configures TCP-specific properties, such as the socket connection timeout.</p></td></tr></tbody></table>

For the complete reference, see the `HttpClientConfigurer` interface (package
`org.mule.sdk.api.http.client`) in the `mule-sdk-api` javadoc.

#### Send a Request

The `HttpClient` implements `Startable` and `Stoppable`, so it **must** be started before use and
stopped when you no longer need it. Build requests with `HttpService.requestBuilder()` and send them
without blocking through `sendAsync(…​)`, which returns a `CompletableFuture<HttpResponse>`:

```java
client.start();

HttpRequest request = httpService.requestBuilder()
    .method(GET)
    .uri("https://api.example.com/resource")
    .build();

CompletableFuture<HttpResponse> future = client.sendAsync(request, options -> options
    .setResponseTimeout(5000)
    .setFollowsRedirect(true));

// ... use the response, then stop the client during the stop() phase
client.stop();
```

Because `sendAsync(…​)` defers response body processing, handle the response on a different thread
when you need the full body right away. For example, with `CompletableFuture.whenCompleteAsync(…​)`.
This avoids blocking the client’s I/O threads.

#### Migrate from the Legacy HTTP Client

If your connector currently creates its client with the legacy
`org.mule.runtime.http.api.client.HttpClient` and the `HttpClientConfiguration` builder, you can
move to the configurer-based API as follows:

- Replace the injected `org.mule.runtime.http.api.HttpService` with
  `org.mule.sdk.api.http.HttpService`.

- Replace `httpService.getClientFactory().create(new HttpClientConfiguration.Builder()…​build())`
  with `httpService.client(configurer → …​)`, mapping each builder setter to the equivalent
  configurer method (for example, `.setName(…​)`).

- Update the imports of `HttpClient`, `HttpRequest`, `HttpResponse`, and related types to their
  `org.mule.sdk.api.http` counterparts.

> [!NOTE]
>
> - The new API delegates to the legacy one and **does not** deprecate it.
>
> - The legacy API remains valid. You can keep using it when your connector’s Minimum Mule Version
>   already permits it.
>
> - Moving to the new API is the recommended path when a connector wants access to newer HTTP
>   features without raising its Minimum Mule Version.

Because the new HTTP types come from `org.mule.sdk.api`, follow the guidance in
[Forward Compatibility Patterns](https://docs.mulesoft.com/mule-sdk/latest/forward-compatibility-patterns) when you need to call newer methods
conditionally and provide fallback behavior for older runtimes.

#### Use the Legacy org.mule.runtime.http.api HTTP Client

The legacy API creates the `HttpClient` from an `HttpClientConfiguration` builder:

```java
httpClient = httpService.getClientFactory()
    .create(new HttpClientConfiguration.Builder()
        .setName(configName)
        .build());
httpClient.start();
```

This API is still fully supported. Use it when your connector’s Minimum Mule Version already covers
it and you don’t need the newer HTTP features exposed by `org.mule.sdk.api.http`.

### Manage the Client in a Connection Provider

Regardless of which API creates the `HttpClient`, the connector’s `ConnectionProvider` is
responsible for managing it according to these rules.

- Handle the HTTP Client Lifecycle

  The ConnectionProvider that creates the HttpClient is responsible for managing its lifecycle.

- Use Cached Connection Providers

  Every ConnectionProvider that creates an HttpClient **must** implement the
  CachedConnectionProvider interface.

  Notice that this rule has implications on the connection object that the Connection Provider can
  yield. Because of the previously discussed Connection Object **must not** expose (nor be) the
  inner client rule, this means that the provided connection object needs to contain the HTTP client
  as part of its state and **must** be thread safe.

- Use Startable and Stoppable Connection Providers

  The Connection Provider **must** also implement the Startable and Stoppable interfaces. The
  HttpClient **must** be created and started during the start() phase and **must** be stopped during
  the stop() phase.

  Lifecycle example:

  ```java
  public class HttpConnectionProvider implements CachedConnectionProvider<HttpConnection>, Startable, Stoppable {

          @Inject
          private HttpService httpService;

          @Parameter
          private TlsContextFactory tlsContext;

          @RefName
          private String configName;

          @Override
     public void start() throws MuleException {
         initialiseIfNeeded(tlsContext);
         httpClient = httpService.client(configurer -> configurer
                 .setName(configName)
                 .setTlsContextFactory(tlsContext));
         httpClient.start();
     }

     @Override
     public void stop() throws MuleException {
             if (httpClient != null) {
                httpClient.stop();
             }
     }

     // rest of the implementation removed for example simplicity

  }
  ```

- Set the HTTP Client Name

  The HttpClient created by each ConnectionProvider **must** have a name which is based on (or
  simply matches) the name of the configuration that owns that ConnectionProvider.

  This is very important for performance troubleshooting. Each HttpClient creates a set of selector
  threads that it uses for I/O. Those threads are named after the client’s name. Giving those
  threads a meaningful name is key for diagnosing performance problems.

  The name of the owning config can be obtained using the @RefName annotation.

  Here’s an example of how to do this:

  ```java
  public class HttpConnectionProvider implements
  	CachedConnectionProvider<HttpConnection>, Startable, Stoppable {

          @Inject
          private HttpService httpService;

          @RefName
          private String configName;

          @Override
     public void start() throws MuleException {
         httpClient = httpService.client(configurer -> configurer.setName(configName));
         httpClient.start();
     }

     // rest of implementation removed for example simplicity

  }
  ```

- Leverage Non-Blocking I/O in Operations

  The HttpClient is capable of using non-blocking I/O to make the requests. Operations **must**
  leverage this capability and also be defined as non-blocking.

- Do not reference <http:requester-config> Elements

  The HttpService allows you to obtain the HttpClient associated with a separate
  <http:requester-config> element. Although this capability exists, it is not meant to be used by
  connectors. Connectors **must not** use this feature.

  All connectors in need of a HttpClient instance, **must** create and manage their own.

- Provide HTTP Proxy Configuration

  Connectors using HTTP Client instances must provide the ability to configure a proxy, similar to
  HTTP Connector. Common reasons to use proxy configuration include security, maintenance, and proxy
  caching. Many organizations also require proxy configuration when working behind firewalls.

  The following code snippets show how to configure proxy, for example, for the OAuth endpoint in
  HTTP Request Connector:

  Use this global proxy configuration as a reference:

  <http:proxy name="proxyConfig" host="localhost" port="3128" username="yourProxyUsername"
  password="yourProxyPassword" />

  When configuring for the Client Credentials grant type, use the following snippet:

  <http:request-config name="HTTP\_Request\_Configuration" host="api.github.com" port="443"
  doc:name="HTTP Request Configuration"> <oauth2:client-credentials-grant-type clientId="111"
  clientSecret="222" > <oauth2:token-request tokenUrl="https://github.com/login/oauth/authorize"" />
  <spring:property name="proxyConfig" ref="proxyConfig"/> </oauth2:client-credentials-grant-type>
  </http:request-config>

  When configuring for the Authorization Code grant type, use the following snippet:

  <http:request-config name="HTTP\_Request\_Configuration" host="api.github.com" protocol="HTTPS"
  port="443" usePersistentConnections="false" doc:name="HTTP Request Configuration">
  <oauth2:authorization-code-grant-type clientId="00a3d08a823faf378568"
  clientSecret="19c09306adbb84c2d4bc99c585df51d49fe858cf"
  redirectionUrl="http://localhost:8082/callback">; <oauth2:authorization-request
  authorizationUrl="https://github.com/login/oauth/authorize""
  localAuthorizationUrl="http://localhost:8082/login"/>; <oauth2:token-request
  tokenUrl="https://github.com/login/oauth/access\_token">; <oauth2:token-response
  accessToken="#\[payload.'access\_token'\]" refreshToken="#\[payload\['access\_token'\]\]"/>
  </oauth2:token-request> <spring:property name="proxyConfig" ref="proxyConfig"/>
  </oauth2:authorization-code-grant-type> </http:request-config>

  When using the `proxyConfig` type, the connection provider must include a `@Parameter` annotation
  so that the connection refers to the proxy, for example:

  ```java
  @Parameter
  @Optional
  @Placement(tab = "Proxy", order = 1)
  private MyConnectorProxyConfiguration proxyConfig;
  ```

  You must also set the proxy configuration in the HTTP Client:

  ```java
  .setProxyConfig(connectionParams.getProxyConfig())
  ```

  For more information, refer to the
  [Java code](https://github.com/mulesoft/mule-http-connector/blob/9914ce6aa6ceb3aa16a5b821289f15b9c6af6acc/src/main/java/org/mule/extension/http/api/request/proxy/DefaultProxyConfig.java)
  for how HTTP Connector handles the proxy.

## Exposing HTTP Inbound Endpoints

Some connectors need to expose their own HTTP inbound endpoints.

To achieve this, connectors **must** reference an external <http:listener-config> element to obtain
an HttpServer instance. Connectors **must not** create their own servers.

This **must** be achieved as follows:

- Correctly reference the listener config

  The connection provider **must** expose a String parameter called listenerConfig. This parameter
  **must** be of type String, not accept expressions, and use the @ConfigReference annotation to
  indicate that it points to an <http:listener-config> element.

  For example:

  ```java
  @Parameter
  @Expression(NOT_SUPPORTED)
  @ConfigReference(name = "LISTENER_CONFIG", namespace = "HTTP")
  private String listenerConfig;
  ```

- Add a RequestHandler

  Using the listenerConfig parameter added above, a matching HttpServer instance can be obtained
  like this:

  ```java
  HttpServer httpServer;
  try {
          httpServer = httpService.getServerFactory().lookup(listenerConfig);
          } catch (ServerNotFoundException e) {
          throw new IllegalArgumentException(
             format("Connector configuration '%s' refers to an <http:listener-config> with name '%s', "
                 + "but such element doesn't exist", configName, listenerConfigName),
             e);
  }
  ```

  With the obtained HttpServer, a new RequestHandler can be added using the
  org.mule.runtime.http.api.server.HttpServer#addRequestHandler(java.lang.String,
  org.mule.runtime.http.api.server.RequestHandler) method.

  The connector **must** carefully follow the contract defined in the Javadocs for that method. Most
  importantly, invoking that method will return a RequestHandlerManager instance. Those instances
  **must** be kept by the connector as they expose two important methods: start() and stop().

  The inbound endpoint will not be actually functioning until the start() method is invoked on the
  RequestHandlerManager. At the same time, the endpoint does not go away until the stop() method is
  invoked on the RequestHandlerManager.

  That means that when the component owning the custom endpoint is stopped, so **must** the
  RequestHandlerManager be stopped. Otherwise, your connector will generate a memory leak.

### Make Timeouts Configurable

The connector **must** expose a parameter that controls the timeout of the HTTP requests.

This **must** be done in a way that is consistent with the previously discussed rules about how to
handle duration parameters and making timeouts Config Override parameters.

## HTTPS Security

The connector **must** support the HTTPS scheme whenever possible and **must** consider it as the
recommended option:

- If the remote system supports only HTTPS, then the connector **must** have a required
  TlsContextFactory parameter.

- If the remote system supports both HTTP and HTTPS schemes, then the connector **must** support
  both options but log a warning when HTTP is used.

## See Also

- [Salesforce Help](https://help.salesforce.com)

- [Mule SDK Development Best Practices](https://docs.mulesoft.com/mule-sdk/latest/best-practices)
