# How to Customize WebClient and RestClient Configurations in CoApi

> Customize CoApi WebClient and RestClient configurations via application.yml, customizers, or by replacing beans. Take full control of your HTTP clients.

- Repository: [Ahoo Wang/coapi](https://github.com/ahoo-wang/coapi)
- Tags: how-to-guide
- Published: 2026-02-23

---

**You can customize CoApi's HTTP clients by setting `coapi.*` properties in your [`application.yml`](https://github.com/ahoo-wang/coapi/blob/main/application.yml), providing your own `WebClientCustomizer` or `RestTemplateCustomizer` beans, or completely replacing the `WebClient` or `RestTemplate` beans with your own implementations.**

CoApi is a declarative HTTP client framework for Spring Boot that auto-configures reactive **WebClient** and blocking **RestTemplate** instances. Understanding how to customize WebClient and RestClient configurations in CoApi allows you to tune timeouts, add interceptors, and swap underlying HTTP engines without modifying core library code.

## Configuration Options Overview

CoApi exposes three distinct layers of customization:

- **Property-driven configuration** – YAML/properties entries under the `coapi` prefix (e.g., `coapi.webclient.connect-timeout`).
- **Customizer beans** – Spring beans implementing `WebClientCustomizer` or `RestTemplateCustomizer` that CoApi auto-detects and applies after its own defaults.
- **Full bean replacement** – Declaring a `@Primary` (or named) `WebClient` or `RestTemplate` bean causes CoApi’s auto-configuration to back off entirely.

## Property-Based Customization

The [[`CoApiProperties.kt`](https://github.com/ahoo-wang/coapi/blob/main/CoApiProperties.kt)](https://github.com/ahoo-wang/coapi/blob/main/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiProperties.kt) class maps external configuration to strongly-typed fields. You can set the following keys:

| Property | Type | Description |
|----------|------|-------------|
| `coapi.webclient.connect-timeout` | `Duration` | Connection timeout for the reactive client. |
| `coapi.webclient.read-timeout` | `Duration` | Response read timeout for the reactive client. |
| `coapi.webclient.max-in-memory-size` | `DataSize` | Maximum bytes buffered per response (prevents `DataBufferLimitException`). |
| `coapi.restclient.connect-timeout` | `Duration` | Connection timeout for the blocking client. |
| `coapi.restclient.read-timeout` | `Duration` | Response read timeout for the blocking client. |

Example [`application.yml`](https://github.com/ahoo-wang/coapi/blob/main/application.yml):

```yaml
coapi:
  webclient:
    connect-timeout: 5s
    read-timeout: 30s
    max-in-memory-size: 10MB
  restclient:
    connect-timeout: 5s
    read-timeout: 30s

```

The [[`CoApiWebClientCustomizer.kt`](https://github.com/ahoo-wang/coapi/blob/main/CoApiWebClientCustomizer.kt)](https://github.com/ahoo-wang/coapi/blob/main/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiWebClientCustomizer.kt) and [[`CoApiRestTemplateCustomizer.kt`](https://github.com/ahoo-wang/coapi/blob/main/CoApiRestTemplateCustomizer.kt)](https://github.com/ahoo-wang/coapi/blob/main/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiRestTemplateCustomizer.kt) classes consume these properties and apply them to the underlying builders.

## Programmatic Customization with Customizers

When YAML alone is insufficient, you can register Spring beans that implement `WebClientCustomizer` or `RestTemplateCustomizer`. CoApi’s auto-configuration detects these beans and invokes them **after** its own property-based customizer, giving you the final word on configuration.

### Customizing the Reactive WebClient

```kotlin
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.reactive.function.client.WebClientCustomizer

@Configuration
class WebClientCustomization {

    @Bean
    fun loggingWebClientCustomizer(): WebClientCustomizer = WebClientCustomizer { builder ->
        builder
            .defaultHeader("X-Request-Source", "CoApi-Custom")
            .filter { request, next ->
                println(">> Sending ${request.method()} request to ${request.url()}")
                next.exchange(request)
            }
    }
}

```

### Customizing the Blocking RestTemplate

```kotlin
import org.springframework.boot.web.client.RestTemplateCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.client.ClientHttpRequestInterceptor
import org.springframework.web.client.RestTemplate
import java.util.*

@Configuration
class RestTemplateCustomization {

    @Bean
    fun traceIdRestTemplateCustomizer(): RestTemplateCustomizer = RestTemplateCustomizer { template ->
        template.interceptors.add(ClientHttpRequestInterceptor { request, body, execution ->
            request.headers.add("X-Trace-Id", UUID.randomUUID().toString())
            execution.execute(request, body)
        })
    }
}

```

Because these beans are of type `WebClientCustomizer` and `RestTemplateCustomizer`, the [[`CoApiAutoConfiguration.kt`](https://github.com/ahoo-wang/coapi/blob/main/CoApiAutoConfiguration.kt)](https://github.com/ahoo-wang/coapi/blob/main/spring-boot-starter/src/main/kotlin/me/ahoo/coapi/spring/boot/starter/CoApiAutoConfiguration.kt) automatically wires them into the client builders.

## Complete Bean Replacement

If you need total control—such as swapping the underlying HTTP engine (e.g., OkHttp, Apache HttpClient 5) or applying global SSL settings—you can override the bean entirely.

### Replacing the WebClient

```kotlin
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import org.springframework.web.reactive.function.client.WebClient
import reactor.netty.http.client.HttpClient
import java.time.Duration

@Configuration
class WebClientReplacement {

    @Bean
    @Primary
    fun coapiWebClient(): WebClient {
        val httpClient = HttpClient.create()
            .responseTimeout(Duration.ofSeconds(45))
            .compress(true)

        return WebClient.builder()
            .clientConnector(ReactorClientHttpConnector(httpClient))
            .defaultHeader("X-Custom-Engine", "Netty-Custom")
            .build()
    }
}

```

### Replacing the RestTemplate

```kotlin
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
import org.springframework.web.client.RestTemplate

@Configuration
class RestTemplateReplacement {

    @Bean
    @Primary
    fun coapiRestTemplate(): RestTemplate {
        val requestFactory = HttpComponentsClientHttpRequestFactory().apply {
            setConnectTimeout(2000)
            setReadTimeout(20000)
        }
        return RestTemplate(requestFactory)
    }
}

```

When a bean named `coapiWebClient` or `coapiRestTemplate` (or any `@Primary` bean of the respective type) exists, the `@ConditionalOnMissingBean` guards in [`CoApiAutoConfiguration.kt`](https://github.com/ahoo-wang/coapi/blob/main/CoApiAutoConfiguration.kt) skip the auto‑configuration, ensuring your implementation is used throughout the application.

## Summary

- **Property-driven**: Set `coapi.webclient.*` and `coapi.restclient.*` in YAML to control timeouts and buffer sizes.  
- **Customizer beans**: Implement `WebClientCustomizer` or `RestTemplateCustomizer` to add headers, filters, or interceptors programmatically.  
- **Full replacement**: Declare a `@Primary` `WebClient` or `RestTemplate` bean to override the auto‑configured client entirely.  

All three mechanisms are supported by the `CoApiAutoConfiguration`, `CoApiProperties`, `CoApiWebClientCustomizer`, and `CoApiRestTemplateCustomizer` classes in the CoApi Spring‑Boot starter.

## Frequently Asked Questions

### How do I change the connection timeout for CoApi WebClient?

Set the `coapi.webclient.connect-timeout` property in your [`application.yml`](https://github.com/ahoo-wang/coapi/blob/main/application.yml) (e.g., `5s`). The `CoApiWebClientCustomizer` reads this value and applies it to the underlying `HttpClient` via the `WebClient.Builder`. If you need more granular control, provide a `WebClientCustomizer` bean and call `builder.clientConnector()` with a custom `ReactorClientHttpConnector`.

### Can I use a custom HTTP client like OkHttp with CoApi?

Yes. Declare a `@Primary` `WebClient` bean that uses the `OkHttpClient` connector (via `OkHttpClientConnector` for WebClient) or a `RestTemplate` bean that uses `OkHttp3ClientHttpRequestFactory`. Because the bean is marked `@Primary`, `CoApiAutoConfiguration` will skip its own bean creation and use your custom implementation for all CoApi clients.

### Why is my custom RestTemplate bean not being used by CoApi?

CoApi’s auto-configuration creates a `RestTemplate` bean only when **no** bean of that type exists (`@ConditionalOnMissingBean`). If your custom bean is not being picked up, ensure it is defined in a configuration class that is scanned by Spring Boot and that it is either named `coapiRestTemplate` or annotated with `@Primary`. Also verify that you are not accidentally creating the bean in a profile that is not active.

### How do I add a logging interceptor to CoApi requests?

Provide a `WebClientCustomizer` (for reactive) or `RestTemplateCustomizer` (for blocking) bean. In the customizer, add a `ExchangeFilterFunction` to the `WebClient.Builder` (e.g., `builder.filter(ExchangeFilterFunction.ofRequestProcessor { ... })`) or add a `ClientHttpRequestInterceptor` to the `RestTemplate`. CoApi’s auto-configuration will detect these beans and apply them after the default property-based settings, ensuring your logging logic is active for all CoApi-generated clients.