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
Introduces HeaderSessionIdResolver, which reads session ids from a session header and generates a session response header when new session are created.
Related issue: SPR-15917
`ReactorClientHttpConnector` provides an adapter layer to `WebClient`
for using Reactor-Netty's `HttpClient`.
This commit enables HTTP compression support by default for this client
Connector.
Another constructor is still available for providing a custom
`HttpOptions` configuration.
Issue: SPR-15908
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
Bean-derived null values may still get passed into bean properties and injection points but only if those are declared as non-required. Note that getBean will never return null; a manual bean.equals(null) / "null".equals(bean.toString()) check identifies expected null values now. This will only ever happen with custom FactoryBeans or factory methods returning null - and since all common cases are handled by autowiring or bean property values in bean definitions, there should be no need to ever manually check for such a null value received from getBean.
Issue: SPR-15829
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
Remove the separator constructor argument (but preserve internal
functionality) now that PathPatternParser is more explicitly purposed
for URL paths and in any case the use of an alternate separator would
also requires a similar input option on the PathContainer parsing side.
Re-arrange the checks so that if there is no form parameter, then
immediately and unconditionally delegate to super.getParameterValues().
Or reversely if there is no super.getParameterValues() then return the
form parameter.
So the only remaining case is when combining values present in both.
In that case we'll take both only if a queryString exists.
One extra fix is to not even wrap the request if we did not parse any
form parameters at all which can happen with HttpHiddenMethodFilter.
Issue: SPR-15828, 15835
This commit also removes WebFlux non-extension functions in favor of
regular Kotlin extensions leveraging ParameterizedTypeReference parameter.
Issue: SPR-15818
When the input stream is a JSON array the tokenizer skips over the
start and end array tokens in order to decode into an array of
top-level objects. However in this mode it also skips over nested
start and end array tokens which prevents proper parsing of JSR-310
dates (represented with an array syntax) as well as any fields that
are collections.
Issue: SPR-15803
The method was orginally added under SPR-14547 but the example in it
was probably intended for use with Content-Disposition server response
header (file dowonload) and not for a Content-Disposition header
within the body of a multipart request.
In a Spring application a multipart request is typically serialized
by the FormHttpMessageConverter and hence the Content-Disposition is
not explicitly set by the application.
Issue: SPR-15205
This commit parses the "Host" HTTP request header as an
`InetSocketAddress`, while supporting IPv6 addresses like `[::1]`.
This host string contains `:` chars even though it has no port
information.
Issue: SPR-15799
StandardMultipartHttpServletRequest now properly decodes RFC-5987
encoded filenames (i.e. filename*) by delegating to ContentDisposition
and also support RFC-2047 syntax through javax.mail MimeUtility.
Issue: SPR-15205
This commit updates BeanUtils class in order to add Kotlin optional
parameters with default values support to the immutable data classes
support introduced by SPR-15199.
Issue: SPR-15673
Prior to this commit, the host+port information of the incoming request
where taken from the remoteAddress, which is actually the socket address
of the HTTP client (i.e. not the server).
This commit resolves this information from the "Host" HTTP request
header, if available, or the actual local address of the channel if no
header is available.
Issue: SPR-15084
Add an option for ForwardedHeaderFilter to only process the
HttpServletRequest. This means that HttpServletResponse.sendRedirect will
only work when the application is conifgured to use relative redirects
using Servlet Container specific setup.
Issue: SPR-15717
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
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 binary format more efficient than JSON should be useful for server
to server communication, for example in micro-services use cases.
Issue: SPR-15424
Avoid re-using the WriteBarrier as the Subscription to both the
completionSubscriber and the writeSubscriber.
Instead DownstreamBridge is now called WriteCompletionBarrier and is
both a Subscriber and Subscription, i.e. handles all signals to and
from the completion Subscriber.
This frees the request method implementation in WriteBarrier to assume
it can only be called by the writeSubscriber and hence it's safe to
pass on request signals to the write source outside the synchronized
block.
This commit introduces a boolean `readOnly` flag in `HttpHeaders`,
which is used to check if creating a new `HttpHeaders` instance is
necessary in `readOnlyHttpHeaders`.
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.
WriteBarrier acts as Subscription to both completionSubscriber and
writeSubscriber so the request method needs to be careful not to
pass on the request outside of readyToWrite or writeSubscriber checks.
ContentNegotiationManagerFactoryBean now provides an option to
explicitly set the strategies to use vs customizing a fixed
list of default strategies.
Issue: SPR-11114
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
Segment.value() now returns the actual original path segment value
including path parameters while semicolonContent() is removed.
valueDecoded() is renamed to valueToMatch() to reflect it is the value
for pattern matching which is not only decoded but also has path
parameters removed.
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
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 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.
The new PathContainer represent the path as a series of elements
including separators. This naturally represents leading/trailing
slashes and empty path segments which in turn makes it easier to match
in PathPattern as well as to reconstruct the path.
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 changes the release of data buffers from a finally block
into a `doFinally()` lambda on the returned `Flux<XMLEvent>` stream.
Issue: SPR-15707
This commit introduces the Jackson2Tokenizer as a replacement for the
JsonObjectDecoder. The latter was dropped because of its complexity, and
hard dependency on Netty's ByteBuf.
The new Jackson2Tokenizer leverages the new non-blocking JSON parser,
using it to parse the incoming data buffers into TokenBuffers, each
token buffer representing one JSON object. As with JsonObjectDecoder,
it also supports streaming individual JSON array elements.
Issue: SPR-14528
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 new WebFilter implementation is designed to allow initial
CORS support when using WebFlux functional API. More high-level
API may be introduced later.
Issue: SPR-15567
Static parse methods on PathSegmentContainer and PathSegment plus:
isEmpty() on PathSegmentContainer and PathSegment
isAbsolute() and hasTrailingSlash() on PathSegmentContainer
char[] alternative for valueDecoded() on PathSegment
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 enables trailing slash matching in `PathPatternParser` by
default - this mirrors the default configuration in `PathMatcher`
implementations in MVC.
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
Before this commit there was no special handling for URL encoding
of the path pattern string coming into the path pattern parser. No
assumptions were made about it being in an encoded form or not.
With this change it is assumed incoming path patterns are not
encoded and as part of parsing the parser builds PathPattern
objects that include encoded elements. For example parsing "/f o"
will create a path pattern of the form "/f%20o". In this form
it can then be used to match against encoded paths.
Handling encoded characters is not trivial and has resulted in
some loss in matching speed but care has been taken to
avoid unnecessary creation of additional heap objects. When
matching variables the variable values are return in a
decoded form. It is hoped the speed can be recovered, at least
for the common case of non-encoded incoming paths.
Issue: SPR-15640
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
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
Without this change the comparator thinks "/{foo}"
is more specific than "/{foo}.*". The minimal fix here
to address it is to copy what the AntPathMatcher
comparator does which is to consider '.*' as *not*
a usage of a wildcard. See PatternInfo#initCounters()
for the AntPathMatcher handling of this.
This change ensures the PathPattern comparator now produces
the expected result but suffix usage in general needs more
thought at some point.
Issue: SPR-15597
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
When an exception happens while writing/flushing, the exception handling
for Servlet 3.1 based implementation will happen when
WriteListener#onError and AsyncListener#onError events are received
When reading more that once for a given request, the position/limit of
the buffer provided by Undertow should be reset in order to use the
full capacity of the buffer.
This commit fixes the implementation of
ExtractingResponseErrorHandler.hasError to allow for null values,
indicating an override of the behavior inherited from
DefaultResponseErrorHandler.
Issue: SPR-15544
This commit introduces ExtractingResponseErrorHandler: an alternative
ResponseErrorHandler that uses `HttpMessageConverter`s to convert HTTP
error responses to `RestClientException`.
Issue: SPR-15544
Simplify the internals of the DefaultCodecs implementation favoring
explicit fields per override vs a generic list of readers and writers
for overrides.
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 introduces a new method in HttpRequest:
`String getMethodValue`, which returns the HTTP method as a String.
Furthermore, HttpRequest.getMethod() has been given a default
implementation using this String value in combination with
`HttpMethod.resolve`.
Issue: SPR-15545
HttpMessageConverter's are client and server and arguably shouldn't
contain a server-side concept such a response status.
The status field is recent, it was added to differentiate 400 vs 500
errors with Jackson 2.9+ but there is no need for it since the same
distinction is reflected in raising an HttpMessageNotReadableException
vs a general HttpMessageConversionException.
Issue: SPR-15516
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 comment extends the use of the charset property in
FormHttpMessageConverter to also include multipart headers with a
default of UTF-8.
We now also set the charset parameter of the "Content-Type" header to
indicate to the server side how to decode correctly.
Issue: SPR-15205
The MultipartHttpMessageWriter now directly encodes part header values
defaulting to UTF-8 and also specifies the charset in the
Content-Type header for the entire request.
This should work with something commonly used like Apache Commons
FileUpload which checks request.getCharacterEncoding() and uses it
for reading headers.
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