This aligns HttpHeaders with other places like ServletWebRequest and
DefaultWebExchange where an ETag is accepted as input.
It also allows us to remove quoting from places that delegate to
HttpHeaders#setETag since it now does that internally.
Closes gh-33412
Update checks whether quoting is needed to be more complete
than what we've used so far, making sure the there is both
opening and closing quotes independent of each other.
See gh-33412
On the client side, supports `name=value` pairs. Placeholders in values
are resolved by the `embeddedValueResolver`.
On the server side, additionally supports `name` and `!name` syntax.
Closes gh-33309
Thymeleaf has its own special handling for SSE that gets in the way
of fragment rendering. This is why we need to set the response
content-type before streaming, and then pass text/html to the
View for rendering each fragment.
See gh-33194
This application/javascript MIME type is deprecated.
This commit therefore changes the MIME type mapping for *.js files from
application/javascript to text/javascript in order to align with
industry standards.
Closes gh-33197
The result returned by Kotlin reflective invocation of a function
returning an inline value class is wrapped, which makes sense
from Kotlin POV but from a JVM perspective the associated value
and type should be unwrapped to be consistent with what
would happen with a reflective invocation done by Java.
This commit unwraps such result.
Closes gh-33026
This provides an implementation of an HTTP Handler Adapter that is coded
directly to the Eclipse Jetty core API, bypassing any servlet
implementation.
This includes a Jetty implementation of the spring `WebSocketClient`
interface, `JettyWebSocketClient`, using an explicit dependency to the
jetty-websocket-api.
Closes gh-32097
Co-authored-by: Lachlan Roberts <lachlan@webtide.com>
Co-authored-by: Arjen Poutsma <arjen.poutsma@broadcom.com>
When a response fails to be completely emitted by the remote (connection
termination during the transmission of the response for example), a
WebClientResponseException can be propagated with a confusing message
which mainly reflects the status code and reason phrase, leading to
messages like "200 OK" in such an exception.
This change improves the situation by appending a hint at the underlying
cause whenever getMessage() is called on a WebClientResponseException
which was created with a non-error status code.
Closes gh-33127
Prior to this commit, if ModelMap was used as an argument type in a
WebFlux controller method, the user encountered an exception similar to
the following.
java.lang.IllegalStateException: argument type mismatch
Controller [example.SampleController]
Method [java.lang.String example.SampleController.index(org.springframework.ui.ModelMap)] with argument values:
[0] [type=org.springframework.validation.support.BindingAwareConcurrentModel] [value={}]
However, the above error message is a bit cryptic since the error
occurs while attempting to invoke the controller method with an
instance of BindingAwareConcurrentModel which is not compatible with
ModelMap. More importantly, this error message does not explicitly
convey to the user that a ModelMap is not supported.
This commit improve the diagnostics for the user in such scenarios by
rejecting the use of ModelMap upfront in WebFlux.
Consequently, for the same use case as above, the user now encounters
an exception similar to the following.
java.lang.IllegalStateException:
Could not resolve parameter [0] in
java.lang.String example.SampleController.index(org.springframework.ui.ModelMap):
No suitable resolver
Closes gh-33109
Prior to this commit, the "Method Arguments" documentation for WebFlux
in the reference manual stated that WebFlux controller methods can
accept arguments of type Map, Model, or ModelMap to access the model.
However, ModelMap is actually not supported and results in exception
due to a type mismatch.
This commit updates the documentation to reflect this.
In addition, this commit updates related Javadoc and tests to avoid
mentioning or using ModelMap in WebFlux.
Closes gh-33107
According to the official FreeMarker documentation, Spring's
FreeMarkerView implementations should be configuring the
output_encoding for template rendering.
To address that, this commit modifies the FreeMarkerView
implementations in Web MVC and WebFlux to explicitly set the
output_encoding for template rendering.
See https://freemarker.apache.org/docs/pgui_misc_charset.html#autoid_53
See gh-33071
Closes gh-33106
Prior to this commit, RequestMappingViewResolutionIntegrationTests
invoked the following:
configurer.setTemplateLoaderPath(
"classpath*:org/springframework/web/reactive/view/freemarker/");
However, that configuration is invalid since `classpath*:` is not
supported for a `templateLoaderPath`.
Despite that, the tests still passed since FreeMarkerConfigurer already
registers a new ClassTemplateLoader(FreeMarkerConfigurer.class, ""),
which automatically finds template files in the same package as
FreeMarkerConfigurer (for the "spring.ftl" macro library support) and
coincidentally RequestMappingViewResolutionIntegrationTests as well
(which resides in the same package).
This commit therefore removes the invalid configuration and adds a
comment to explain what's going on.
This commit compiles our Protobuf against 4.27, effectively raising our
baseline to 3.9+.
This commit also re-generates all the Java messages from the .proto spec
using the latest protoc binary.
Closes gh-33011
This commit aligns Spring WebFlux with WebMvc in adding URI variables
conditionally if not already in the map. The idea is that data
binding is primarily through form data and query params, with URI
variables, and request headers (to be implemented next) also made
available but without shadowing existing values.
See gh-32676
This commit makes several improvements to MultiValueMap:
- asSingleValueMap offers a single-value view (as opposed to the
existing toSingleValueMap, which offers a copy)
- fromSingleValue is a static method that adapts a Map<?,?> to the
MultiValueMap interface
- fromMultiValue is a static method that adapts a Map<?,List<?>> to the
MultiValueMap interface
Closes gh-32832
Prior to this commit, gh-31936 enabled content negotiation for
`@ExceptionHandler` annotated methods in Spring MVC and WebFlux.
In the case of WebFlux, HTTP clients sending invalid media types in the
"Accept" request header would fail with a `NotAcceptableStatusException`
This exception would be handled with an HTTP 406 response status,
instead of processing the original exception.
This commit ensures that invalid media types are ignored during the
exception handling phase and that we fall back to "*/*".
Fixes gh-32878
Prior to this commit, `@ExceptionHandler` annotated controller methods
could be mapped using the exception type declaration as an annotation
attribute, or as a method parameter.
While such methods support a wide variety of method arguments and return
types, it was not possible to declare the same exception type on
different methods (in the same controller/controller advice).
This commit adds a new `produces` attribute on `@ExceptionHandler`; with
that, applications can vary the HTTP response depending on the exception
type and the requested content-type by the client:
```
@ExceptionHandler(produces = "application/json")
public ResponseEntity<ErrorMessage> handleJson(IllegalArgumentException exc) {
return ResponseEntity.badRequest().body(new ErrorMessage(exc.getMessage(), 42));
}
@ExceptionHandler(produces = "text/html")
public String handle(IllegalArgumentException exc, Model model) {
model.addAttribute("error", new ErrorMessage(exc.getMessage(), 42));
return "errorView";
}
```
This commit implements support in both Spring MVC and Spring WebFlux.
Closes gh-31936
Prior to this commit, `DataBufferLimitException` would be thrown by
codecs when the request body was too large for the configured buffer
limit. This exception would not be handled by the web infrastructure and
would result in an HTTP 500 server error.
This commit introduces a new `PayloadTooLargeException` type that will
result in an HTTP 413 "Payload too large" response status.
Closes gh-32558
This commit ensures that a copy is made of old attributes before
replacing it with new attributes. Because new attributes can be
composed of old, clearing the old would also remove entries from the
new.
See gh-32245
This commit introduces
BodyInserters.fromValue(T, ParameterizedTypeReference<T>) variant as
well as related WebClient.RequestBodySpec API,
ServerResponse.BodyBuilder API and Kotlin extensions.
Closes gh-32713
This commit ensures that `InvocableHandlerMethod` executes the method
on the desired thread if a non-blocking thread is specified, even in the
case where arguments resolution happens on a different thread. This is
notably the case if the method body is resolved as an input argument to
the controller method (`@RequestBody`).
Closes gh-32502
This commit introduces support for org.webjars:webjars-locator-lite
via a new LiteWebJarsResourceResolver in Spring MVC and WebFlux, and
deprecates WebJarsResourceResolver which is performing a classpath
scanning that slows down application startup.
Closes gh-27619
Javadoc doesn't seem to like having `e.g.` as it thinks the sentence
ends there, which is usually incorrect and results in broken descriptions.
This commit rewords the doc strings slightly to avoid problematic parts.
Closes gh-32532