[[io.rest-client]]
= Calling REST Services

Spring Boot provides various convenient ways to call remote REST services.
If you are developing a non-blocking reactive application and you're using Spring WebFlux, then you can use javadoc:org.springframework.web.reactive.function.client.WebClient[].
If you prefer imperative APIs then you can use javadoc:org.springframework.web.client.RestClient[] or javadoc:org.springframework.web.client.RestTemplate[].



[[io.rest-client.webclient]]
== WebClient

If you have Spring WebFlux on your classpath we recommend that you use javadoc:org.springframework.web.reactive.function.client.WebClient[] to call remote REST services.
The javadoc:org.springframework.web.reactive.function.client.WebClient[] interface provides a functional style API and is fully reactive.
You can learn more about the javadoc:org.springframework.web.reactive.function.client.WebClient[] in the dedicated {url-spring-framework-docs}/web/webflux-webclient.html[section in the Spring Framework docs].

TIP: If you are not writing a reactive Spring WebFlux application you can use the xref:io/rest-client.adoc#io.rest-client.restclient[`RestClient`] instead of a javadoc:org.springframework.web.reactive.function.client.WebClient[].
This provides a similar functional API, but is imperative rather than reactive.

Spring Boot creates and pre-configures a prototype javadoc:org.springframework.web.reactive.function.client.WebClient$Builder[] bean for you.
It is strongly advised to inject it in your components and use it to create javadoc:org.springframework.web.reactive.function.client.WebClient[] instances.
Spring Boot is configuring that builder to share HTTP resources and reflect codecs setup in the same fashion as the server ones (see xref:web/reactive.adoc#web.reactive.webflux.httpcodecs[WebFlux HTTP codecs auto-configuration]), and more.

The following code shows a typical example:

include-code::MyService[]



[[io.rest-client.webclient.runtime]]
=== WebClient Runtime

Spring Boot will auto-detect which javadoc:org.springframework.http.client.reactive.ClientHttpConnector[] to use to drive javadoc:org.springframework.web.reactive.function.client.WebClient[] depending on the libraries available on the application classpath.
In order of preference, the following clients are supported:

. Reactor Netty
. Jetty RS client
. Apache HttpClient
. JDK HttpClient

If multiple clients are available on the classpath, the most preferred client will be used.

The `spring-boot-starter-webflux` starter depends on `io.projectreactor.netty:reactor-netty` by default, which brings both server and client implementations.
If you choose to use Jetty as a reactive server instead, you should add a dependency on the Jetty Reactive HTTP client library, `org.eclipse.jetty:jetty-reactive-httpclient`.
Using the same technology for server and client has its advantages, as it will automatically share HTTP resources between client and server.

Developers can override the resource configuration for Jetty and Reactor Netty by providing a custom javadoc:org.springframework.http.client.ReactorResourceFactory[] or javadoc:org.springframework.http.client.reactive.JettyResourceFactory[] bean - this will be applied to both clients and servers.

If you wish to override that choice for the client, you can define your own javadoc:org.springframework.http.client.reactive.ClientHttpConnector[] bean and have full control over the client configuration.

You can learn more about the {url-spring-framework-docs}/web/webflux-webclient/client-builder.html[`WebClient` configuration options in the Spring Framework reference documentation].



[[io.rest-client.webclient.configuration]]
=== Global HTTP Connector Configuration

If the auto-detected javadoc:org.springframework.http.client.reactive.ClientHttpConnector[] does not meet your needs, you can use the configprop:spring.http.clients.reactive.connector[] property to pick a specific connector.
For example, if you have Reactor Netty on your classpath, but you prefer Jetty's javadoc:org.eclipse.jetty.client.HttpClient[] you can add the following:

[configprops,yaml]
----
spring:
  http:
    clients:
      reactive:
        connector: jetty
----

TIP: You can also use xref:io/rest-client.adoc#io.rest-client.global-configuration[global configuration properties] which apply to all HTTP clients.

For more complex customizations, you can use javadoc:org.springframework.boot.http.client.autoconfigure.reactive.ClientHttpConnectorBuilderCustomizer[] or declare your own javadoc:org.springframework.boot.http.client.reactive.ClientHttpConnectorBuilder[] bean which will cause auto-configuration to back off.
This can be useful when you need to customize some of the internals of the underlying HTTP library.

For example, the following will use a JDK client configured with a specific javadoc:java.net.ProxySelector[]:

include-code::MyConnectorHttpConfiguration[]



[[io.rest-client.webclient.customization]]
=== WebClient Customization

There are three main approaches to javadoc:org.springframework.web.reactive.function.client.WebClient[] customization, depending on how broadly you want the customizations to apply.

To make the scope of any customizations as narrow as possible, inject the auto-configured javadoc:org.springframework.web.reactive.function.client.WebClient$Builder[] and then call its methods as required.
javadoc:org.springframework.web.reactive.function.client.WebClient$Builder[] instances are stateful: Any change on the builder is reflected in all clients subsequently created with it.
If you want to create several clients with the same builder, you can also consider cloning the builder with `WebClient.Builder other = builder.clone();`.

To make an application-wide, additive customization to all javadoc:org.springframework.web.reactive.function.client.WebClient$Builder[] instances, you can declare javadoc:org.springframework.boot.webclient.WebClientCustomizer[] beans and change the javadoc:org.springframework.web.reactive.function.client.WebClient$Builder[] locally at the point of injection.

Finally, you can fall back to the original API and use `WebClient.create()`.
In that case, no auto-configuration or javadoc:org.springframework.boot.webclient.WebClientCustomizer[] is applied.



[[io.rest-client.webclient.ssl]]
=== WebClient SSL Support

If you need custom SSL configuration on the javadoc:org.springframework.http.client.reactive.ClientHttpConnector[] used by the javadoc:org.springframework.web.reactive.function.client.WebClient[], you can inject a javadoc:org.springframework.boot.webclient.autoconfigure.WebClientSsl[] instance that can be used with the builder's `apply` method.

The javadoc:org.springframework.boot.webclient.autoconfigure.WebClientSsl[] interface provides access to any xref:features/ssl.adoc#features.ssl.bundles[SSL bundles] that you have defined in your `application.properties` or `application.yaml` file.

The following code shows a typical example:

include-code::MyService[]



[[io.rest-client.restclient]]
== RestClient

If you are not using Spring WebFlux or Project Reactor in your application we recommend that you use javadoc:org.springframework.web.client.RestClient[] to call remote REST services.

The javadoc:org.springframework.web.client.RestClient[] interface provides a functional style imperative API.

Spring Boot creates and pre-configures a prototype javadoc:org.springframework.web.client.RestClient$Builder[] bean for you.
It is strongly advised to inject it in your components and use it to create javadoc:org.springframework.web.client.RestClient[] instances.
Spring Boot is configuring that builder with javadoc:org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters[] and an appropriate javadoc:org.springframework.http.client.ClientHttpRequestFactory[].

The following code shows a typical example:

include-code::MyService[]



[[io.rest-client.restclient.customization]]
=== RestClient Customization

There are three main approaches to javadoc:org.springframework.web.client.RestClient[] customization, depending on how broadly you want the customizations to apply.

To make the scope of any customizations as narrow as possible, inject the auto-configured javadoc:org.springframework.web.client.RestClient$Builder[] and then call its methods as required.
javadoc:org.springframework.web.client.RestClient$Builder[] instances are stateful: Any change on the builder is reflected in all clients subsequently created with it.
If you want to create several clients with the same builder, you can also consider cloning the builder with `RestClient.Builder other = builder.clone();`.

To make an application-wide, additive customization to all javadoc:org.springframework.web.client.RestClient$Builder[] instances, you can declare javadoc:org.springframework.boot.restclient.RestClientCustomizer[] beans and change the javadoc:org.springframework.web.client.RestClient$Builder[] locally at the point of injection.

Finally, you can fall back to the original API and use `RestClient.create()`.
In that case, no auto-configuration or javadoc:org.springframework.boot.restclient.RestClientCustomizer[] is applied.

TIP: You can also change the xref:io/rest-client.adoc#io.rest-client.clienthttprequestfactory.configuration[global HTTP client configuration].



[[io.rest-client.restclient.ssl]]
=== RestClient SSL Support

If you need custom SSL configuration on the javadoc:org.springframework.http.client.ClientHttpRequestFactory[] used by the javadoc:org.springframework.web.client.RestClient[], you can inject a javadoc:org.springframework.boot.restclient.autoconfigure.RestClientSsl[] instance that can be used with the builder's `apply` method.

The javadoc:org.springframework.boot.restclient.autoconfigure.RestClientSsl[] interface provides access to any xref:features/ssl.adoc#features.ssl.bundles[SSL bundles] that you have defined in your `application.properties` or `application.yaml` file.

The following code shows a typical example:

include-code::MyService[]

If you need to apply other customization in addition to an SSL bundle, you can use the javadoc:org.springframework.boot.http.client.HttpClientSettings[] class with javadoc:org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder[]:

include-code::settings/MyService[]



[[io.rest-client.resttemplate]]
== RestTemplate

Spring Framework's javadoc:org.springframework.web.client.RestTemplate[] class predates javadoc:org.springframework.web.client.RestClient[] and is the classic way that many applications use to call remote REST services.
You might choose to use javadoc:org.springframework.web.client.RestTemplate[] when you have existing code that you don't want to migrate to javadoc:org.springframework.web.client.RestClient[], or because you're already familiar with the javadoc:org.springframework.web.client.RestTemplate[] API.

Since javadoc:org.springframework.web.client.RestTemplate[] instances often need to be customized before being used, Spring Boot does not provide any single auto-configured javadoc:org.springframework.web.client.RestTemplate[] bean.
It does, however, auto-configure a javadoc:org.springframework.boot.restclient.RestTemplateBuilder[], which can be used to create javadoc:org.springframework.web.client.RestTemplate[] instances when needed.
The auto-configured javadoc:org.springframework.boot.restclient.RestTemplateBuilder[] ensures that sensible javadoc:org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters[] and an appropriate javadoc:org.springframework.http.client.ClientHttpRequestFactory[] are applied to javadoc:org.springframework.web.client.RestTemplate[] instances.

The following code shows a typical example:

include-code::MyService[]

javadoc:org.springframework.boot.restclient.RestTemplateBuilder[] includes a number of useful methods that can be used to quickly configure a javadoc:org.springframework.web.client.RestTemplate[].
For example, to add BASIC authentication support, you can use `builder.basicAuthentication("user", "password").build()`.



[[io.rest-client.resttemplate.customization]]
=== RestTemplate Customization

There are three main approaches to javadoc:org.springframework.web.client.RestTemplate[] customization, depending on how broadly you want the customizations to apply.

To make the scope of any customizations as narrow as possible, inject the auto-configured javadoc:org.springframework.boot.restclient.RestTemplateBuilder[] and then call its methods as required.
Each method call returns a new javadoc:org.springframework.boot.restclient.RestTemplateBuilder[] instance, so the customizations only affect this use of the builder.

To make an application-wide, additive customization, use a javadoc:org.springframework.boot.restclient.RestTemplateCustomizer[] bean.
All such beans are automatically registered with the auto-configured javadoc:org.springframework.boot.restclient.RestTemplateBuilder[] and are applied to any templates that are built with it.

The following example shows a customizer that configures the use of a proxy for all hosts except `192.168.0.5`:

include-code::MyRestTemplateCustomizer[]

Finally, you can define your own javadoc:org.springframework.boot.restclient.RestTemplateBuilder[] bean.
Doing so will replace the auto-configured builder.
If you want any javadoc:org.springframework.boot.restclient.RestTemplateCustomizer[] beans to be applied to your custom builder, as the auto-configuration would have done, configure it using a javadoc:org.springframework.boot.restclient.autoconfigure.RestTemplateBuilderConfigurer[].
The following example exposes a javadoc:org.springframework.boot.restclient.RestTemplateBuilder[] that matches what Spring Boot's auto-configuration would have done, except that custom connect and read timeouts are also specified:

include-code::MyRestTemplateBuilderConfiguration[]

The most extreme (and rarely used) option is to create your own javadoc:org.springframework.boot.restclient.RestTemplateBuilder[] bean without using a configurer.
In addition to replacing the auto-configured builder, this also prevents any javadoc:org.springframework.boot.restclient.RestTemplateCustomizer[] beans from being used.

TIP: You can also change the xref:io/rest-client.adoc#io.rest-client.clienthttprequestfactory.configuration[global HTTP client configuration].



[[io.rest-client.resttemplate.ssl]]
=== RestTemplate SSL Support

If you need custom SSL configuration on the javadoc:org.springframework.web.client.RestTemplate[], you can apply an xref:features/ssl.adoc#features.ssl.bundles[SSL bundle] to the javadoc:org.springframework.boot.restclient.RestTemplateBuilder[] as shown in this example:

include-code::MyService[]



[[io.rest-client.clienthttprequestfactory]]
== HTTP Client Detection for RestClient and RestTemplate

Spring Boot will auto-detect which HTTP client to use with javadoc:org.springframework.web.client.RestClient[] and javadoc:org.springframework.web.client.RestTemplate[] depending on the libraries available on the application classpath.
In order of preference, the following clients are supported:

. Apache HttpClient
. Jetty HttpClient
. Reactor Netty HttpClient
. JDK client (`java.net.http.HttpClient`)
. Simple JDK client (`java.net.HttpURLConnection`)

If multiple clients are available on the classpath, and no global configuration is provided, the most preferred client will be used.



[[io.rest-client.clienthttprequestfactory.configuration]]
=== Global HTTP Client Configuration

If the auto-detected HTTP client does not meet your needs, you can use the configprop:spring.http.clients.imperative.factory[] property to pick a specific factory.
For example, if you have Apache HttpClient on your classpath, but you prefer Jetty's javadoc:org.eclipse.jetty.client.HttpClient[] you can add the following:

[configprops,yaml]
----
spring:
  http:
    clients:
      imperative:
        factory: jetty
----

TIP: You can also use xref:io/rest-client.adoc#io.rest-client.global-configuration[global configuration properties] which apply to all HTTP clients.

For more complex customizations, you can use javadoc:org.springframework.boot.http.client.autoconfigure.ClientHttpRequestFactoryBuilderCustomizer[] or declare your own javadoc:org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder[] bean which will cause auto-configuration to back off.
This can be useful when you need to customize some of the internals of the underlying HTTP library.

For example, the following will use a JDK client configured with a specific javadoc:java.net.ProxySelector[]:

include-code::MyClientHttpConfiguration[]



[[io.rest-client.apiversioning]]
== API Versioning

Both `WebClient` and `RestClient` support making versioned remote HTTP calls so that APIs can be evolved over time.
Commonly this involves sending an HTTP header, a query parameter or URL path segment that indicates the version of the API that should be used.

You can configure API versioning using methods on `WebClient.Builder` or `RestClient.Builder`.

TIP: API versioning is also supported on the server-side.
See the xref:web/servlet.adoc#web.servlet.spring-mvc.api-versioning[Spring MVC] and xref:web/reactive.adoc#web.reactive.webflux.api-versioning[Spring WebFlux] sections for details.

NOTE: The server-side API versioning configuration is not taken into account to auto-configure the client.
Clients that should use an API versioning strategy, typically for testing, need to configure it explicitly.



[[io.rest-client.httpservice]]
== HTTP Service Interface Clients

Instead of directly using a javadoc:org.springframework.web.client.RestClient[] or javadoc:org.springframework.web.reactive.function.client.WebClient[] to call an HTTP service, it's also possible to call them using annotated Java interfaces.

HTTP Service interfaces defines a service contract by using methods that are annotated with javadoc:org.springframework.web.service.annotation.HttpExchange[format=annotation], or more typically the method specific variants (javadoc:org.springframework.web.service.annotation.GetExchange[format=annotation], javadoc:org.springframework.web.service.annotation.PostExchange[format=annotation], javadoc:org.springframework.web.service.annotation.DeleteExchange[format=annotation], etc).

For example, the following code defines an HTTP Service for an "`echo`" API that will return a JSON object containing an echo of the request.

include-code::EchoService[]

More details about how to develop HTTP Service interface clients can be found in the {url-spring-framework-docs}/integration/rest-clients.html#rest-http-service-client[Spring Framework reference documentation].



[[io.rest-client.httpservice.importing]]
=== Importing HTTP Services

In order to use an HTTP Service interface as client you need to import it.
One way to achieve this is to use the javadoc:org.springframework.web.service.registry.ImportHttpServices[format=annotation] annotation, typically on your main application class.
You can use the annotation to import specific classes, or scan for classes to import from specific packages.

For example, the following configuration will scan for HTTP Service interfaces in the `com.example.myclients` package:

include-code::MyApplication[]



[[io.rest-client.httpservice.groups]]
=== Service Client Groups

Hard-coding absolute URLs in javadoc:org.springframework.web.service.annotation.HttpExchange[format=annotation] annotations is often not ideal in production applications.
Instead, you will typically want to give the HTTP Service client a logical name in your code, and then lookup a URL from a property based on that name.

HTTP Service clients allow you to do this by registering them into named groups.
An HTTP Service group is a collection of HTTP Service interfaces that all share common features.

For example, we may want to define an "`echo`" group to use for HTTP Service clients that call `\https://echo.zuplo.io`.

NOTE: HTTP Service groups can be used to define more than just URLs.
For example, your group could define connection timeouts and SSL settings.
You can also associate client customization logic to a group, such as adding code to insert required authorization headers.

To associate an HTTP Service interface with a group when using javadoc:org.springframework.web.service.registry.ImportHttpServices[format=annotation] you can use the `group` attribute.

For example, if we assume our example above is organized in such a way that all HTTP Service interfaces in the `com.example.myclients` package belong to the `echo` group.
We first remove the hardcoded URL from the service interface:

include-code::EchoService[]

We can then write:

include-code::MyApplication[]

And finally we can then use a `base-url` property to link the `echo` group to an actual URL:

[configprops,yaml]
----
spring:
  http:
    serviceclient:
      echo:
        base-url: "https://echo.zuplo.io"
----

TIP: HTTP Service clients will be associated with a group named "`default`" if you don't specify a group.

[NOTE]
====
If you have multiple HTTP Service interfaces in the same package that need to be associated with different groups you can list them individually.
The javadoc:org.springframework.web.service.registry.ImportHttpServices[format=annotation] is repeatable and the `types` attributes allows you to import individual classes.

For example:

include-code::repeat/MyApplication[]
====



[[io.rest-client.httpservice.properties]]
=== Configuration Properties

Configuration properties for HTTP Services can be specified under `spring.http.serviceclient.<group-name>`:

You can use properties to configure aspects such as:

* The base URL.
* Any default headers that should be sent.
* API versioning configuration.
* Redirect settings.
* Connection and read timeouts.
* SSL bundles to use.

TIP: You can also use xref:io/rest-client.adoc#io.rest-client.global-configuration[global configuration properties] which apply to all HTTP clients.

For example, the properties below will:

* Configure all HTTP clients to use a one second connect timeout (unless otherwise overridden).
* Configure HTTP Service clients in the "`echo`" group to:
** Use a specific base URL.
** Have a one-second connect timeout.
** Have a two-second read timeout.

[configprops,yaml]
----
spring:
  http:
    clients:
      connect-timeout: 1s
    serviceclient:
      echo:
        base-url: "https://echo.zuplo.io"
        connect-timeout: 2s
        read-timeout: 2s
----



[[io.rest-client.httpservice.customization]]
=== Customization

If you need to customize HTTP Service clients beyond basic properties, you can use an HTTP Service group configurer.
For `RestClient` backed HTTP Service clients, you can declare a bean that implements javadoc:org.springframework.web.client.support.RestClientHttpServiceGroupConfigurer[].
For `WebClient` backed HTTP Service clients you can declare a bean that implements javadoc:org.springframework.web.reactive.function.client.support.WebClientHttpServiceGroupConfigurer[].

Both work in the same way and will be automatically applied by Spring Boot's auto-configuration.

For example, the following configuration would add a group customizer that adds an HTTP header to each outgoing request containing the group name:

include-code::MyHttpServiceGroupConfiguration[]



[[io.rest-client.httpservice.advanced-configuration]]
=== Advanced Configuration

As well as the javadoc:org.springframework.web.service.registry.ImportHttpServices[format=annotation] annotation, Spring Framework also offers an javadoc:org.springframework.web.service.registry.AbstractHttpServiceRegistrar[] class.
You can javadoc:org.springframework.context.annotation.Import[format=annotation] your own extension of this class to perform programmatic configuration.
For more details, see {url-spring-framework-docs}/integration/rest-clients.html#rest-http-service-client-group-config[Spring Framework reference documentation].

Regardless of which method you use to register HTTP Service clients, Spring Boot's support remains the same.



[[io.rest-client.global-configuration]]
== Applying Global Configuration to All HTTP Clients

Regardless of the underlying technology being used, all HTTP clients have common settings that can be configured.

These include:

* Connection Timeouts.
* Read Timeouts.
* How HTTP redirects should be handled.
* Which SSL bundle should be used when connecting.

These common settings are represented by the javadoc:org.springframework.boot.http.client.HttpClientSettings[] class which can be passed into the `build(...)` methods of javadoc:org.springframework.boot.http.client.reactive.ClientHttpConnectorBuilder[] and javadoc:org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder[].

If you want to apply the same configuration to all auto-configured clients, you can use `spring.http.clients` properties to do so:

[configprops,yaml]
----
spring:
  http:
    clients:
      connect-timeout: 2s
      read-timeout: 1s
      redirects: dont-follow
----



[[io.rest-client.global-configuration.inetaddress-filtering]]
=== InetAddress Filtering and SSRF Protection

It's sometimes useful to limit the remote addresses that an HTTP client is permitted to call.
This technique can be especially useful when hardening your application against Server-Side Request Forgery (SSRF) attacks.

To limit the address that a client can call, you can use an javadoc:org.springframework.boot.http.client.InetAddressFilter[] which will only allow outgoing calls to addresses that match the filter.
The filter is a functional interface and you can either create your own implementation, or use one of the convenient factory methods.

Filters may be applied to the javadoc:org.springframework.boot.http.client.HttpClientSettings[] you used when building a client:

include-code::MyService[]

Or you can also define one as a javadoc:org.springframework.context.annotation.Bean[format=annotation] if you want to apply it to all auto-configured HTTP client builders:

include-code::MyHttpClientConfiguration[]
