Request Customization
About
When interacting with external services, it is often necessary to customize HTTP requests adding headers, cookies, setting timeouts, modifying the request body, or even intercepting requests conditionally. WebClient offers a rich and fluent API for such customizations.
HTTP Methods
WebClient supports all standard HTTP methods
GET
webClient.get()
Retrieve data without modifying server state
POST
webClient.post()
Send data to create resources
PUT
webClient.put()
Send full updates to existing resources
PATCH
webClient.patch()
Send partial updates
DELETE
webClient.delete()
Remove a resource
HEAD
webClient.method(HttpMethod.HEAD)
Retrieve only headers
OPTIONS
webClient.method(HttpMethod.OPTIONS)
Discover supported HTTP methods
TRACE
webClient.method(HttpMethod.TRACE)
Debugging or tracing path of a request
All methods internally use below when more flexibility is needed.
webClient.method(HttpMethod.X)
Setting Multiple Query Parameters
Use uriBuilder.queryParam(...)
repeatedly to add multiple query parameters.
Mono<Response> response = webClient.get()
.uri(uriBuilder -> uriBuilder
.path("/orders")
.queryParam("status", "PENDING")
.queryParam("sortBy", "date")
.queryParam("page", 1)
.queryParam("limit", 20)
.build())
.retrieve()
.bodyToMono(Response.class);
If we are using dynamic values, use a map:
Map<String, Object> queryParams = Map.of(
"status", "PENDING",
"sortBy", "date",
"page", 1,
"limit", 20
);
Mono<Response> response = webClient.get()
.uri(uriBuilder -> {
UriBuilder builder = uriBuilder.path("/orders");
queryParams.forEach(builder::queryParam);
return builder.build();
})
.retrieve()
.bodyToMono(Response.class);
Setting Multiple Path Variables
Use .uri(String template, Object... uriVariables)
with multiple values:
Mono<ProductDetail> response = webClient.get()
.uri("/stores/{storeId}/categories/{categoryId}/products/{productId}",
storeId, categoryId, productId)
.retrieve()
.bodyToMono(ProductDetail.class);
Using a Map<String, ?>
:
Map<String, String> pathVars = Map.of(
"storeId", "101",
"categoryId", "electronics",
"productId", "555"
);
Mono<ProductDetail> response = webClient.get()
.uri(uriBuilder -> uriBuilder
.path("/stores/{storeId}/categories/{categoryId}/products/{productId}")
.build(pathVars))
.retrieve()
.bodyToMono(ProductDetail.class);
Setting Request Body
Request body is usually needed for POST, PUT, PATCH.
a. Single Java Object
UserRequest request = new UserRequest("[email protected]", "John", "Doe");
Mono<UserResponse> response = webClient.post()
.uri("/users")
.bodyValue(request)
.retrieve()
.bodyToMono(UserResponse.class);
b. List or Collection
List<OrderRequest> orders = List.of(
new OrderRequest("item-1", 2),
new OrderRequest("item-2", 1)
);
Flux<OrderRequest> requestFlux = Flux.fromIterable(orders);
Flux<OrderResponse> response = webClient.post()
.uri("/bulk-orders")
.body(BodyInserters.fromPublisher(requestFlux, OrderRequest.class))
.retrieve()
.bodyToFlux(OrderResponse.class);
Setting Headers
Headers can be set using the headers
method inside the request spec.
Mono<CustomerResponse> response = webClient.get()
.uri("/customers/{id}", customerId)
.headers(httpHeaders -> {
httpHeaders.set("X-Correlation-ID", UUID.randomUUID().toString());
httpHeaders.setBearerAuth(jwtToken);
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(List.of(MediaType.APPLICATION_JSON));
})
.retrieve()
.bodyToMono(CustomerResponse.class);
We can also use header(String, String...)
directly for quick one-liners:
webClient.get()
.uri("/orders")
.header("X-Client-ID", "my-app")
.header(HttpHeaders.AUTHORIZATION, "Bearer " + jwtToken)
.retrieve()
.bodyToMono(OrderSummary.class);
Adding Cookies
Use .cookies()
to add one or more cookies to the request.
Mono<LoginStatus> response = webClient.get()
.uri("/session/check")
.cookies(cookies -> {
cookies.add("SESSIONID", sessionId);
cookies.add("clientType", "web");
})
.retrieve()
.bodyToMono(LoginStatus.class);
Change content type / accept type
These are crucial for telling the server what format we are sending and what we expect in return.
a. Set Content-Type (what we are sending)
webClient.post()
.uri("/users")
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(new UserRequest("[email protected]", "John"))
.retrieve()
.bodyToMono(UserResponse.class);
Other content types:
MediaType.APPLICATION_XML
MediaType.MULTIPART_FORM_DATA
MediaType.APPLICATION_FORM_URLENCODED
b. Set Accept Header (what we want back)
webClient.get()
.uri("/catalog")
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(CatalogResponse.class);
We can specify multiple types if needed:
webClient.get()
.uri("/report")
.accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML)
.retrieve()
.bodyToMono(Report.class);
Last updated