This commit moves the ResolvableType field from HttpEntity to
PublisherEntity, a new entity type defined in MultipartBodyBuilder.
With this change, the scope of the ResolvableType is limited to
multipart-related code, instead of becoming part of the complete
HttpEntity hierarchy.
Issue: SPR-16307
This commit adds a ResolvableType field to HttpEntity, in order to
support Publishers as multipart data. Without the type, the
MultipartHttpMessageWriter does not know which delegate writer to use to
write the part.
Issue: SPR-16307
This commit allows CorsConfiguration#combine()
to differentiate permit default values set by
CorsConfiguration#applyPermitDefaultValues()
from values configured explicitly by the user.
Those permit default values will be overridden
by any user-provided ones while user-provided values
will be combined in an additive way, including
when "*" is specified.
Documentation has been improved accordingly.
Issue: SPR-15772
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
Provide a fully mutable HttpHeaders to ClientHttpRequestInterceptors
of a RestTemplate when headers are set using HttpEntity. This avoids
UnsupportedOperationException if both HttpEntity and
ClientHttpRequestInterceptor add values for the same HTTP header.
Issue: SPR-15066
The request URI returned from HttpServerRequest.uri() typically
contains contains an absolute path but could also contain an
absolute URI. This commit adds handling for the latter, effectively
taking only the absolute path portion.
Issue: SPR-16243
ResponseStatusExceptionHandler lets the error through if it can't
change the status while HttpWebHandlerAdapter logs a more helpful
message (including status code) but without a full stack trace.
Issue: SPR-16231
1. setComplete checks the isCommitted flag to avoid an unnecessary
debug message. This method is meant to be safe to call many times.
2. setStatusCode lowers log message to TRACE, since the return value
communicates the outcome it's arguably much less critical.
3. Add comment and test case for ResponseStatusExceptionHandler.
A ResponseStatusException is clearly meant to be handled by this
handler so don't let it pass through even if the respones is
committed.
Issue: SPR-16231
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
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
Transition from DEMAND->NO_DEMAND:
Two concurrent threads enter DEMAND.request and DEMAND.onDataAvailable.
And DEMAND.onDataAvailable finishes before DEMAND.request to be able to
update the demand field then a request for reading will be lost.
Transition from READING->NO_DEMAND:
readAndPublish() returns false because there is no demand but before
switching the states READING.request is invoked again a request for
reading will be lost.
Changing READING->DEMAND/NO_DEMAND is made conditional so that the
operations will be executed only if changing states succeeds.
When in READING state detect completion before each next item in order
to exit sooner, if completed.
Issue: SPR-16207
- Ensure completion signal (normal/exception) will be delivered to
the subscriber when transition from UNSUBSCRIBED->COMPLETED
- According to the specification "Publisher.subscribe MUST call onSubscribe
on the provided Subscriber prior to any other signals to that Subscriber" so
ensure onComplete/onError signals will be called AFTER onSubscribe signal.
Issue: SPR-16207
This commit changes the implementation of the PathPattern
extractPathWithinPattern method that used an old AntPathMatcher
derivative to a new version that integrates more closely with
PathContainer.
It also introduces consistency in a couple of areas. The javadoc
is updated to specify this but basically:
- the response from the extra method will have all leading
and trailing separators removed.
- the response will have multiple adjacent separators within the
reponse reduced to just one. (For example response would be
aaa/bb/cc and not aaa///bbb//cc)
If your response would start or finish with multiple separators, they
are all removed.
Issue: SPR-16120
- When there is no demand for reading, the implementation
should suspend reading otherwise useless events will be
send by Undertow to the registered read listener.
- There is not need to wait for an event for reading/writing after calling
resumeReads/resumeWrites
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.
Also remove ErrorDeferredResultProcessingInterceptor which was meant
to be package private to begin with as its peer
ErrorCallableProcessingInterceptor (also removed).
Includes fixes for invalid exception declarations in Mockito-based unit tests. Also includes FreeMarker 2.3.27, Commons Pool 2.4.3, JSON-P 1.1.2.
Issue: SPR-16157
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
The RFCs around basic authentication don't explicitly disallow empty
usernames. On the other hand usernames containing colons are, as colons
are used to separate the username from the password.
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 changes the way Undertow's PooledByteBuffers are dealt with.
Previously, these buffers where closed as soon as all data was read. As
of this commit, the UndertowServerHttpRequest returns PooledDataBuffers
from getBody(), so that the buffers are released when release() is
called.
This commit introduces various improvements in DataBuffer:
- DataBuffer now exposes its read and write position, as well as its
capacity and writable byte count.
- Added DataBuffer.asByteBuffer(int, int)
- DataBufferUtils.read now reads directly into a DataBuffer, rather than
copying a ByteBuffer into a DataBuffer
- TomcatHttpHandler now reads directly into a DataBuffer
Issues: SPR-16068 SPR-16070
Includes redeclaration of CodecConfigurer.DefaultCodecs without concrete Jackson decoder/encoder references in order to avoid hard Jackson dependency.
Issue: SPR-16064
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, 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
Now that WebSessionStore is in charge of expiration checks on retrieve
it makes sense to also update the lastAccessTime on retrieve at the
same time, saving the need to call it after a retrieve.
Issue: SPR-15963
It is no longer adequate to list supported arguments and return values
-- between Web MVC and WebFlux, directly on the annotation.
Instead we have tables in the respective chapters in the reference with
cross references to each other.
Issue: SPR-15149
This commit makes Reactor Netty `WebClient` instances
support zero-copy requests by implementing `ZeroCopyHttpOutputMessage`.
The implementation leverages the optimized `sendFile` mechanism if
available.
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
When writing Publisher<Publisher<T>>, a flush operation is performed onComplete
for every Publisher. If the flush operation is not able to be performed immediately
it will be retried before starting to process data provided by the next Publisher.
For the last Publisher the implementation needs to ensure that the flush will
be performed only then whole operation will complete.
Issue: SPR-15949
This commit introduces a ForwardedHeaderFilter for WebFlux, similar to
the existing Servlet version. As part of this the
DefaultServerHttpRequestBuilder had to be changed to no longer use
delegation, but instead use a deep copy at the point of mutate().
Otherwise, headers could not be removed.
Issue: SPR-15954
Now that https://github.com/reactor/reactor-netty/issues/138 is solved,
this commit removes the temporary workaround introduced in SPR-15784
but leaves the general mechanism for detecting empty responses.
The high level matchStarting API was removed a few commits ago.
This change tidies up by removing the supporting infrastructure
for that from the PathElements.
InMemoryWebSessionStore is very closely associated to DefaultWebSession
passing it to it several fields and functions. Now that the store also
creates the session, it makes sense to bring the latter in as an inner,
nested class.
Issue: SPR-15875, 15876
DefaultWebSessionManager no longer requires the WebSessionStore
to use DefaultWebSession.
Removed explicit start() in save(). This seemed unnecessary since at
that point isStarted is guaranteed to return true. The status can
be updated through the copy constructor.
DefaultWebSessionTests added.
Issue: SPR-15875
- Add WebSessionStore.createWebSession.
- Remove remove WebSessionStore.changeSessionId
- Add WebSessionStore updateLastAccessTime which allows updating the
WebSession lastAccessTime without exposing a method on WebSession in
an implementation independent way.
- Remove WebSessionStore.storeSession. This method is not necessary
since the WebSession that is returned allows saving the WebSession.
Additionally, it is error prone since the wrong type might be passed
into it.
Issue: SPR-15875, 15876
Add missing DefaultWebSessionManagerTests .block(). Previously
session.save() was invoked, but we did not ensure it was completed.
This commit makes it block on session.save()
Fix existingSessionIsExpired. This test is actually broken and is
testing a new session is created because the session id returned
by the idResolver does not match the existing WebSession.
This commit ensures that the id of the WebSession found by idResolver
matches the existing WebSession.
DefaultWebSessionManagerTests use Mockito. To ensure we test with
independence from InMemoryWebSessionStore we use Mockito for the
DefaultWebessionManager collaborators.
Add test for response.setComplete(). We want to ensure that when the
response is completed, it saves the WebSession and writes it to the
response using idResolver
Use constant for default header name and make getHeaderName private.
Also switch HeaderWebSessionIdResolverTests to unit tests rather than
testing with DefaultWebSessionManager.
Issue: SPR-15917
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
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