This new interface is not strictly necessary and introduces a binary
incompatibility. This commit merges back all the method definitions into
`SseBuilder` and `StreamBuilder` interfaces.
Closes gh-33736
Prior to this commit, our XML parser usage would be already haredened
against XXE (XML External Entities) attacks. Still, we recently received
several invalid security reports claiming that our setup should be
hardened.
This commit documents a few usages of XML parsers to add some more
context and hopefully prevent future invalid reports.
Closes gh-33713
Rather than leaving it to the Resource implementation, and
potentially normalizing twice, we apply it once as part of the
initial processPath checks.
Closes gh-33689
Prior to this commit, the URL handler mapping would expose the matching
pattern, the path within mapping and matching URI variables as request
attributes. This was the case when the mapping would use the
`AntPathMatcher` as matching infrastructure, but not when using the
`PathPattern` variant. In this case, the map of URI variables would be
`null`. This could throw `IllegalArgumentException` when `RedirectView`
instances were relying on the presence of specific variables.
This commit ensures that URI variables are also extracted when the
`PathPatternParser` is used.
Fixes gh-33422
Prior to this commit, MVC function endpoints would allow Server Sent
Event responses through `ServerResponse.sse()`. While this covers a
common use case for streaming responses, other technologies would
benefit from a "low-level", unopinionated streaming support.
This commit introduces a new `BodyBuilder.stream()` methods that enables
such use cases. Developers are in charge of setting the relevant HTTP
response headers beforehand, and then can write to the response as raw
`String`, `byte[]` or using complex objects and the configured message
converters for serialization.
Because each streaming protocol has different message separator
semantics, it is also the developers' responsibility to flush buffered
content to the network once a message has been fully written.
Closes gh-32710
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
Prior to this commit, `ResponseBodyEmitter` woud accept a single
`Runnable` callback on each of its `onTimeout`, `onError` or
`onCompletion` methods. This would limit the developers' ability to
register multiple sets of callbacks: one for managing the publication of
streaming values, another one for managing other concerns like
keep-alive signals to maintain the connection.
This commit now allows multiple calls to `onTimeout`, `onError` and
`onCompletion` and will register all callbacks accordingly.
Closes gh-33356
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
Based on feedback from htmx-spring-boot. It's more generally useful
to process those from within DefaultFragmentsRendering rather than
in ModelAndViewMethodReturnValueHandler. That way a custom
return value handler can create a FragmentsRendering as well and
get the same result.
See gh-33194
This commit documents `ControllerAdviceBean` as internal usage, as it is
not meant for application to manually create controller advice bean
instances.
This also refactors the existing partial implementation of the support
for creating controller advice beans "programmatically".
Closes gh-32776
This change tracks the multipart nature of the async request
within the `DispatcherServlet`, in the `WebAsyncManager`.
This allows for the second ASYNC dispatch to recognize the
multipart aspect and clean up the associated resources.
Closes gh-33161
SmartHttpMessageConverter is similar to GenericHttpMessageConverter,
but more consistent with WebFlux Encoder and Decoder contracts, with
the following differences:
- A ResolvableType parameter is used instead of the Type one
- The MethodParameter can be retrieved via the ResolvableType source
- No contextClass parameter
- `@Nullable Map<String, Object> hints` additional parameter for write
and read methods
This commit also refines RestTemplate#canReadResponse in order to use
the most specific converter contract when possible.
Closes gh-33118
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
Before this commit, characters were always encoded with the default
encoding (i.e. ISO-8859-1). Now, the character encoding of the response
is used.
Closes gh-files
Prior to this commit, exceptions thrown by MVC functional handlers would
not be considered by `ExceptionHandlerExceptionResolver`. This means
that common exceptions would not be handled consistently between
annotated and functional handlers. This is true, for example, for all
`ProblemDetails`-related exception handling.
While MVC functional and annotation models are separate concepts,
WebFlux has a different error handling model that processes all
exceptions in a central place.
This commit ensures that `ExceptionHandlerExceptionResolver` considers
exceptions thrown by handlers of type `HandlerFunction<?>` and processes
them accordingly.
Closes gh-32689
Includes checking the Servlet 3.0+ ServletRequest.getServletContext() method in the request-only constructors, being able to fall back to the root WebApplicationContext.
See gh-32926
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, `@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, the `ReactiveTypeHandler` would handle `Flux`-like
return types from controller methods and adapt them to SSE streams using
the `SseEmitter`/`ResponseBodyEmitter` APIs. In case an `IOException` is
thrown while writing to the HTTP response stream, the
`ReactiveTypeHandler` would rely on the Servlet container to call
`AsyncListener#onError` - this would be the signal for Spring MVC to
complete the async exchange. To prevent racing issues between this
signal and the actual handling of the exception, changes like gh-20173
were applied. Since then, robust checks were added with gh-32340 in
`StandardServletAsyncWebRequest.LifecycleHttpServletResponse`.
With Jetty 12, `AsyncListener#onError` would not be called as the error
would happen while writing in blocking mode to the response (so, not
using the Servlet WriteListener contract). But still, such `IOException`
would still result in the closing of the HTTP connection. As of Jetty
12.0.4, this is no longer the case and the party managing the async
lifecycle is in charge of completing the exchange, as it should. This
means that the current behavior leaks HTTP connections for these cases
and causes memory issues.
This commit ensures that such exceptions happening during response
writes are caught and result in the completion of the `SSEEmitter` and
the closing of the exchange. Even if other Servlet containers still
propagate the error `AsyncListener#onError`, competing signals are still
managed with gh-32340.
Closes gh-32629