This commit ensures that POST/PUT requests sent by the Netty client have
a Content-Length header set.
Integration tests have been refactored to use mockwebserver instead of
Jetty and have been parameterized to run on all available supported
clients.
Issue: SPR-14860
This commit adds the ability to serve Resources (static files) through a
RouterFunction. Two methods have been added to RouterFunctions: one that
exposes a given directory given a path pattern, and a generic method
that requires a lookup function.
Issue: SPR-14913
In general, web.util is supposed to remain lowest-level, not depending on any other web.* package. Since web.client also has a support package, a corresponding web.server.support package seemed appropriate for a helper class depending on ServerWebExchange in web.server itself.
This commit polishes previous one by also accepting
generic types explicitly declared with a class that
extends DataBuffer allowing to write Flux<DefaultDataBuffer>
for example.
Issue: SPR-14952
This modifies the signature of
ReactiveHttpOutputMessage#writeAndFlush(...) in order to
be able to use Flux<Flux<DataBuffer>> objects as arguments of
this method.
Issue: SPR-14952
This commit polishes Kotlin nullable support by reusing
MethodParameter#isOptional() instead of adding a new
MethodParameter#isNullable() method, adds
Kotlin tests and introduces Spring Web Reactive
support.
Issue: SPR-14165
Where `isOptional` is used, also check for `isNullable` i.e.
values are not considered required if they are Kotlin nullables:
- spring-messaging: named value method arguments
- spring-web: named value method arguments
- spring-webmvc: request parts
This means that Kotlin client code no longer has to explicity specify
"required=false" for Kotlin nullables -- this information is inferred
automatically by the framework.
Issue: SPR-14165
This commit adds a HTTP PATCH operation to the RestTemplate:
patchForObject. As with most operations, there are three variants:
varargs, Map, and URI based.
Issue: SPR-14857
This commit introduces a new ContentDisposition class designed
to parse and generate Content-Disposition header value as defined
in RFC 2183. It supports the disposition type and the name,
filename (or filename* when encoded according to RFC 5987) and
size parameters.
This new class is usually used thanks to
HttpHeaders#getContentDisposition() and
HttpHeaders#setContentDisposition(ContentDisposition).
Issue: SPR-14408
- ScriptedSubscriber has been renamed to Verifier
- The Publisher is passed to create() instead of verify()
- No more need to specify the generic type explicitly
- Version is now sync with reactor-core
Issue: SPR-14800
The method to access the Principal from the ServerWebExchange is now
a Mono<Principal> (rather than Optional<Principal>).
There is also support for Principal as a controller method argument.
Issue: SPR-14680, SPR-14865
This commit adds support for detecting the target WebHandler along with
WebFilters, WebExceptionHandlers, and other spring-web reactive
strategies in an ApplicationContext.
WebReactiveConfigurationSupport has @Bean factory methods for
DispatcherHandler and ResponseStatusExceptionHandler.
WebHttpHandlerBuilder has a static factory method that initializes the
builder from an ApplicationContext. This method is also used in the
DispatcherHandler#toHttpHandler(ApplicationContext) shortcut method.
Issue: SPR-14837
The ServerWebExchange now has a getFormData() method that delegates to
FormHttpMessageReader for the parsing and then caches the result so
it may be used multiples times during request processing.
Issue: SPR-14541
This commit introduces two new `WebClient` methods: `retrieveMono` and
`retrieveFlux`, both of which offer direct access to the response body.
More importantly, these methods publish a WebClientException if the
response status code is in the 4xx or 5xx series.
Issue: SPR-14852
This commit introduces a couple of changes to BodyInserters:
- Refactored writeWithMessageWriters into BiFunction
- BodyInserters.fromResource now uses ResourceMessagewriter from context
- BodyInserters.fromServerSentEvents now uses SseHttpMessageWriter from context
Reactor recently added the `ScriptedSubscriber` in its new
`reactor-addons` module. This `Subscriber` revissits the previous
`TestSubscriber` with many improvements, including:
* scripting each expectation
* builder API that guides you until the final verification step
* virtual time support
This commit refactor all existing tests to use this new
infrastructure and removed the `TestSubscriber` implementation.
Issue: SPR-14800
At present Tomcat expects a WriteListener to be registered immediately
on the initial thread so for the time being this commit ensures the
WriteListener is registered unconditionally for every request.
Issue: SPR-14772, SPR-14803
This commit replaces the lazy URI and headers initialization in the
reactive ServerHttpRequest in favor of eager initialization at
construction time. Both the URI and headers are nearly guaranteed to
be accessed for every request (URI for application path, headers for
"Origin" header).
Query params are still lazily parsed but parsing is idemptotent and
in the unlikely case of concurrent access (it's the framework that
typically accesses query params) it maybe parsed twice but should
be side effect free still.
Cookies are also parsed lazily and since we delegate to the "native"
request, it depends on the underlying runtime whether synchronization
is needed. This commit adds synchronization for the HttpServletRequest.
At present RxNetty, Reactor, and Undertow implementations provide
thread-safe access to cookies.
This commit introduces support for running multiple HttpHandler's under
distinct context paths which effectively allows running multiple
applications on the same server. ContextPathIntegrationTests contains
an example of two applications with different context paths.
In order to support this the HttpHandler adapters for all supported
runtimes now have a common base class HttpHandlerAdapterSupport
which has two constructor choices -- one with a single HttpHandler and
another with a Map<String, HttpHandler>.
Note that in addition to the contextPath under which an HttpHandler is
configured there may also be a "native" contextPath under which the
native runtime adapter is configured (e.g. Servlet containers). In such
cases the contextPath is a combination of the native contextPath and
the contextPath assigned to the HttpHandler. See for example
HttpHandlerAdapterSupportTests.
Issue: SPR-14726
This commit adds a bodyToMono and bodyToFlux convenience method to
ClientResponse/ServerRequest, similar to the body(Publisher) method that
is on ClientRequest/ServerResponse.
This commit removes the usage of Reactor adapters (about to
be moved from Reactor Core to a new Reactor Adapter module).
Instead, RxReactiveStreams is now used for adapting RxJava
1 and Flowable methods are used for RxJava 2.
Issue: SPR-14824
This commit refactors the web client to be more similar to
web.reactive.function. Changes include:
- Refactor ClientWebRequest to immutable ClientRequest with builder and
support for BodyInserters.
- Introduce ClientResponse which exposes headers, status, and support
for reading from the body with BodyExtractors.
- Removed ResponseErrorHandler, in favor of having a ClientResponse
with "error" status code (i.e. 4xx or 5xx). Also removed
WebClientException and subclasses.
- Refactored WebClientConfig to WebClientStrategies.
- Refactored ClientHttpRequestInterceptor to ExchangeFilterFunction.
- Removed ClientWebRequestPostProcessor in favor of
ExchangeFilterFunction, which allows for asynchronous execution.
Issue: SPR-14827
This commit moves the web.reactive.function.[BodyInserter|BodyExtractor]
to http.codec, so that they can be used from the client as well.
Furthermore, it parameterized both inserter and extractor over
ReactiveHttpOutputMessage and ReactiveHttpInputMessage respectively, so
that they can be limited to only be used on the client or server.
Typically the Mono<Void> from the HttpHandler also reflects the
completion of the request and response body processors and at that
point invoking AsyncContext#complete() from HandlerResultSubscriber
should be sufficient.
This commit explicitly propagates the AsyncListener.onComplete event
to the request and response body processors for added safety.
Technically as mentioned those processors should have completed but
depending on how the controller is written there is a possibility
the body processors may not have completed.
Issue: SPR-14772
ServerWebExchange now has a getPrincipal method and along with that a
ServerWebExchangeDecorator that can be used to wrap the exchange in
order to return the authenticated user.
Issue: SPR-14680
String with version 5 the name of Java Platform, Enterprise Edition
changed from J2EE to Java EE. However a lot of the documentation still
uses the term J2EE.
This commit includes the following changes:
* replace J2EE with Java EE where appropriate
This is not a blind search and replace. The following occurrences
remain unchanged:
* references to old J2EE releases, most notably 1.3 and 1.4.
* references to "Expert One-On-One J2EE Design and Development"
* references to "Core J2EE patterns"
* XML namespaces
* package names
Issue: SPR-14811
See gh-1206
Problem:
The following exception is observed on an async timeout:
"java.lang.IllegalStateException: It is invalid to call
isReady() when the response has not been put into non-blocking mode"
Current Implementation:
The async operation events sent by the web container are not propagated
to the internal implementation. When timeout/error happens and if the
application does not complete the async operation, the web container
will complete it. At that point if the application tries to read/write,
the operation will fail with an exception (above) that there is not
async operation started.
Proposed Solution:
On async timeout or error, make calls to:
- AbstractRequestBodyPublisher.onError,
- AbstractResponseBodyProcessor.onError,
- AbstractResponseBodyFlushProcessor.onError
As a result of these calls the async operation will be completed and no
more invocations of read/write will be made.
This commit simplifies the logic for applying beforeCommit actions
replacing the use of chained Mono.then calls with a single
Flux.concat.
Also renamed writeStatusCode, writeHeaders, and writeCookies to
applyStatusCode, applyHeaders, and applyCookies respectively to
better reflect we're simply setting them on the underlying response
(not necessarily written yet).
Commit e65a1a4372 introduced support in PrintingResultHandler for only
printing the request or response body in the Spring MVC Test framework
if the content type is known to be text-based (e.g., plain text, HTML,
XHTML, XML, JSON, etc.). For unknown content types the body is assumed
to be text-based and is therefore always printed. The latter behavior,
however, is undesirable since the content may in fact not be text-based.
This commit addresses this issue by making the printing of the request
or response body an opt-in feature. Specifically, if a character
encoding has been set, the request or response body will be printed by
the PrintingResultHandler. Note, however, that the character encoding
is set to ISO-8859-1 in MockHttpServletResponse by default.
In addition, MockHttpServletRequest's getContentAsString() method now
throws an IllegalStateException if the character encoding has not been
set.
Issue: SPR-14776
This is a port of Spring MVC CORS support for Spring Web Reactive:
- CORS classes keep the same name but are in the
web.cors.reactive package
- CorsConfiguration is reused because not tied to Servlet API
- CORS HandlerMapping integration is done at
AbstractHandlerMapping level
- AbstractUrlHandlerMapping and AbstractHandlerMethodMapping
have been slightly modified to call
AbstractHandlerMapping#processCorsRequest()
- Both global CORS configuration + @CrossOrigin support have
been implemented
Issue: SPR-14545
This commit configures a default SslContext if none has been provided.
This also enforces separate Netty bootstrap instances for cleartext and
TLS exchanges.
Issue: SPR-14744
In order to improve debugging and logging within test suites, this
commit introduces getContentAsByteArray() and getContentAsString()
methods in MockHttpServletRequest, analogous to the existing methods in
MockHttpServletResponse.
Issue: SPR-14717
This commit adds a new chain-based, interception contract to be used
with `WebClient`. This is the HTTP client equivalent of the `WebFilter`
contract already implemented in web reactive server.
A `ClientHttpRequestInterceptor` implementation can transform the
outgoing HTTP request (method, URI or headers) before delegating it to
the next interceptor in the chain, or bypass the request processing
altogether and return a (cached) HTTP response.
Issue: SPR-14502
This new `HttpMessageWriter` leverages the `ResourceRegionEncoder` to
write `ResourceRegion` to HTTP responses, thus supporting HTTP Range
requests.
Whenever possible, this message writer uses the zero copy support for
single range requests.
This `HttpMessageWriter` is never used directly, but is used as a
delegate by the `ResourceHttpMessageWriter`. When provided with the
`BOUNDARY_STRING_HINT`, the `ResourceRegionHttpMessageWriter`
adapts its behavior in order to write a single/multiple byte ranges.
Issue: SPR-14664
This commit adds the necessary infrastructure for the support of HTTP
Range requests. The new `ResourceRegionEncoder` can write
`ResourceRegion` objects as streams of bytes.
The `ResourceRegionEncoder` relies on an encoding hint
`BOUNDARY_STRING_HINT`. If present, the encoder infers that multiple
`ResourceRegion`s should be encoded and that the provided boundary
String should be used to separate ranges by mime boundaries.
If that hint is absent, only a single resource region is encoded.
Issue: SPR-14664
This commit makes it possible, in addition to provide hints, to
perform additional operations with the request and the response
at ServerHttpMessageReader/Writer level.
AbstractServerHttpMessageReader/Writer now provide
convenient beforeRead/beforeWrite abstract methods for such need.
Issue: SPR-14557
Move the AbstractServletHttpHandlerAdapterInitializer together with
the other two base classes in spring-web-reactive. Since the
interface is in the web package, this avoids a package cycle.
Also add a mention in the reference.
Issue: SPR-14713
This commit introduces three new WebApplicationInitializers for use with
Spring Web Reactive:
- The AbstractServletHttpHandlerAdapterInitializer registers a
ServletHttpHandlerAdapter that wraps a user-provided HttpHandler.
- The AbstractDispatcherHandlerInitializer registers a
ServletHttpHandlerAdapter that wraps a DispatcherHandler (or any
WebHandler). The handler is provided with an application context.
- The AbstractAnnotationConfigDispatcherHandlerInitializer is a
subclass of the above, creating an
AnnotationConfigApplicationContext based no provided @Configuration
classes.
Issue: SPR-14713
Rather than setting the status to 503 directly from the timeout
interceptor which no longer seems to work reliably with Servlet
containers like Jetty even performing an additional ERROR dispatch back
to the original URL, we know rather set the DeferredResult to an
AsyncTimeoutException, which results in a dispatch and standard
handling within Spring MVC. This should be a more reliable way of
dealing with timeouts.
Issue: SPR-14669
Since SPR-14522, the web reactive framework supports checkNotModified
features. This commit aligns the existing MVC infrastructure with
web reactive's behavior.
Because of the new Servlet 3.0 baseline, some constraints
aren't relevant anymore and duplicate code has been removed in
`HttpEntityMethodProcessor`.
Issue: SPR-14659
As per specification "The Subscription MUST allow the Subscriber to
call Subscription.request synchronously from within onNext or
onSubscribe". With the current implementation if Subscription.request
is called more than once when Subscriber.onSubscribe ISE will be
thrown - java.lang.IllegalStateException: DEMAND.
With this fix the implementation will not throw ISE and will allow
many invocations of Subscription.request when
Subscriber.onSubscribe.
This change puts the MockHttpServerRequest/Response under
org.springframework.mock.http.server.reactive.test which
mirrors the arrangement we have with the Servlet mock equivalents
and sets up the addition of MockHttpServerRequest/Response in
spring-test.
Issue: SPR-14421
This commit avoid merging automatically the SSE stream with
Flux.never(). Since browsers automatically reconnect when
the HTTP connection is closed, it is now the user responsability
to optionally perform a concatWith(Flux.never()) on streams that
complete in order to avoid receiving the data multiple times on
client side.
The behavior with hot streams that never complete does not change.
Issue: SPR-14578
- Renamed SseEvent to ServerSentEvent to make the name less redundant.
- ServerSentEvent is now immutable, having a builder to create new instances.
- Realigned the class properties to more closely match the events
described in the spec, so that `reconnectTime` becomes `retry`, and
`name` becomes `event`.
This commit updates the instructions on getting started with
Spring Web Reactive and also updates constructors and setters to
streamline the getting started procedure.
Issue: SPR-14640
This commit adds Smile and CBOR Jackson HttpMessageConverters
and make it possible to create Smile and CBOR ObjectMapper via
Jackson2ObjectMapperBuilder, which now allows to specify any
custom JsonFactory.
Like with JSON and XML Jackson support, the relevant
HttpMessageConverters are automaticially configurered by
Spring MVC WebMvcConfigurationSupport if jackson-dataformat-smile
or jackson-dataformat-cbor dependencies are found in the classpath.
Issue: SPR-14435
When using a `RestTemplate` instance within a Spring MVC application,
client exceptions may propagate in the MVC stack and can be wrongly
mapped by server `ExceptionHandlers`, leading to a wrong HTTP response
sent to the MVC client.
The `RestTemplate` instance uses `HttpMessageConverter` to decode
the remote service responses; and when those fail decoding an HTTP
response, they can throw an `HttpMessageNotReadableException`. That
exception then bubbles up through the `HttpMessageConverterExtractor`,
`RestTemplate` and the whole MVC stack, later mapped to HTTP 400
responses, since those exceptions can also be throws by the server stack
when the incoming requests can't be deserialized.
This commit wraps all `IOException` and `HttpMessageNotReadableException`
instances thrown by the extractor into `RestClientException`` instances.
It's now easier to consistently handle client exceptions and avoid such
edge cases.
Issue: SPR-13592
HttpEntityMethodProcessor should not throw IllegalArgumentExceptions for
invalid If-None-Match headers.
For those cases, this commit makes sure that both
`HttpEntityMethodProcessor` and `ServletWebRequest` have a consistent
behavior and stop processing the request as conditional and leave the
handler handle it.
Issue: SPR-14559
This commit sorts `ClientHttpRequestInterceptor`s when those are set in
`InterceptingHttpAccessor` (which `RestTemplate` extends from).
Interceptors can now be annotated with `@Order` or implements `Ordered`
to reflect their order of execution for each request.
Issue: SPR-13971
This commit adds support for HTTP header field parameters encoding, as
described in RFC5987.
Note that the default implementation still relies on US-ASCII encoding,
as the latest rfc7230 Section 3.2.4 says that:
> Newly defined header fields SHOULD limit their field values to
US-ASCII octets
Issue: SPR-14547
Prior to this commit, extracting an HTTP response with an empty body
and no Content-Type header using the WebClient would:
* trigger the use of the Jackson2JsonDecoder
* throw a NoSuchElementException because of the use of `Flux.single()`
This commit changes this behavior to `Flux.singleOrEmpty()` to avoid
throwing exceptions for empty Flux instances.
Issue: SPR-14582
reactor.test.TestSubscriber will not be part of Reactor Core
3.0.0 since it needs to be refactored to fit all the needs
expressed by the users. It is likely to be back later in one
of the Reactor Core 3.0.x releases.
This commit anticipate this removal by temporarily copying
TestSubscriber in spring-core test classes. As soon as
the new TestSubscriber will be available in Reactor Core,
Spring Framework reactive tests will use it again.
With the current state machine
- the implementation can hang after the last element when executing
on Jetty.
- in some cases there will be no flush after the last
Publisher<DataBuffer>.
AbstractResponseBodyProcessor.onError and
AbstractResponseBodyFlushProcessor.onError will be invoked when:
- The Publisher wants to signal with onError that there are failures.
Once onError is invoked the Subscription should be considered canceled.
- The internal implementation wants to signal with onError that there
are failures. In this use case the implementation should invoke
Subscription.cancel()
DataSourceUtils moved to main core.io.buffer package.
Consistently named Jackson2JsonDecoder/Encoder and Jaxb2XmlDecoder/Encoder.
Plenty of related polishing.
xmlunit 2.1.0 is the latest release for xmlunit.
Most of the xmlunit functionality used within spring-framework
was done through the xmlunit 1.x helper class
`org.custommonkey.xmlunit.XMLAssert`.
As of xmlunit 2.0.0 most of the XML comparison methods are done
through hamcrest matchers exposed by the xmlunit-matchers
library. In some cases during the migration, the matchers
had to be customized with custom `NodeMatcher` or
`DifferenceEvaluator` instances in order to keep the assertions
correct (they were performed with xmlunit 1.x previously).
Issue: SPR-14043