Skip to content

Commit

Permalink
Consistently use releaseBody in DefaultWebClient
Browse files Browse the repository at this point in the history
  • Loading branch information
rstoyanchev committed Dec 4, 2019
1 parent 3a48682 commit 828fe39
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,11 @@
* <li>{@link #toBodilessEntity()}</li>
* <li>{@link #releaseBody()}</li>
* </ul>
* You can use {@code bodyToMono(Void.class)} if no response content is
* expected. However keep in mind that if the response does have content, the
* connection will be closed and will not be placed back in the pool.
* You can also use {@code bodyToMono(Void.class)} if no response content is
* expected. However keep in mind the connection will be closed, instead of
* being placed back in the pool, if any content does arrive. This is in
* contrast to {@link #releaseBody()} which does consume the full body and
* releases any content received.
*
* @author Brian Clozel
* @author Arjen Poutsma
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ private <T> Mono<T> statusHandlers(ClientResponse response) {
private <T> Mono<T> drainBody(ClientResponse response, Throwable ex) {
// Ensure the body is drained, even if the StatusHandler didn't consume it,
// but ignore exception, in case the handler did consume.
return (Mono<T>) response.bodyToMono(Void.class)
return (Mono<T>) response.releaseBody()
.onErrorResume(ex2 -> Mono.empty()).thenReturn(ex);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,9 +498,15 @@ interface RequestHeadersSpec<S extends RequestHeadersSpec<S>> {
* .exchange()
* .flatMapMany(response -&gt; response.bodyToFlux(Person.class));
* </pre>
* <p><strong>NOTE:</strong> You must always use one of the body or
* entity methods of the response to ensure resources are released.
* See {@link ClientResponse} for more details.
* <p><strong>NOTE:</strong> Unlike {@link #retrieve()}, when using
* {@code exchange()}, it is the responsibility of the application to
* consume any response content regardless of the scenario (success,
* error, unexpected data, etc). Not doing so can cause a memory leak.
* See {@link ClientResponse} for a list of all the available options
* for consuming the body. Generally prefer using {@link #retrieve()}
* unless you have a good reason to use {@code exchange()} which does
* allow to check the response status and headers before deciding how or
* if to consume the response.
* @return a {@code Mono} for the response
* @see #retrieve()
*/
Expand Down
17 changes: 6 additions & 11 deletions src/docs/asciidoc/web/webflux-webclient.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -496,17 +496,12 @@ Note that (unlike `retrieve()`), with `exchange()`, there are no automatic error

[CAUTION]
====
When using `exchange()`, you have to make sure that the body is always consumed or released,
even when an exception occurs (see <<core.adoc#databuffers-using,Using DataBuffer>>).
Typically, you do this by invoking either `bodyTo*` or `toEntity*` on `ClientResponse`
to convert the body into an object of the desired type, but
you can also invoke `releaseBody()` to discard the body contents without consuming it or
`toBodilessEntity()` to get just the status and headers (while discarding the body).
Finally, there is `bodyToMono(Void.class)`, which should only be used if no response content is
expected.
If the response does have content, the connection is closed and is not placed back in the pool,
because it is not left in a reusable state.
Unlike `retrieve()`, when using `exchange(), it is the responsibility of the application
to consume any response content regardless of the scenario (success, error, unexpected
data, etc). Not doing so can cause a memory leak. The Javadoc for `ClientResponse` lists
all the available options for consuming the body. Generally prefer using `retrieve()`
unless you have a good reason for using `exchange()` which does allow to check the
response status and headers before deciding how to or if to consume the response.
====


Expand Down

0 comments on commit 828fe39

Please sign in to comment.