Prior to this commit, controller handlers (regular and exception
handlers as well) would not overwrite existing HTTP response headers on
the exchange. This would lead to situations where Content-Type values
set during the initial handling phase would not be overwritten when
handling an error later on.
This commit aligns the implementation of that result handler on the
Spring MVC one in that regard.
Issue: SPR-17082
Prior to this commit, the `DefaultClientResponse` implementation would
handle HTTP client cases where the server response body would need to be
consumed (pooled resources need to be released) and the body publisher
cancelled right away. This is done to avoid reading the whole response
body and returning the connection to the pool, now that this connection
cannot be reused.
This was done already when the `WebClient` is asked for a `Void` type
for the response body.
SPR-17054 brought a new case for that: whenever no message reader is
able to decode the response body, an `UnsupportedMediaTypeException`
error signal is sent. Prior to this commit, the response body would not
be consumed and cancelled for that case.
This commit refactors all those cases from the `DefaultClientResponse`
directly into the `BodyExtractors`, since most of the logic and
knowledge for that belongs there. We only need to only apply this
behavior when the HTTP client is involved, as the server does not want
this to happen.
Issue: SPR-17054
Given "/{foo}" and "/a=42;c=b", previously that would be treated as a
sequence of matrix vars with an empty path variable. After the change
the path variable "foo" is "a=42".
This should be ok for backawards compatibility since it's unlikely for
anything to rely on an empty path variable.
Issue: SPR-11897
Leverage https://github.com/jetty-project/jetty-reactive-httpclient
to add support for Jetty in WebClient via JettyClientHttpConnector.
Implemented with buffer copy instead of optimized buffer wrapping
because the latter hangs since Callback#succeeded doesn't allow
releasing the buffer and requesting more data at different times
(required for Mono<DataBuffer> for example).
See https://github.com/eclipse/jetty.project/issues/2429.
Issue: SPR-15092
Prior to this commit, resolving an argument for a WebFlux controller
that's missing from the request and not required by the handler would
throw a NullPointerException in some cases.
This involves the conversion of the parameter (a `String` parameter type
might not trigger this behavior) and sending a `null` within a reactive
stream, which is illegal per the RS spec.
We now rely on a `Mono.justOrEmpty()` to handle those specific cases.
Issue: SPR-17050
Prior to this commit, `WebClient` would throw `IllegalArgumentException`
when receiving an HTTP response with an unknown HTTP status code.
This commit is a follow up of SPR-16748 (supporting non-standard HTTP
status codes on the reactive `ClientHttpResponse`), and is mirroring
SPR-15978 (supporting non-standard HTTP status codes in `RestTemplate`).
With this change, `WebClient` now tolerates unknown status codes in some
cases, while not offering that choice as a first class citizen:
`HttpStatus` is still the preferred way to deal with HTTP status codes.
Here's how `WebClient` will behave when fetching the full response:
```
// Given a remote endpoint returning a "123" HTTP status code
Mono<ClientResponse> result = this.webClient.get()
.uri("/status/123")
.exchange();
// will still throw an IllegalArgumentException
HttpStatus status = result.block().statusCode();
// is safe and will return 123
int statusCode = result.block().rawStatusCode();
```
Resolving directly the response body with `retrieve()` is different.
```
// will send an error signal with a UnknownHttpStatusCodeException
Mono<String> result = this.webClient.get()
.uri("/status/123")
.retrieve()
.bodyToMono(String.class);
```
In general, `WebClient` will provide high-level support
for well-known HTTP status codes, like error handling with
`WebClient.ResponseSpec#onStatus`.
For such support with unknown status codes, it is better to rely
on lower level constructs such as `ExchangeFilterFunction`.
Issue: SPR-16819
1. Use special category prefix "spring-web.reactivestreams" for logging
of reactive streams signals in spring-web, since those are quite
verbose would fill the logs at TRACE.
2. Add and use loggers in request and websocket session implementations
separate from reactive streams bridge for regular TRACE logging.
3. Improve log messages and add where missing (e.g. for Reactor)
Issue: SPR-16898
Hiding it (at AbstractServerHttpRequest) complicates matters since
requests are often mutated and decorated, plus it's also possible to
implement the interface directly (we've one, albeit corner case).
Issue: SPR-16966
1. Eliminate WebSocketClientSupport base class whose main value was
to provide logging but those methods get in the way of inserting a
log prefix.
2. Remove checks and synchronization in lifecycle methods of Jetty
client since underlying Jetty client already has that.
This commit introduces RouterFunctions.Builder, a new way to build
router functions that does not require static imports, thus being more
discoverable and convenient.
Issue: SPR-16953
Polish a few issue identified when adding checkstyle to the
build. Although checkstyle is not enforcing rules on tests,
these are a few minor changes that are still worth making.
Issue: SPR-16968
Reorganize imports to ensure consistent ordering. This commit also
expands any `.*` static imports in favor of using fully-qualified
method references.
Issue: SPR-16968
Update all classes so that inner classes are always last. Also
ensure that utility classes are always final and have a private
constructor and make exceptions final whenever possible.
Issue: SPR-16968
In SPR-16892, the `EncoderHttpMessageWriter` has been improved to write
`"Content-Length"` HTTP response headers if the response body is of type
`Mono` (i.e. the actual content length is easily accessible without
buffering a possibly large response body). That change was relying on
the fact that the server side is using a `ChannelSendOperator` to delay
the writing of the body until the first signal is received.
This strategy is not effective on the client side, since no such channel
operator is used for `WebClient`. This commit improves
`EncoderHttpMessageWriter` and delays, for `Mono` HTTP message bodies
only, the writing of the body so that we can write the
`"Content-Length"` header information once we've got the body resolved.
Issue: SPR-16949
Prior to this commit, the generated POMs for Spring Framework modules
would contain unneeded/harmful information from the Spring Framework
build:
1. The BOM imports applied to each module by the dependency
management plugin, for example for Netty or Reactor Netty.
Spring should not export that opinion to its POMs.
2. The exclusion of "org.slf4:jcl-over-slf4j" from *all* dependencies,
which made the POMs much larger than necessary and suggested to
developers that they should exclude it as well when using all those
listed dependencies. In fact, only Apache Tiles currently brings that
transitively.
This commit removes that information from the POMs.
The dependencyManagement Gradle plugin is disabled for POM generation
and we manually resolve the dependency versions during the generation
phase.
The Gradle build is streamlined to exclude "org.slf4:jcl-over-slf4j"
only when necessary.
Issue: SPR-16893
The key in CachingResourceResolver now includes the "Accept-Encoding"
request header cleaned to exclude "*", "identity", and parameters, and
also sorted alphabetically.
For encoded resources the response now includes a response header with
"Vary: Accept-Encoding".
Issue: SPR-16381
The new EncodedResourceResolver is a generalized version of
GzipResourceResolver that can be configured to support different
content codings, by "br" and "gzip".
GzipResourceResolver is now deprecated.
Issue: SPR-16381
This commit makes it possible to pass attributes from the WebSession of
a handshake request to the WebSocketSession, by configuring a
Predicate<String> on HandshakeWebSocketService.
Issue: SPR-16212
This commit removes all places where forwarded headers are checked
implicitly, on an ad-hoc basis.
ForwardedHeaderFilter is expected to be used instead providing
centralized control over using or discarding such headers.
Issue: SPR-16668
This commit exposes the resource lookup function used by
`RouterFunctions.resources(String, Resource)`, so that it can be
composed upon.
Issue: SPR-16788
This commit introduces support for creating a new `ServerRequest` from
an existing instance. This is especially useful when filtering requests
in a HandlerFilterFunction.
Issue: SPR-16707
ServerSentEventHttpMessageReader had logic to split on new lines
and buffer until an empty new line (start of a new event). To account
for random data chunking, it later re-assembled the lines for each
event and split again on new lines. However bufferUntil was still
unreliable a chunk may contain nothing but a newline, which doesn't
necessarily mean an empty newline in the overall SSE stream.
This commit simplifies the above by delegating the splitting of the
stream along newlines to StringDecoder.
Issue: SPR-16744
This breaks the package dependency cycle between web.server/web.method and makes ServerErrorException more generally applicable. Includes deprecation of the plain reason constructor variant, in favor of providing a Method or MethodParameter context (which MatrixVariableMethodArgumentResolver does now).
Consistently return "*/*" if no media types were requested rather than
an empty list. Existing code has to check for both in any case to see
if nothing was requested.
Issue: SPR-16624
The web.server package is quite low-level and should not depend on web.bind in order to avoid a dependency cycle. Extracting the introspection of the ResponseStatus annotation into a WebFlux-level subclass resolves the cycle.
Issue: SPR-16567
After this commit the use of interval in tests is combined with
take(n).onBackpressureBuffer(n) to ensure emissions don't fail if the
fixed rate is exceeded (e.g. on slow CI server).
Tests that verify N number of items followed by verifyOnComplete()
should set the number of emissions to N.
Tests that verify N number of items followed by thenCancel() should
set the number of buffered to an arbitrary number greater than N.
This commit adds these 2 Vary headers in addition to the existing
Origin one to avoid caching of Access-Control-Request-Method and
Access-Control-Request-Headers headers which can be an issue
when allowed methods or headers are unbounded and only the
requested method or headers are returned in the response.
Issue: SPR-16413
The commit brings following changes:
- Move getDecodableMimeTypes() to AbstractJackson2Decoder
- Move getEncodableMimeTypes() to AbstractJackson2Encoder
- Add support for application/stream+x-jackson-smile
- Avoid streaming line separator when Smile encoder is used
- Use double null token in Jackson2Tokenizer to identify documents
Issue: SPR-16151
This commit checks the Etag/LastModified headers on the incoming
request, and sets a 304 Not Modified status with no body when they
match, by delegating to ServerWebExchange.checkNotModified.
Issue: SPR-16348
Use DataBufferUtils.compose instead of writeAggregator to combine
multiple data buffers into one, as the write aggregator would not work
when the initial data buffer did not have enough capacity to contain
all subsequent buffers.
Removed writeAggregator, as it is no longer needed.
Issue: SPR-16365
Clarify what PathPatternParser is used for which is CORS checks in the
very least. Some sub-classes will also use it for request mapping but
not all (e.g. RouterFunctionMapping). Hence the need to be more
explicit.
@EnableWebFlux bootstraps both annotated controllers and functional
endpoints, so we need to be more explicit about which parts of the
configuration apply to which.
Issue: SPR-16360
Since type erasure can be fixed only when using
ParameterizedTypeReference based Java methods, RestOperations and
WebFlux API documentation should be updated to specify which extensions
are subject to type erasure, and which are not.
Issue: SPR-16273
This allows us to confirm 0.7.3 fixes and run tests against the latest
ahead of an upgrade to Reactor Netty 0.8 snapshots.
The fix for #231 and #240 are confirmed but unfortunately test case for
With this commit, the default content-type defined by the
view (usually "text/html;charset=UTF-8" defined in AbstractView)
is used if any, when none is defined in the response headers.
Issue: SPR-16247
If the response is set and we can't change the status through
ServerHttpResponse any more, allow the error signal to propagate and
let the individual server adapters handle it. Ultimately that should
result in closing the connection.
On Servlet containers, we check one last time if the response is
committed (we may not have filled the buffer). If not then save
the exception as a request attribute, dispatch, and re-throw it on the
container thread.
On Undertow access the connection and close it.
On Netty just let the error through to Reactor Netty.
Issue: SPR-16051
From #9a894a we began using the content-type from the ResponseEntity
but cross-checking it still against the requested content type.
Arguably there isn't any purpose in cross-checking. The only possible
outcomes are: a) it's compatible or b) it's not, which would result in
406 (NOT_ACCEPTABLE). As we've been given explicitly the media type to
use, it makes little sense to send 406, ignoring the wish to use that
content type.
Issue: SPR-16251
Before this commit, the return value from write was interpreted as the
data being fully written and ready to be released via releaseData().
This is not true for WebSocketSession implementations where a true
return value simply means the message was sent with the full payload
but releas is not appropriate until a send confirmation.
Technically not an issue since WebSocketSession's extending this do
not use pooled buffers. Nevertheless this commit refines the semantics
of write, removes the releaseData() method, and makes sub-classes
responsible for releasing the buffer when fully written (and they
know best when that is). As a bonus currentData is now private.
Issue: SPR-16207
After this commit, Tomcat and Undertow WebSocketSession imlpementations
start out in suspended mode and wait for demand.
The JettyWebSocketSession is capable of suspending but it doesn't seem
to work if invoked before any messages are received. That may become an
issue if there is a case where no demand appears long enough for more
messages to accumulate than we can hold.
UnderowServerHttpRequest would ideally also start in suspended mode but
that also doesn't work. It is not an issue in this case since we can
ignore the read notifications.
Servlet API requires a proactive check before it calls you back so
there is no need to suspend.
Issue: SPR-16207
This commit turns suspendReading() into a readingPaused() notification
that is invoked after a succession of reads stops because there is no
more demand. Sub-classes can use this notification to suspend, if that
applies to them.
Most importantly the notification is guaranteed not to overlap with
checkOnDataAvailable() which means that suspend does not need to be
atomic and guarded against resume. The two can and do compete all the
time when reading ends with no demand, and a request for demand arrives
concurrently.
Issue: SPR-16207
Access-Control-Allow-Credentials CORS header, used to
allow cookies with CORS requests, is not set to true
anymore by default when enabling CORS with
@CrossOrigin or global CORS configuration in order to
provide a more secured default CORS configuration.
The related allowCredentials property now requires to
be set to true explicitly in order to support cookies
with CORS requests.
Issue: SPR-16130
This commit adds
AbstractMessageReaderArgumentResolver#readBody and
AbstractMessageWriterResultHandler#writeBody variants
which allow to pass the actual MethodParameter in order
to perform proper annotation-based hint resolution with
nested generics, for example with HttpEntity.
Issue: SPR-16098
Practically no changes to RxNetty for a year and efforts underway to
rebuild 0.6.x based on a current Reactor Netty base.
Aside from the extra time to run integration tests having two
Netty-based servers can also cause false alarms such as ByteBuf leaks
related to RxNetty.
This commit introduces a new AbstractReactiveWebInitializer in
spring-web that relies on WebHttpHandlerBuilder to detect request
processing infrastructure beans from an ApplicationContext.
This eliminates the need to create a DispatcherHandler, since it is
expected to be a Spring bean, and as a result the initializers in
spring-webflux have been deprecated.
Issue: SPR-16144
FromHttpMessageWriter and MultipartHttpMessageWriter both support
MultiValueMap except the former supports String values only. This
presents an issue since either full generic type information must be
provided, which is cumbersome on the client side, or if left out there
is no good way to order the writers to make a proper decision.
This commit:
- refines the canWrite behavior of to not a
accept MultiValueMap without proper generic information unless the
MediaType is explicitly set providing a strong hint.
- modifies MultipartHttpMessageWriter to be configured with a
FormHttpMessageWriter so it can write both plan and multipart data with
the ability to properly differentiate based on actual map values.
Issue: SPR-16131
This commit exposes the ClientRequest's URL and HttpMethod fields via a
setter, so that they can be changed more easily in a request that was
created via ClientRequest.from(ClientRequest).
Issue: SPR-16093
Before this commit, when adding filters to a builder obtained via
`WebClient.mutate()`, the filters were added both to the original client
as well as the mutated builder. This commit fixes that.
Issue: SPR-16059
Prior to this commit, the `ResourceWebHandler` would itself handle the
response with an HTTP 404 in many cases, including a missing static
resource.
This does not give a chance to `WebExceptionHandler` instances to handle
that error and, for example, display an error page.
See spring-projects/spring-boot#8625
Issue: SPR-16023
Concrete server and client, reactive request and response
implementations should not have to be accessed outside their package.
They could be seen as private to their HttpHandler adapters and
ClientHttpConnector's respectively.
The one exception, WebSocket upgrades in spring-webflux, is an internal
framework use case, accommodated via downcast + accessors in the
abstract base classes.
Prior to this commit, the `WebClient` always throws a `ClassCastException`
when an error occurs in `bodyToMono(ParameterizedTypeReference)``, and
not the expected exception, as set up by `onStatus`
Issue: SPR-16025
Prior to this commit, asking for a `Void` type using any of the
`ClientResponse#bodyTo*` methods would immediately return an empty
`Publisher` without consuming the response body.
Not doing so can lead to HTTP connection pool inconsistencies and/or
memory leaks, since:
* a connection that still has a response body being written to it cannot
be properly recycled in the connection pool
* incoming `DataBuffer` might not be released
This commit detects when `Void` types are asked as body types and in
those cases does the following:
1. Subscribe to the response body `Publisher` to allow the connection to
be returned to the connection pool
2. `cancel()` the body `Publisher` if the response body is not empty; in
that case, we choose to close the connection vs. consume the whole
response body
Those changes imply that `ClientHttpResponse` and other related
contracts don't need a `close()` method anymore.
Issue: SPR-16018
Includes unified detection of Kotlin's optional parameters in MethodParameter.isOptional(), reduces BeanUtils.findPrimaryConstructor to Kotlin semantics (for reuse in AutowiredAnnotationBeanPostProcessor), and finally introduces a common KotlinDetector delegate with an isKotlinType(Class) check.
Issue: SPR-15877
Issue: SPR-16020
Prior to this issue, SPR-15920 added this new `close()` method which was
supposed to be called to clean resources after response processing.
This commit changes the meaning of that method: calling `close()` will
close the underlying HTTP connection. This has to be called if the
response body is not consumed by the application, since at that point
the underlying connection might be in an inconsistent state if shared in
a connection pool.
Issue: SPR-15993
This commit moves WebFluxUriComponentsBuilder.fromServerRequest to the
ServerRequest interface itself.
Consequently, the WebFluxUriComponentsBuilder is removes itself, as it
contained no other methods.
Issue: SPR-15953
The typical way to load DispatcherHandler is to use
WebHttpHandlerBuilder#applicationContext which also detecs filters,
exception handlers, as well as other beans that are injected into every
ServerWebExchange -- custom session manager, localecontext resolver,
codecs for form data, multipart data, etc
WebHttpHandlerBuilder is the preferred and way so removing the ones on
DispatcherHandler. They could always be added back later.
This commit introduces a visitor for router functions
(RouterFunctions.Visitor), allowing to iterate over all the components
that make up a router function.
This commit also introduces a ToStringVisitor, which creates a nicely
formatted string for use with toString().
Issue: SPR-15711, SPR-15711
This commit introduces the WebFluxUriComponentsBuilder, with a single
method that creates a UriComponentsBuilder for a ServerRequest. More
methods to be added by @rstoyanchev.
Issue: SPR-15953
This commit introduces a methodName() method to the ServerRequest,
returning the String name of the method. This method is useful for
non-standard HTTP methods.
This commit introduces the following changes.
1) It adds a new Spring @NonNull annotation which allows to apply
@NonNullApi semantic on a specific element, like @Nullable does.
Combined with @Nullable, it allows partial null-safety support when
package granularity is too broad.
2) @Nullable and @NonNull can apply to ElementType.TYPE_USE in order
to be used on generic type arguments (SPR-15942).
3) Annotations does not apply to ElementType.TYPE_PARAMETER anymore
since it is not supported yet (applicability for such use case is
controversial and need to be discussed).
4) @NonNullApi does not apply to ElementType.FIELD anymore since in a
lot of use cases (private, protected) it is not part for the public API
+ its usage should remain opt-in. A dedicated @NonNullFields annotation
has been added in order to set fields default to non-nullable.
5) Updated Javadoc and reference documentation.
Issue: SPR-15756
This commit fixes a typo in the `DefaultWebClient` implementation.
Instead of forwarding resolved `WebClientException` instances as error
signals, the `bodyToMono(ParameterizedTypeReference)` variant would just
forward those exceptions as `onNext` signals.
Issue: SPR-15946
Prior to that commit, the `ResponseSpec` `WebClient` would process error
responses (4xx, 5xx HTTP status) and transform those into error signals
with a `WebClientResponseException`. But this would only work if the
HTTP response would have a non-empty response body.
An empty error response would not send an error signal and only
translate in an `onComplete` signal.
This commit fixes this behavior and makes sure that this error signal is
sent in all cases.
Issue: SPR-15946
Before this commit, there was no way to signal the HTTP client that we
were done consuming the response. Without that, the underlying client
library cannot know when it is safe to release the associated resources
(e.g. the HTTP connection).
This commit adds new `close()` methods on both `ClientHttpResponse`
and `ClientResponse`. This methods is non-blocking and its behavior
depends on the library, its configuration, HTTP version, etc.
At the `WebClient` level, `close()` is called automatically if we
consume the response body through the `ResponseSpec` or the
`ClientResponse` itself.
Note that it is *required* to call `close()` manually otherwise; not
doing so might create resource leaks or connection issues.
Issue: SPR-15920
This commit moves `encodeUrl` and `registerUrlEncoder` from
ServerHttpResponse to ServerWebExchange.
It also renames `encodeUrl` to `transformUrl` and `registerUrlEncoder`
to `addUrlTransformer` to make it clearer that these methods do not
perform actual URL encodings (i.e. they do not replaceinvalid
characters).
The `add` prefix (instead of `register`) makes it clearer that each
function is added in addition to the previous one.
Issue: SPR-15924
This commit applies the Dependency Management Plugin to modules that
require it; right now Spring Framework is importing BOMs for Netty and
Reactor dependencies only.
Instead of applying those BOMs to all modules, they're applied only
where they're needed.
Issue: SPR-15885
The main `build.gradle` file contains now only the common build
infrastructure; all module-specific build configurations have
been moved to their own build file.
Issue: SPR-15885
The PathPattern compareTo method is now consistent with equals when
two patterns are of the same specificity but otherwise different.
Separately PathPattern now exposes a Comparator by specificity that
offers the current functionality of compareTo. This can be used for
actual sorting where we only care about specificity.
Consistent behavior with matches(PathContainer), the two had slightly
different logic for handling of empty paths.
Make matchAndExtract independantly usable without the need to call
matches(PathContainer) first. Essentially no longer raising ISE if the
pattern doesn't match but simply returning null.
Rename getPathRemaining to matchStartOfPath since the method does
match and to be more clear about what the method and the return value
intuitively follows.
Remove matchStart which matches the start of the pattern (rather than
the start of the path). It is a use case that does not come up in
request mapping.
This commit changes the WebClient so that it now throws a
`WebClientResponseException` for `ResponseSpec.bodyTo`. This newly
introduces exception contains the status code, headers, and body of the
response message.
As a consequence of the above, we had to change `onStatus` so that the
`exceptionFunction` now returns a `Mono<Throwable>` rather than a
`Throwable`, which it was before. The Mono allows for asynchronous
operations, such as reading the contents of the body.
Issue: SPR-15824
Removed superfluous `fromServerSentEvent` variants from `BodyInserters`,
as their functionality can also be obtained by passing a stream of
strings or POJOs (to be encoded as JSON) to
`fromPublisher(Publisher, Class)}`, and specifying a `text/event-stream`
Content-Type.
Issue: SPR-15826
This commit also removes WebFlux non-extension functions in favor of
regular Kotlin extensions leveraging ParameterizedTypeReference parameter.
Issue: SPR-15818
This commit changes the usage of two separate attributes (username and
password) into one: a single `Credentials` object.
Additionally, the attributes key under which the credentials are stored
is changed to be specific to Basic Authentication, in order to allow for
other sorts of authentication later.
Issue: SPR-15764
This commit changes adds overloaded `ParameterizedTypeReference `
variants to body-related methods in `ServerRequest` and
`ServerResponse`.
It also adds a single PTR variant to ClientRequest, which was missing
before.
Issue: SPR-15817
This commit changes all consumers of CodecConfigurer to consume a `List`
of HttpMessageReaders or HttpMessageWriters instead of consuming the
Server- or ClientCodecConfigurer directly.
Issue: SPR-15816
This commit ensure that null-safety is consistent between
getters and setters in order to be able to provide beans
with properties with a common type when type safety is
taken in account like with Kotlin.
It also add a few missing property level @Nullable
annotations.
Issue: SPR-15792
Since there is no reason for an exchange to ever complete without a
ClientResponse I've added a switchIfEmpty check at the WebClient level.
Also, temporarily a second check closer to the problem in the
ReactorClientHttpConnector suggesting a workaround and providing a
reference to the Reactor Netty issue #138.
Issue: SPR-15784
Collapse the base interface VersionPathStrategy into its extension
VersionStrategy and then turn the prefix nad fliename based
implementations into abstract base classes (vs delegate strategies).
It is simpler to have one VersionStrategy hierarchy vs that plus a
separate VersionPathStrategy as a delegate. In practice each
VersionStrategy is suited to be prefix or filename based. Also none
of our code cares about the distinction between those two interfaces.
Since `PathPattern.combine` now returns another `PathPattern` instance
(it was previously returning a String instance), we can now safely
remove the parser instance included in `PatternsRequestCondition`.
Issue: SPR-15663
Use copy constructor to refresh a session with lastAccessTime and a
save function referencing the current exchange. As a result both fields
are now final and ConfigurableWebSession is no longer needed.
This commit introduces overloaded variants of `bodytoMono`,
`bodyToFlux`, `toEntity`, and `toEntityList` that take a
`ParameterizedTypeReference`. It also adds similar methods to
`WebClient.ResponseSpec`.
Issue: SPR-15725
This binary format more efficient than JSON should be useful for server
to server communication, for example in micro-services use cases.
Issue: SPR-15424
This commit introduces an apply method to `WebClient.Builder`, allowing
users to make multiple changes to the builder in one consumer.
Issue: SPR-15743
The failures look like older failures possibly exposed by recent
changes in Reactor.
The one in ViewResolutionResultHandler is very old test error.
The one in Jackson2JsonDecoderTests is more recent but went unreported.
This commit moves `toEntity(Class<T>)` and `toEntityList(Class<T>)`
from WebClient.ResponseSpec to ClientResponse. The main reason for doing
so is that the newly introduced `onStatus` method (see
2f9bd6e075) does not apply to these two
methods, and the result would be confusing. Also, `ClientResponse` and
`ResponseEntity` represent the same data: status code, headers, and a
body.
Issue: SPR-15724
This commit introduces a way to customize the WebClientExceptions, as
thrown by WebClient.ResponseSpec.bodyTo[Mono|Flux]. The first
customization will override the defaults, additional customizations are
simply tried in order.
Issue: SPR-15724
This commit changes `ServerRequest.attribute(String)`` to return
`Optional<Object>` instead of `Optional<T>`, where `T` was infered
from a type parameter.
This commit makes the `uri` step of the WebClient optional, so that
users who have specified a base URL during WebClient config do not need
to provide an empty one (i.e. `url("")`).
The basic idea of this fix is that the HTTP method methods in WebClient
(`get`, `post`, etc.) should be able to "bypass" the uri stage, and skip
straight to defining headers, or even doing an exchange or retrieve
(i.e. call methods on `RequestHeaderSpec` or `RequestBodySpec`).
I have accomplished this by adding two new composed interfaces:
`RequestHeadersUriSpec` and `RequestBodyUriSpec`.
`RequestHeadersUriSpec` extends from the existing `UriSpec` and
`RequestHeaderSpec`, while `RequestBodyUriSpec` extends from `UriSpec`
and `RequestBodySpec`. These types are returned from the HTTP methods
(`get`, `post` etc). The `uri` methods on these types return a plain
`RequestHeaderSpec` and `RequestBodySpec` (i.e. types without the `uri`
methods), so that you can call `uri` once only.
Issue: SPR-15695
Explicitly pass the client-side JSR-356 WebSocketContainer to the
TomcatWebSocketClient to prevent the ContainerProvider from finding
the one from undertow-websockets-jsr through the ServiceLoader API.
This commit disables the "failOnServerError" feature on the
`HttpClientRequest`, as wrapped by ReactorClientHttpRequest. 5xx errors
are supposed to be dealt with in the WebClient, not in the lower-level
components.
Issue: SPR-15739
This commit introduces client-side request attributes, similar to those
found on the server-side. The attributes can be used, for instance, for
passing on request-specific information to a globally registered
ExchangeFilterFunction.
The client request builder, as well as WebClient.RequestHeadersSpec and
WebTestClient.RequestHeaderSpec, add methods for adding a single
attribute, as well as manipulating the entire attributes map.
The client request itself adds a accessor for the (immutable) attributes
map.
This commit also introduces a new variant of the basic authentication
filter in ExchangeFilterFunctions. This variant takes the username and
password from well-known attributes.
Issue: SPR-15691
Previously `UrlBasedCorsConfigurationSource` was relying on
`PathMatcher` implementations for matching incoming request lookup paths
with the configured path patterns for CORS configuration.
This commit replaces the use of `PathMatcher` with a `PathPatternParser`
that parses the string patterns into `PathPattenr` instances and allows
for faster matching against lookup paths.
Issue: SPR-15688
This commit changes ServerRequest.queryParams from returning a
List<String> given a String name, to returning a
MultiValueMap<String, String>, which gives more flexibility.
This commit uses the newly introduced `PathContainer` and `RequestPath`
support in the functional web framework. It exposes the path container
as property in `ServerRequest`, and uses that in the path-based
`RequestPredicates`.
Direct comparison of a pattern (as a String) to the path does not make
much sense now that we deal with URL encoding through PathContainer
which exposes (safely) decoded path segments.
Removing the PathPatternComparator also means we can keep patterns
pre-sorted instead of sorting them all the time. That probably offsets
any benefits from comparing to the lookup path for direct matches and
patterns are still sorted according to specificity.
This commits extends nullability declarations to the field level, formalizing the interaction between methods and their underlying fields and therefore avoiding any nullability mismatch.
Issue: SPR-15720
This commit adds a new `cloneBuilder()` method on `WebClient.Builder`;
we can now reuse the customizations of an existing builder without
sharing its state across several `WebClient` building code paths.
Issue: SPR-15690
This commit introduces 2 new public methods in HttpHeaders in order
to leverage Java 8 ZonedDateTime in addition to the existing long
(with GMT time zone implied) variants:
- ZonedDateTime getFirstZonedDateTime(String headerName)
- void setZonedDateTime(String headerName, ZonedDateTime date)
This commit also leverages Java 8 thread-safe DateTimeFormatter for
HttpHeader implementation instead of SimpleDateFormat. As a consequence
of the usage of DateTimeFormatter.RFC_1123_DATE_TIME, HTTP date header
serialization could change slightly for single digit days from for
example "Thu, 01 Jan 1970 00:00:00 GMT" to
"Thu, 1 Jan 1970 00:00:00 GMT".
Issue: SPR-15661
This commit adds support for Void response body types in the WebClient,
both when using `exchange` with a response.bodyToMono(Void.class), as
well as using `retrieve` with `toEntity(Void.class)`.
Issue: SPR-15679
This commit replaces the WebClient.filter method with
WebClient.Builder.filter. The reason for this change is that filters
added via WebClient.filter would be applied in the opposite order of
their declaration, due to the compositional nature of the method,
combined with the immutable nature of the WebClient.
WebClient.Builder.filter does keep the order of the filters, as
registered.
Furthermore, this commit introduces a WebClient.mutate() method,
returning a WebClient.Builder. This method allow to add/remove filters
and other defaults from a given WebClient.
Issue: SPR-15657
Add WebClient.Builder.addFilter
Add Consumer-based headers and cookies methods to builders.
Add WebClient.mutate
This commit changes the `ExchangeStrategies` and `HandlerStrategies`
interfaces to consistently use the `CodecConfigurer` (and
sub-interfaces) for configuring codecs on the server and on the client.
Issue: SPR-15682
Supporting ScriptEngine#eval(String, Bindings) when no render function
is specified allows to support use cases where script templates are
simply evaluating a script expression with an even more simplified
configuration.
This improvement also makes it possible to use script engines that
do not implement Invocable.
Issue: SPR-15115
This commit introduces LocaleContextResolver interface, which is used
at ServerWebExchange level to resolve Locale, TimeZone and other i18n
related informations.
It follows Spring MVC locale resolution patterns with a few differences:
- Only LocaleContextResolver is supported since LocaleResolver is less
flexible
- Support is implemented in the org.springframework.web.server.i18n
package of spring-web module rather than in spring-webflux in order
to be able to leverage it at ServerWebExchange level
2 implementations are provided:
- FixedLocaleContextResolver
- AcceptHeaderLocaleContextResolver
It can be configured with both functional or annotation-based APIs.
Issue: SPR-15036
Previously `HandlerMapping` implementation were heavily relying on
`String` path patterns, `PathMatcher` implementations and dedicated maps
for matching incoming request URL to an actual request handler.
This commit adds the `PathPatternRegistry` that holds `PathPattern`
instances and the associated request handler — matching results are then
shared as `PathMatchResult` instances. `AbstractUrlHandlerMapping` will
use this registry directly, but other components dealing with request
matching (like `PatternsRequestCondition`) will directly use ordered
`PathPattern` collections since ordering is important there.
This opens the door for faster request matching and simplifies the
design of this part.
Issue: SPR-15608
This commit removes the headers(HttpHeaders) method on ClientRequest and
ServerResponse, in favor of headers(Consumer<HttpHeaders>), which is
more flexible.
The revised builder emphasizes creating a list of resolvers either
built-in or custom with each top-level builder method resulting in
adding a resolver.
By default only the Header resolver is configured.
The path extension resolver is removed altogether to discourage its use
but is trivial to create manually with the helpf of
UriUtils#extractFileExtension + MediaTypeFactory.
Issue: SPR-15639
After the removal of suffix pattern matches, there is no longer a need
to expose the list of registered file extensions.
Also polish, refactor, and simplify the abstract base class
AbstractMappingContentTypeResolver and its sub-classes.
Issue: SPR-15639
There is no need for ResourceWebHandler to go through the
PathExtensionContentTypeResolver when MediaTypeFactory makes it easy to
perform such lookups for a given Resource.
This does not support any extensions explicitly registered through a
WebFluxConfigurer but it would be easy enough to pass those into
ResourceWebHandler as a simple Map<String, MediaType>, should the need
arise.
Issue: SPR-15639
The use of the undecoded URL path by default and the removal of suffix
pattern matching effectively means HttpRequestPathHelper is no longer
needed.
Issue: SPR-15640, SPR-15639
Introduce pathWithinApplication() in ServerHttpRequest and use it for
request mapping purposes instead of LookupPath.
In turn this means that for request mapping purposes:
1) the path is not decoded
2) suffix pattern matching is not supported
Issue: SPR-15640
This commit changes the use of `ResolvableType` to
`ParameterizedTypeReference` in all public-facing WebFlux APIs. This
change removes the necessity for providing the parameterized type
information twice: once for creating the `ResolvableType`, and once for
specifying a `BodyExtractor`.
Issue: SPR-15636
This commit also removes nullability from two common spots: ResolvableType.getType() and TargetSource.getTarget(), both of which are never effectively null with any regular implementation. For such scenarios, a non-null empty type/target is the cleaner contract.
Issue: SPR-15540
This commit adds two Consumer based methods to ClientRequest that allow
for direct manipulation of the underlying headers or cookies map. As
such, these methods can be used to override or remove existing entries.
Issue: SPR-15635
This commit changes the `headers(HttpHeaders)` method in
DefaultClientRequestBuilder so that it copies the individual header
values instead of using the `List<String>` value directly. The reason
for this change is that the list of values can be immutable, and adding
additional values after that could result in
UnsupportedOperationExceptions.
Beyond just formally declaring the current behavior, this revision actually enforces non-null behavior in selected signatures now, not tolerating null values anymore when not explicitly documented. It also changes some utility methods with historic null-in/null-out tolerance towards enforced non-null return values, making them a proper citizen in non-null assignments.
Some issues are left as to-do: in particular a thorough revision of spring-test, and a few tests with unclear failures (ignored as "TODO: NULLABLE") to be sorted out in a follow-up commit.
Issue: SPR-15540
Restore matrix variable parsing code not resorting to the use of
WebUtils which brings Servlet API dependencies with it.
Instead the parsing logic is now exposed through HttpRequestPathHelper
which already contained the decoding logic and also the knowledge of
whether to decode the parsed variables or not.
Issue: SPR-15397
This commit adds the `LookupPath` class that contains the full
request path relative to the web context; the application can
get from it various information, including the file extension
and path parameters (if any).
Since that operation is done multiple times for each request, this
object is stored as an attribute at the `ServerWebExchange` level.
Issue: SPR-15397
With the new `ParsingPathMatcher` implementation, new patterns are now
allowed, such as `"/foo/{*bar}". The `"{*bar}"` segment will capture
everything until the end of the given path. Adding other elements after
that segment is illegal and will throw exceptions.
One can configure on a `PathMatchConfigurer` various options like
`useTrailingSlashMatch` and `useSuffixPatternMatch`; those options, when
enabled, will try to append suffixes like `".*"` and `"/"` to existing
path patterns. In case of a "capture the rest" pattern segment, those
options won't be honored.
This is why this commit ensures that an exception is thrown at the start
of the application if an illegal configuration is applied to the
`PathMatchConfigurer`.
Issue: SPR-15303, SPR-15558
This commit introduces 2 new @Nullable and @NonNullApi
annotations that leverage JSR 305 (dormant but available via
Findbugs jsr305 dependency and already used by libraries
like OkHttp) meta-annotations to specify explicitly
null-safety of Spring Framework parameters and return values.
In order to avoid adding too much annotations, the
default is set at package level with @NonNullApi and
@Nullable annotations are added when needed at parameter or
return value level. These annotations are intended to be used
on Spring Framework itself but also by other Spring projects.
@Nullable annotations have been introduced based on Javadoc
and search of patterns like "return null;". It is expected that
nullability of Spring Framework API will be polished with
complementary commits.
In practice, this will make the whole Spring Framework API
null-safe for Kotlin projects (when KT-10942 will be fixed)
since Kotlin will be able to leverage these annotations to
know if a parameter or a return value is nullable or not. But
this is also useful for Java developers as well since IntelliJ
IDEA, for example, also understands these annotations to
generate warnings when unsafe nullable usages are detected.
Issue: SPR-15540
This commit changes all methods that return `Supplier<Stream<T>` to
return `List<T>` instead. This includes the HandlerStrategies, but also
BodyInserter.Context, BodyExtractor.Context, and ServerResponse.Context.
The reason for this change is that most of the strategies have some sort
of order, where more specific message readers - for instance - come
before generic ones. Such an ordering can only be enforced through a
List.
Issue: SPR-15578
This commit removes the RouterFunctions.toHandlerMapping method, in
favor of native support for RouterFunctions in @EnableWebFlux
configuration classes.
In order to accomplish this, the HandlerStrategies components has been
repurposed to only be used for the "bare-bones" HttpHandler, while the
(newly introduced) RouterFunctionMapping uses the strategies as exposed
through WebFluxConfigurationSupport.
Furthermore, this commit also introduces support for testing
RouterFunctions without resorting to an application context.
Issue: SPR-15536
This commit adds support for configuring `WebFilter` and
`WebExceptionHandler` instances in HandlerStrategies. It also drops the
"native" support for `ResponseStatusException`s, in favor of the
`ResponseStatusExceptionHandler`, which is registered by default.
Issue: SPR-15518
The ResourceHandlerFunction now returns an `EntityResponse<Resource>`
(instead of a `ServerResponse`), so that filters can inspect/change the
returned Resource.
Starting with removing a package cycle on the use of
ResponseStatusException in the codec package, this commit generally
refines codec exception handling.
The new [Encoding|Decoding]Exception mirror the existing
HttpMessageNot[Readable|Writable]Exception and are used similarly
especially to differentiate betwen 400 and 500 errors when parsing
server request body content.
The commit also aligns some of the exception handling of JSON and XML
on the WebFlux side with that on the Spring MVC side.
Issue: SPR-15516
This commit turns the Synchronoss NIO Multipart HttpMessageReader into
a reader of Flux<Part> and creates a separate reader that aggregates
the parts into a MultiValueMap<String, Part>.
Issue: SPR-14546