Also fix a couple of related issues:
- add AsyncRequestNotUsableException to the list of exceptions
that imply response issues.
- handle exceptions from @ExceptionHandler regardless of whether
thrown immediately or via Publisher.
Closes gh-32359
The following adjustments are also made as a result:
- Use int to check if lock is held and unlock is needed, given that
for non-async requests we don't need to obtain a lock.
- Protect access methods getOutputStream and getWriter with the
same locking and state checks.
Closes gh-32340
ServletResponseHttpHeaders#get should be annotated with `@Nullable` and
return null instead of a singleton list containing null when there is no
content type header.
Closes gh-32362
In addition to using the ServletOutputStream, it's also possible to call
ServletResponse#flushBuffer, so the ServletOutputStream wrapper logic needs
to apply there as well.
See gh-32340
The wrapped response prevents use after AsyncListener onError or completion
to ensure compliance with Servlet Spec 2.3.3.4.
The wrapped response is applied in RequestMappingHandlerAdapter.
The wrapped response raises AsyncRequestNotUsableException that is now
handled in DefaultHandlerExceptionResolver.
See gh-32340
This commit refines WebMVC and WebFlux argument resolution in order to
convert properly Kotlin value class arguments by using the type of the
value instead of the type of the value class.
Closes gh-32353
The HttpHeaders.getAcceptLanguageAsLocales was incurring overhead from
using a Stream, as well as calling the fairly expensive
Locale.getDisplayName method.
Switch to using an ArrayList, and skipping over wildcard ranges to avoid
needing to check the display name.
Closes gh-32318
This commit fixes a performance regression caused by gh-31698,
and more specifically by KClass#isValue invocations which are slow since
they load the whole module to find the class to get the descriptor.
After discussing with the Kotlin team, it has been decided that only
checking for the presence of `@JvmInline` annotation is enough for
Spring use case.
As a consequence, this commit introduces a new
KotlinDetector#isInlineClass method that performs such check, and
BeanUtils, CoroutinesUtils and WebMVC/WebFlux InvocableHandlerMethod
have been refined to leverage it.
Closes gh-32334
Based on feedback from several members of the community, we have
decided to revert the caching of the Content-Type header that was
introduced in ContentCachingResponseWrapper in 375e0e6827.
This commit therefore completely removes Content-Type caching in
ContentCachingResponseWrapper and updates the existing tests
accordingly.
To provide guards against future regressions in this area, this commit
also introduces explicit tests for the 6 ways to set the content length
in ContentCachingResponseWrapper and modifies a test in
ShallowEtagHeaderFilterTests to ensure that a Content-Type header set
directly on ContentCachingResponseWrapper is propagated to the
underlying response even if content caching is disabled for the
ShallowEtagHeaderFilter.
See gh-32039
Closes gh-32317
Prior to this commit, getHeaderNames() returned duplicates for the
Content-Type and Content-Length headers if they were set in the wrapped
response as well as in ContentCachingResponseWrapper.
This commit fixes that by returning a unique set from getHeaderNames().
In addition, this commit introduces a new test in
ContentCachingResponseWrapperTests to verify the expected behavior for
Content-Type and Content-Length headers that are set in the wrapped
response as well as in ContentCachingResponseWrapper.
See gh-32039
See gh-32317
Commit 375e0e6827 introduced a regression in
ContentCachingResponseWrapper (CCRW). Specifically, CCRW no longer
honors Content-Type and Content-Length headers that have been set on
the wrapped response and returns null for those header values if they
have not been set directly on the CCRW.
This commit fixes this regression as follows.
- The Content-Type and Content-Length headers set in the wrapped
response are honored in getContentType(), containsHeader(),
getHeader(), and getHeaders() unless those headers have been set
directly on the CCRW.
- In copyBodyToResponse(), the Content-Type in the wrapped response is
only overridden if the Content-Type has been set directly on the CCRW.
See gh-32039
Closes gh-32317
Previously, RestClientAdapter claimed that it supports request
attributes when, in fact, it does not. This commit updates the
implementation accordingly.
See gh-32232
This commit ensures that, when creating a RestClient.Builder from a
RestTemplate, the UriBuilderFactory is only copied if it has been
changed from the default values.
Before this commit, the UriBuilderFactory was effectively alway copied,
resulting in not being able to use a baseUrl.
This commit also introduces a small memory optimization in
DefaultUriBuilderFactory, so that default environment variables are
created lazily.
Closes gh-32180
This commit replaces occurrences of modelAttribitePredicate with modelAttributePredicate
in HandlerMethodValidationException and the associated validator.
Closes gh-32183
To improve consistency and avoid confusion regarding primitive types
and their wrapper types, this commit ensures that we always use class
literals for primitive types.
For example, instead of using the `Void.TYPE` constant, we now
consistently use `void.class`.
Before this commit, the JDK and Jetty connectors do not have any
safeguards against multiple body subscriptions. Such as check has now
been added.
Closes gh-32100
The behavior for the toString() implementation for annotations changed
in JDK 19, per my request to the JDK team (see link below).
Specifically, since JDK 19, the toString() implementation for annotation
proxies created by the JDK started using canonical names instead of
binary names for types.
See https://bugs.openjdk.org/browse/JDK-8281462
Prior to this commit, the `RestTemplate` observation instrumentation
would only record `RestClientException` and `IOException` as errors in
the observation. Other types of errors can be thrown by custom
components, such as `ResponseErrorHandler` and in this case they aren't
recorded with the observation.
Also, the current instrumentation does not create any observation scope
around the execution. While this would have a limited benefit as no
application code is executed there, developers could set up custom
components (such as, again, `ResponseErrorHandler`) that could use
contextual logging with trace ids.
This commit ensures that all `Throwable` are recorded as errors with the
observations and that an observation `Scope` is created around the
execution of the client exchange.
Fixes gh-32060
This commit makes sure that, when building a RestClient based on the
configuration of a RestTemplate, the request factory is unwrapped if it
is a InterceptingClientHttpRequestFactory.
Closes gh-32038
This commit ensures that setting the Content-Length through
setHeader("Content-Length", x") has the same effect as calling
setContentLength in the ShallowEtagHeaderFilter. It also filters out
Content-Type headers similarly to Content-Length.
Closes gh-32039
If multiple request mapping annotations are discovered, Spring MVC and
Spring WebFlux now log a warning similar to the following (without
newlines).
Multiple @RequestMapping annotations found on
void org.example.MyController.put(), but only the first will be used:
[
@org.springframework.web.bind.annotation.PutMapping(consumes={}, headers={}, name="", params={}, path={"/put"}, produces={}, value={"/put"}),
@org.springframework.web.bind.annotation.PostMapping(consumes={}, headers={}, name="", params={}, path={"/put"}, produces={}, value={"/put"})
]
Closes gh-31962
This change moves container element properties from ParameterErrors
to base class ParameterValidationResult, and makes that support
independent of whether violations are nested within a container
element bean or through constraints on container elements, e.g.
`List<@NotBlank String>`.
Closes gh-31887
This commit adds CORS support for Private Network Access
by adding an Access-Control-Allow-Private-Network response
header when the preflight request is sent with an
Access-Control-Request-Private-Network header and that
Private Network Access has been enabled in the CORS
configuration.
See https://developer.chrome.com/blog/private-network-access-preflight/
for more details.
Closes gh-28546
This commit implements Cookie support in WebFlux without any workaround
as now all supported servers have the SameSite feature enabled.
Closes gh-31954
This commit updates the description of RequestHandledEvent to avoid
providing a misleading status as the absence of a failure logs OK which
can be inaccurate.
Closes gh-27595
This commit adds Javadoc to the `getContentLength` method of
`MockHttpServletResponse` to reflect that it gets its value from the
HTTP response header.
Closes gh-31833