Browse Source

Merge branch '6.2.x'

pull/34993/merge
rstoyanchev 1 month ago
parent
commit
9daf99af3f
  1. 21
      framework-docs/modules/ROOT/pages/web/webmvc/filters.adoc
  2. 18
      spring-web/src/main/java/org/springframework/http/StreamingHttpOutputMessage.java
  3. 31
      spring-web/src/main/java/org/springframework/http/client/AbstractStreamingClientHttpRequest.java
  4. 7
      spring-web/src/main/java/org/springframework/web/client/RequestCallback.java

21
framework-docs/modules/ROOT/pages/web/webmvc/filters.adoc

@ -3,7 +3,10 @@ @@ -3,7 +3,10 @@
[.small]#xref:web/webflux/reactive-spring.adoc#webflux-filters[See equivalent in the Reactive stack]#
The `spring-web` module provides some useful filters:
In the Servlet API, you can add a `jakarta.servlet.Filter` to apply interception-style logic
before and after the rest of the processing chain of filters and the target `Servlet`.
The `spring-web` module has a number of built-in `Filter` implementations:
* xref:web/webmvc/filters.adoc#filters-http-put[Form Data]
* xref:web/webmvc/filters.adoc#filters-forwarded-headers[Forwarded Headers]
@ -11,9 +14,19 @@ The `spring-web` module provides some useful filters: @@ -11,9 +14,19 @@ The `spring-web` module provides some useful filters:
* xref:web/webmvc/filters.adoc#filters-cors[CORS]
* xref:web/webmvc/filters.adoc#filters.url-handler[URL Handler]
Servlet filters can be configured in the `web.xml` configuration file or using Servlet annotations.
If you are using Spring Boot, you can
{spring-boot-docs}/how-to/webserver.html#howto.webserver.add-servlet-filter-listener.spring-bean[declare them as beans and configure them as part of your application].
There are also base class implementations for use in Spring applications:
* `GenericFilterBean` -- base class for a `Filter` configured as a Spring bean;
integrates with the Spring `ApplicationContext` lifecycle.
* `OncePerRequestFilter` -- extension of `GenericFilterBean` that supports a single
invocation at the start of a request, i.e. during the `REQUEST` dispatch phase, and
ignoring further handling via `FORWARD` dispatches. The filter also provides control
over whether the `Filter` gets involved in `ASYNC` and `ERROR` dispatches.
Servlet filters can be configured in `web.xml` or via Servlet annotations.
In a Spring Boot application , you can
{spring-boot-docs}/how-to/webserver.html#howto.webserver.add-servlet-filter-listener.spring-bean[declare Filter's as beans]
and Boot will have them configured.
[[filters-http-put]]

18
spring-web/src/main/java/org/springframework/http/StreamingHttpOutputMessage.java

@ -22,10 +22,16 @@ import java.io.OutputStream; @@ -22,10 +22,16 @@ import java.io.OutputStream;
import org.springframework.util.StreamUtils;
/**
* Represents an HTTP output message that allows for setting a streaming body.
* Note that such messages typically do not support {@link #getBody()} access.
* Contract for {@code HttpOutputMessage} implementations to expose the ability
* to stream request body content by writing to an {@link OutputStream} from
* a callback.
*
* <p>The {@link #setBody(Body)} method provides the option to stream, and is
* mutually exclusive use of {@link #getBody()}, which instead returns an
* {@code OutputStream} that aggregates the request body before sending it.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 4.0
* @see #setBody
*/
@ -33,6 +39,8 @@ public interface StreamingHttpOutputMessage extends HttpOutputMessage { @@ -33,6 +39,8 @@ public interface StreamingHttpOutputMessage extends HttpOutputMessage {
/**
* Set the streaming body callback for this message.
* <p>Note that this is mutually exclusive with {@link #getBody()}, which
* may instead aggregate the request body before sending it.
* @param body the streaming body callback
*/
void setBody(Body body);
@ -60,9 +68,9 @@ public interface StreamingHttpOutputMessage extends HttpOutputMessage { @@ -60,9 +68,9 @@ public interface StreamingHttpOutputMessage extends HttpOutputMessage {
/**
* Defines the contract for bodies that can be written directly to an
* {@link OutputStream}. Useful with HTTP client libraries that provide
* indirect access to an {@link OutputStream} via a callback mechanism.
* Contract to stream request body content to an {@link OutputStream}.
* In some HTTP client libraries this is only possible indirectly through a
* callback mechanism.
*/
@FunctionalInterface
interface Body {

31
spring-web/src/main/java/org/springframework/http/client/AbstractStreamingClientHttpRequest.java

@ -22,16 +22,23 @@ import java.io.OutputStream; @@ -22,16 +22,23 @@ import java.io.OutputStream;
import org.jspecify.annotations.Nullable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.StreamingHttpOutputMessage;
import org.springframework.util.Assert;
import org.springframework.util.FastByteArrayOutputStream;
/**
* Abstract base for {@link ClientHttpRequest} that also implement
* {@link StreamingHttpOutputMessage}. Ensures that headers and
* body are not written multiple times.
* Extension of {@link AbstractClientHttpRequest} that adds the ability to stream
* request body content directly to the underlying HTTP client library through
* the {@link StreamingHttpOutputMessage} contract.
*
* <p>It is necessary to call {@link #setBody} and stream the request body through
* a callback for access to the {@code OutputStream}. The alternative to call
* {@link #getBody()} is also supported as a fallback, but that does not stream,
* and returns an aggregating {@code OutputStream} instead.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 6.1
*/
abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequest
@ -42,6 +49,12 @@ abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequ @@ -42,6 +49,12 @@ abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequ
private @Nullable FastByteArrayOutputStream bodyStream;
/**
* Implements the {@link HttpOutputMessage} contract for request body content.
* <p>Note that this method does not result in streaming, and the returned
* {@code OutputStream} aggregates the full content in a byte[] before
* sending. To use streaming, call {@link #setBody} instead.
*/
@Override
protected final OutputStream getBodyInternal(HttpHeaders headers) {
Assert.state(this.body == null, "Invoke either getBody or setBody; not both");
@ -52,6 +65,10 @@ abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequ @@ -52,6 +65,10 @@ abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequ
return this.bodyStream;
}
/**
* Implements the {@link StreamingHttpOutputMessage} contract for writing
* request body by streaming directly to the underlying HTTP client.
*/
@Override
public final void setBody(Body body) {
Assert.notNull(body, "Body must not be null");
@ -72,12 +89,14 @@ abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequ @@ -72,12 +89,14 @@ abstract class AbstractStreamingClientHttpRequest extends AbstractClientHttpRequ
/**
* Abstract template method that writes the given headers and content to the HTTP request.
* @param headers the HTTP headers
* Abstract method for concrete implementations to write the headers and
* {@link StreamingHttpOutputMessage.Body} to the HTTP request.
* @param headers the HTTP headers for the request
* @param body the HTTP body, may be {@code null} if no body was {@linkplain #setBody(Body) set}
* @return the response object for the executed request
* @since 6.1
*/
protected abstract ClientHttpResponse executeInternal(HttpHeaders headers, @Nullable Body body) throws IOException;
protected abstract ClientHttpResponse executeInternal(
HttpHeaders headers, @Nullable Body body) throws IOException;
}

7
spring-web/src/main/java/org/springframework/web/client/RequestCallback.java

@ -19,6 +19,7 @@ package org.springframework.web.client; @@ -19,6 +19,7 @@ package org.springframework.web.client;
import java.io.IOException;
import java.lang.reflect.Type;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.client.ClientHttpRequest;
/**
@ -44,6 +45,12 @@ public interface RequestCallback { @@ -44,6 +45,12 @@ public interface RequestCallback {
* Gets called by {@link RestTemplate#execute} with an opened {@code ClientHttpRequest}.
* Does not need to care about closing the request or about handling errors:
* this will all be handled by the {@code RestTemplate}.
* <p><strong>Note:</strong> In order to stream request body content directly
* to the underlying HTTP library, implementations must check if the request
* is an implementation of {@link org.springframework.http.StreamingHttpOutputMessage},
* and set the request body through it. Use of the {@link HttpOutputMessage#getBody()}
* is also supported, but results in full content aggregation prior to execution.
* All built-in request implementations support {@code StreamingHttpOutputMessage}.
* @param request the active HTTP request
* @throws IOException in case of I/O errors
*/

Loading…
Cancel
Save