This commit introduces a toString() overload in
FastByteArrayOutputStream that accepts a Charset in order to mirror the
method that was introduced in ByteArrayOutputStream in JDK 10,
including a special case for when a single buffer is in use internally
to avoid the need to resize.
This commit also updates getContentAsString() in
ContentCachingRequestWrapper to use this new toString(Charset) method.
Closes gh-31737
This commit ensures that the RestClient uses the
IntrospectingClientHttpResponse to verify whether the response has a
body, and return null if it does not.
See gh-12671
Closes gh-31719
The getContentAsString method was originally added in d9b8826 to avoid
the extra copying inherent to calling ByteArrayOutputStream.toByteArray;
however, in f83c609 the class was updated to instead use
FastByteArrayOutputStream, and in the process the extra copy was brought
back when getContentAsString was changed to call toByteArray.
Switch to calling toByteArrayUnsafe, a method provided by
FastByteArrayOutputStream, which avoids the extra copy; since we
immediately pass the byte array to the String constructor, and it isn't
accessed anywhere else, the usage is safe.
See gh-31731
Prior to this commit, regressions were introduced with gh-31417:
1. the observation keyvalues would be inconsistent with the HTTP response
2. the observation scope would not cover all controller handlers, causing
traceIds to be missing
The first issue is caused by the fact that in case of error signals, the
observation was stopped before the response was fully committed, which
means further processing could happen and update the response status.
This commit delays the stop event until the response is committed in
case of errors.
The second problem is caused by the change from a `contextWrite`
operator to using the `tap` operator with a `SignalListener`. The
observation was started in the `doOnSubscription` callback, which is too
late in some cases. If the WebFlux controller handler is synchronous
non-blocking, the execution of the handler is performed before the
subscription happens. This means that for those handlers, the
observation was not started, even if the current observation was
present in the reactor context. This commit changes the
`doOnSubscription` to `doFirst` to ensure that the observation is
started at the right time.
Fixes gh-31703
Fixes gh-31706
Prior to this commit, the Jackson 2.x encoders, in case of encoding a
stream of data, would first release the `ByteArrayBuilder` and then the
`JsonGenerator`. This order is inconsistent with the single value
variant (see `o.s.h.codec.json.AbstractJackson2Encoder#encodeValue`) and
invalid since the `JsonGenerator` uses internally the
`ByteArrayBuilder`.
In case of a CSV Encoder, the codec can buffer data to write the column
names of the CSV file. Writing an empty Flux with this Encoder would not
fail but still log a NullPointerException ignored by the reactive
pipeline.
This commit fixes the order and avoid such issues at runtime.
Fixes gh-30493
This commit fixes a regression introduced by gh-21139
via the usage of Kotlin reflection to invoke HTTP
handler methods. It ensures that kotlin.Unit is treated
as void by returning null.
It also polishes CoroutinesUtils to have a consistent
handling compared to the regular case, and adds related
tests to prevent future regressions.
Closes gh-31648
This commit introduces a ConvertibleClientHttpResponse type that
extends ClientHttpResponse, and that can convert the body to a desired
type. Before this commit, it was not easy to use the configured HTTP
message converters in combination with RestClient::exchange.
Closes gh-31597
This commit ensures that not every OutputStream.write gets written as a
separate chunk, by buffering the written data in a BufferedOutputStream.
In some cases, a large quantity of small writes would result in many
sent chunks.
Closes gh-31361
This commit ensures that the StreamingHttpOutputMessage.Body.repeatable
flag is set in message converters for bodies that can be written
repeatedly.
Closes gh-31516
See gh-31449
This commit introduces the maxParts and maxPartSize properties to
PartEventHttpMessageReader, which can be used to limit the amount of
parts, and maximum part size respectively.
Closes gh-31343
Previously the documentation assumed that the readers knew how to use
the X-Forwarded-* headers. This commit documents details & examples
of how to use the X-Forwarded-* headers.
See gh-31491
This commit refines MaxUploadSizeExceededException
handling in order to translate to a "413 Payload Too Large"
status code instead of "500 Internal Server Error", with
related ProblemDetail body.
Closes gh-27170
This commit adds a test and polishing for a change in
AbstractNamedValueMethodArgumentResolver erroneously committed
with (unrelated) commit e57b942b.
If an argument becomes null after conversion and a default value is
applied, that default value should also pass through conversion.
Closes gh-31336
This commit adds a repeatable property to
StreamingHttpOutputMessage.Body, indicating that the body can be written
multiple times. In HttpComponentsClientHttpRequest, this property is
exposed via org.apache.hc.core5.http.HttpEntity.isRepeatable, to allow
for redirects.
Closes gh-31449
This commit re-generates the protobuf Java classes with a recent version
of the protoc binary and adds JMH benchmarks that exercise the message
converter for both the reading and writing cases.
See gh-29496
Since the Spring WebFlux HTTP server instrumentation has been moved from
the `WebFilter` to the `HttpWebHandlerAdapter`, we need to apply similar
changes there.
See gh-31417
Prior to this commit, HTTP server observations for Spring WebFlux could
be recorded twice for a single request in some cases. The "COMPLETE" and
"CANCEL" signals would race in the reactive pipeline and would trigger
both the `doOnComplete()` and ` `doOnCancel()` operators, each calling
`observation.stop()` on the current observation.
This would in fact publish two different observations for the same
request.
This commit ensures that the instrumentation uses the `Mono#tap`
operator to guard against this case and only call `Observation#stop`
once for each request.
Fixes gh-31417
Prior to this commit, a cancelled exchange would always result in an
`"status":"UNKNOWN"` KeyValue. This only applied to reactive variants,
as cancelled exchanges are not currently detected for Servlet
implementations.
In some cases, exchanges can be cancelled by clients before they are
completed, but the response was actually received by the client. The
response status information has been set by the application and the
response has been committed. For those cases, we shouldn't assume an
"UNKNOWN" value.
This commit assumes that committed responses have a response status set
by the application and that the observations should reflect that. From
now on, we only assume an "UNKNOWN" status if the response has not been
commited.
Fixes gh-31388
This commit reintroduces a deprecated ReactorResourceFactory in
org.springframework.http.client.reactive package that extends
the one in org.springframework.http.client package to avoid an
API breaking change and to provide a smoother upgrade experience.
Closes gh-31399
This commit adds a constructor with externally managed
Reactor Netty resources to ReactorNettyClientRequestFactory
and makes it lifecycle-aware in order to support Project CRaC.
Closes gh-31280
Closes gh-31281
This commit replaces uses of onErrorResume() with
- onErrorMap() in places where onErrorResume() is just used to map to a
different exception.
- onErrorComplete() where onErrorResume() just maps to Mono.empty().
- onErrorReturn() where onErrorResum() just maps to Mono.just().
Closes gh-31352