This commit updates CORS support in order to check Origin header
in CorsUtils#isPreFlightRequest which does not change how Spring
MVC or WebFlux process CORS request but is more correct in term
of behavior since it is a public API potentially used in another
contexts.
It also removes an unnecessary check in
AbstractHandlerMethodMapping#hasCorsConfigurationSource and processes
every preflight request with PreFlightHandler.
Closes gh-24327
Prior to this commit, when WebFlux handlers added `"Content-*"` response
headers and an error happened while handling the request, all those
headers would not be cleared from the response before error handling.
This commit clears those headers from the response in two places:
* when invoking the handler and adapting the response
* when writing the response body
Not removing those headers might break HTTP clients since they're given
wrong information about how to interpret the HTTP response body: the
error response body might be very different from the original one.
Fixes gh-24238
Add a note on encoding for query parameters specifically mentioning the
"+" sign and a link to the reference docs.
Also remove duplicate Javadoc in UriComponentsBuilder which is already
inherited from UriBuilder.
The converter now tries to keep reading from the same InputStream which
should be possible with ordered and non-overlapping regions. When
necessary the InputStream is re-opened.
Closes gh-24214
The new register methods replace the now deprecated
encoder, decoder, reader, and writer methods, and also offer a choice
to opt into default properties such maxInMemorySize, if configured.
See gh-24124
This commit restores the interpretation of JSON as UTF-8 by default that
was removed in #bc205e0 and also ensures a charset is not appended
automatically to "application/json".
Closes gh-24123
Spring Framework 5.2 introduced support for caching @ControllerAdvice
beans; however, this caching was also applied incorrectly to
non-singleton beans.
This commit addresses this regression by only caching singleton
@ControllerAdvice beans.
Closes gh-24157
As a follow-up of gh-23961, this change provides a way for custom codecs
to align with the default codecs' behavior on common features like
buffer size limits and logging request details.
Closes gh-24118
Co-authored-by: Rossen Stoyanchev <rstoyanchev@pivotal.io>
Prior to this commit, developers could configure their WebClient to use
their custom `ExchangeStrategies`, by providing it in the
`WebClient.Builder` chain.
Once created, an `ExchangeStrategies` instance is not mutable, which
makes it hard for further customizations by other components. In the
case of the reported issue, other components would override the default
configuration for the codecs maxInMemorySize.
This commit makes the `ExchangeStrategies` mutable and uses that fact to
further customize them with a new `WebClient.Builder#exchangeStrategies`
`Consumer` variant. This commit is also deprecating those mutating
variants in favor of a new `WebClient.Builder#exchangeStrategies` that
takes a `ExchangeStrategies#Builder` directly and avoids mutation issues
altogether.
Closes gh-23961
Prior to this commit, developers could configure their WebClient to use
their custom `ExchangeStrategies`, by providing it in the
`WebClient.Builder` chain.
Once created, an `ExchangeStrategies` instance is not mutable, which
makes it hard for further customizations by other components. In the
case of the reported issue, other components would override the default
configuration for the codecs maxInMemorySize.
This commit makes the `ExchangeStrategies` mutable and uses that fact to
further customize them with a new `WebClient.Builder#exchangeStrategies`
`Consumer` variant. This commit is also deprecating those mutating
variants in favor of a new `WebClient.Builder#exchangeStrategies` that
takes a `ExchangeStrategies#Builder` directly and avoids mutation issues
altogether.
Closes gh-23961
This commit exposes the method that returns the media type used to write
forms. By default, it includes the charset in the content type, which
can cause issues with certain consumers. This commit changes the method
from a private to a protected method, so that users can override the
default behavior.
Closes: gh-22971
Fix uncommon case in Jackson2SmileDecoder, where a null token,
incicating a document separator in streaming mode, is followed by
NOT_AVAILABLE.
Closes gh-24009
Before this commit the connector waited for a completed response (via
ServerHttpResponse#setComplete or ServerHttpResponse#writeWith) or an
error signal in handling, but it didn't deal explicitly with the case
where both can occur.
This commit explicitly waits for the completion of handling (success
or error) before passing the response downstream. If an error occurs
after response completion, it is wrapped in a dedicated exception that
also provides access to the completed response.
Close gh-24051
Prior to this commit, methods in a @ControllerAdvice bean were
registered and invoked twice if the advice was a scoped bean (e.g.,
request or session scoped). In other words, both the proxy bean and the
target bean were wrapped in ControllerAdviceBean instances.
This commit fixes this bug by modifying the findAnnotatedBeans() method
in ControllerAdviceBean so that it filters out targets of scoped
proxies.
Closes gh-24017
Spring Framework 5.2 introduced support for implementing the Ordered
interface in a @ControllerAdvice bean. This support requires that
@ControllerAdvice beans be eagerly resolved from the BeanFactory in
order to invoke the getOrder() method defined in the Ordered interface.
Unfortunately doing so resulted in a regression in that an attempt to
eagerly resolve a scoped @ControllerAdvice bean throws a
BeanCreationException due to the lack of an active scope (e.g., request
or session scope).
This commit fixes this regression by avoiding eager resolution of scoped
@ControllerAdvice beans. As a direct consequence, the Ordered interface
is not supported for scoped @ControllerAdvice beans.
Closes gh-23985
Changes introduced in commit 9b2087618b
caused a regression for Cookie support in MockHttpServletResponse.
Specifically, an Expires attribute that cannot be parsed using
`ZonedDateTime.parse()` now results in an exception; whereas,
previously an entry such as `Expires=0` was allowed.
This commit fixes this issue in MockCookie by catching and ignoring any
DateTimeException thrown while attempting to parse an Expires attribute.
Closes gh-23911
Prior to this commit, if MockServletContext was configured with a
FileSystemResourceLoader, invocations of the following methods on a
Microsoft Windows operating system resulted in an InvalidPathException
if the supplied path contained a colon (such as "C:\\temp"). This is
inconsistent with the behavior on non-Windows operating systems. In
addition, for comparable errors resulting in an IOException, those
methods (except getRealPath()) return null instead of throwing the
exception.
- getResourcePaths()
- getResource()
- getResourceAsStream()
- getRealPath()
This commit makes handling of InvalidPathException and IOException
consistent for these methods: both exceptions now result in null be
returned by these methods.
Closes gh-23717
A ResponseStatus exception now exposes extra method to return headers
for the response. This is used in ResponseStatusExceptionHandler to
apply the headers to the response.
Closes gh-23741
- Add maxInMemorySize property to Decoder and HttpMessageReader
implementations that aggregate input to trigger
DataBufferLimitException when reached.
- For codecs that call DataBufferUtils#join, there is now an overloaded
variant with a maxInMemorySize extra argument. Internally, a custom
LimitedDataBufferList is used to count and enforce the limit.
- Jackson2Tokenizer and XmlEventDecoder support those limits per
streamed JSON object.
See gh-23884
At present, MockCookie doesn't preserve expires attribute. This has a
consequence that a cookie value set using
MockHttpServletResponse#addHeader containing an expires attribute will
not match the cookie value obtained from
MockHttpServletResponse#getHeader, since the expires attribute will get
calculated based on current time.
This commit enhances MockCookie to preserve the expires attribute.
Closes gh-23769
Bypass server cookie and write Set-Cookie header directly for Reactor
Netty, and Servlet API which do not provide options.
For Undertow use the sameSite attribute.
Closes gh-23693
If an error looks like a "disconnected client" but the response is not
yet committed then it can't be an I/O error from writing to the server
response. It is most likely as a result of a remote call as part of
request handling.
Not setting the response to 500 in this case results in a 200 response
status despite the error. Even if it was an I/O error from the server
response, setting the status won't impact a failed response.
Closes gh-23319
Add `ClientHttpRequestInitializer` interface that can be used with any
`HttpAccessor` to initialize each `ClientHttpRequest` before it's used.
This provides a useful alternative to `ClientHttpRequestInterceptor`
when users need to configure things like `HttpHeaders`.
Closes gh-22002
On a Servlet container a completion notification may come at any time
even in the UNSUBSCRIBED state, i.e. before the write Publisher has
called onSubscribe.
See: gh-23553
Prior to this commit, a lot of work had been done to prevent improper
use of testing Framework APIs throughout the codebase; however, there
were still some loopholes.
This commit addresses these loopholes by introducing additional
Checkstyle rules (and modifying existing rules) to prevent improper use
of testing framework APIs in production code as well as in test code.
- Checkstyle rules for banned imports have been refactored into
multiple rules specific to JUnit 3, JUnit 4, JUnit Jupiter, and
TestNG.
- Accidental usage of org.junit.Assume has been switched to
org.junit.jupiter.api.Assumptions.
- All test classes now reside under org.springframework packages.
- All test classes (including abstract test classes) now conform to the
`*Tests` naming convention.
- As an added bonus, tests in the renamed
ScenariosForSpringSecurityExpressionTests are now included in the
build.
- Dead JUnit 4 parameterized code has been removed from
DefaultServerWebExchangeCheckNotModifiedTests.
Closes gh-22962
Prior to this commit, the entry set of read-only HttpHeaders lost the
original headers' ordering.
The changes in commit ce7278aaf4 introduced a regression in the read-only
HttpHeaders support. Specifically, the implementation of entrySet() in
the internal ReadOnlyHttpHeaders class converted the original entry set
to an immutable, non-ordered set of immutable entries.
This commit fixes this issue by converting the original entry set to an
immutable, ordered set of immutable entries.
Closes gh-23551
This commit prepends "[{index}] " to all custom display names
configured via @ParameterizedTest.
This provides better diagnostics between the "technical names" reported
on the CI server vs. the "display names" reported within a developer's
IDE.
See gh-23451
Prior to this commit, there was no way to replace the Set-Cookie header
via MockHttpServletResponse. Specifically, an invocation of setHeader()
for the Set-Cookie header resulted in an additional Set-Cookie header
instead of replacing the existing one, which is in violation of the
contract for javax.servlet.http.HttpServletResponse.setHeader(...).
This commit refactors the internals of MockHttpServletResponse to ensure
that an existing Set-Cookie header is overwritten when set via an
invocation of setHeader(). This commit also verifies the expected
behavior for addHeader() and addCookie() with regard to multiple cookies.
Closes gh-23512
Due to a bug (or "unintentional feature") in JUnit 4, overridden test
and lifecycle methods not annotated with @Test, @Before, @After, etc.
are still executed as test methods and lifecycle methods; however,
JUnit Jupiter does not support that. Thus, prior to this commit, some
overridden test and lifecycle methods were no longer executed after the
migration from JUnit 4 to JUnit Jupiter.
This commit addresses this issue for such known use cases, but there
are likely other such use cases within Spring's test suite.
See gh-23451
The use of LinkedCaseInsensitiveMap, going back to 3.0, makes it
unnecessary to iterate over keys which can cause
ConcurrentModificationException.
Closes gh-23460
This commit removes the JUnit 4 dependency from all modules except
spring-test which provides explicit JUnit 4 support.
This commit also includes the following.
- migration from JUnit 4 assertions to JUnit Jupiter assertions in all
Kotlin tests
- migration from JUnit 4 assumptions in Spring's TestGroup support to
JUnit Jupiter assumptions, based on org.opentest4j.TestAbortedException
- introduction of a new TestGroups utility class than can be used from
existing JUnit 4 tests in the spring-test module in order to perform
assumptions using JUnit 4's Assume class
See gh-23451
This commit migrates parameterized tests in spring-core using the
"composed @ParameterizedTest" approach. This approach is reused in
follow-up commits for the migration of the remaining modules.
For a concrete example, see AbstractDataBufferAllocatingTests and its
subclasses (e.g., DataBufferTests).
Specifically, AbstractDataBufferAllocatingTests declares a custom
@ParameterizedDataBufferAllocatingTest annotation that is
meta-annotated with @ParameterizedTest and
@MethodSource("org.springframework.core.io.buffer.AbstractDataBufferAllocatingTests#dataBufferFactories()").
Individual methods in concrete subclasses are then annotated with
@ParameterizedDataBufferAllocatingTest instead of @ParameterizedTest or
@Test.
The approach makes the migration from JUnit 4 to JUnit Jupiter rather
straightforward; however, there is one major downside. The arguments
for a @ParameterizedTest test method can only be accessed by the test
method itself. It is not possible to access them in an @BeforeEach
method (see https://github.com/junit-team/junit5/issues/944).
Consequently, we are forced to declare the parameters in each such
method and delegate to a custom "setup" method. Although this is a bit
cumbersome, I feel it is currently the best way to achieve fine grained
parameterized tests within our test suite without implementing a custom
TestTemplateInvocationContextProvider for each specific use case.
Once https://github.com/junit-team/junit5/issues/878 is resolved, we
should consider migrating to parameterized test classes.
See gh-23451
Deprecate all mutation methods in `MethodParameter` in favor of factory
methods that return a new instance. Existing code that previously relied
on mutation has been updated to use the replacement methods.
Closes gh-23385
Added support for status codes that do not occur in HttpStatus in
DefaultClientResponseBuilder and made ClientResponse::statusCode
ClientHttpResponse::getStatusCode @Nullable.
Closed gh-23366
The isJavaIdentifier check is not really required, but also seems
intuitive for variables to be Java identifier-like. This commit relaxes
the constraint a bit by also allowing "-".
Closes gh-23101
Prior to this commit, the `header(String, String)` method in the
ServerHttpRequest.Builder API actually added a header value instead of
setting or overriding a header value. Since this conflicted with the
stated behavior in the Javadoc as well as the original intention of the
method, we have decided to introduce an overloaded variant
`header(String, String...)` which accepts a var-args list of header
values to set or override.
In addition, this commit deprecates the existing `header(String, String)`
method for removal in Spring Framework 5.2.
In order not to be a breaking change for custom implementations of the
builder API, this commit implements the new `header(String, String...)`
method as an interface `default` method, with the intent to remove the
default implementation in Spring Framework 5.2
closes gh-23333
Prior to this commit, the `header(String, String)` method in the
ServerHttpRequest.Builder API actually added a header value instead of
setting or overriding a header value. Since this conflicted with the
stated behavior in the Javadoc as well as the original intention of the
method, we have decided to introduce an overloaded variant
`header(String, String...)` which accepts a var-args list of header
values to set or override.
In addition, this commit deprecates the existing `header(String, String)`
method for removal in Spring Framework 5.2.
In order not to be a breaking change for custom implementations of the
builder API, this commit implements the new `header(String, String...)`
method as an interface `default` method, with the intent to remove the
default implementation in Spring Framework 5.2
closes gh-23333
To make the switching of separators complete, it is also important to
know whether the decoding of path segment values and the parsing of
path param should be done as those are applied transparently.
This commit replaces the recently added separator argument to
PathContainer.parsePath with an Options type with two predefined
constants. One for HTTP URLs with automatic decoding and parsing of
path params, and another for "." separated message routes without
decoding except for encoded sequences of the separator itself.
See gh-23310