Merge branch '5.3.x'
This commit is contained in:
commit
e0b405869f
|
@ -2015,10 +2015,9 @@ generally supported for all return values.
|
|||
to be written (however, `text/event-stream` must be requested or declared in the mapping
|
||||
through the `produces` attribute).
|
||||
|
||||
| Any other return value
|
||||
| If a return value is not matched to any of the above, it is, by default, treated as a view
|
||||
name, if it is `String` or `void` (default view name selection applies), or as a model
|
||||
attribute to be added to the model, unless it is a simple type, as determined by
|
||||
| Other return values
|
||||
| If a return value remains unresolved in any other way, it is treated as a model
|
||||
attribute, unless it is a simple type as determined by
|
||||
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty],
|
||||
in which case it remains unresolved.
|
||||
|===
|
||||
|
|
|
@ -2282,23 +2282,18 @@ supported for all return values.
|
|||
| Write to the response `OutputStream` asynchronously. Also supported as the body of a
|
||||
`ResponseEntity`. See <<mvc-ann-async>> and <<mvc-ann-async-http-streaming>>.
|
||||
|
||||
| Reactive types -- Reactor, RxJava, or others through `ReactiveAdapterRegistry`
|
||||
| Alternative to `DeferredResult` with multi-value streams (for example, `Flux`, `Observable`)
|
||||
collected to a `List`.
|
||||
| Reactor and other reactive types registered via `ReactiveAdapterRegistry`
|
||||
| A single value type, e.g. `Mono`, is comparable to returning `DeferredResult`.
|
||||
A multi-value type, e.g. `Flux`, may be treated as a stream depending on the requested
|
||||
media type, e.g. "text/event-stream", "application/json+stream", or otherwise is
|
||||
collected to a List and rendered as a single value. See <<mvc-ann-async>> and
|
||||
<<mvc-ann-async-reactive-types>>.
|
||||
|
||||
For streaming scenarios (for example, `text/event-stream`, `application/json+stream`),
|
||||
`SseEmitter` and `ResponseBodyEmitter` are used instead, where `ServletOutputStream`
|
||||
blocking I/O is performed on a Spring MVC-managed thread and back pressure is applied
|
||||
against the completion of each write.
|
||||
|
||||
See <<mvc-ann-async>> and <<mvc-ann-async-reactive-types>>.
|
||||
|
||||
| Any other return value
|
||||
| Any return value that does not match any of the earlier values in this table and that
|
||||
is a `String` or `void` is treated as a view name (default view name selection through
|
||||
`RequestToViewNameTranslator` applies), provided it is not a simple type, as determined by
|
||||
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty].
|
||||
Values that are simple types remain unresolved.
|
||||
| Other return values
|
||||
| If a return value remains unresolved in any other way, it is treated as a model
|
||||
attribute, unless it is a simple type as determined by
|
||||
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty],
|
||||
in which case it remains unresolved.
|
||||
|===
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -54,6 +54,10 @@ public abstract class InterceptingHttpAccessor extends HttpAccessor {
|
|||
* Set the request interceptors that this accessor should use.
|
||||
* <p>The interceptors will get immediately sorted according to their
|
||||
* {@linkplain AnnotationAwareOrderComparator#sort(List) order}.
|
||||
* <p><strong>Note:</strong> This method does not support concurrent changes,
|
||||
* and in most cases should not be called after initialization on startup.
|
||||
* See also related note on {@link org.springframework.web.client.RestTemplate}
|
||||
* regarding concurrent configuration changes.
|
||||
* @see #getRequestFactory()
|
||||
* @see AnnotationAwareOrderComparator
|
||||
*/
|
||||
|
|
|
@ -78,11 +78,17 @@ import org.springframework.web.util.UriTemplateHandler;
|
|||
/**
|
||||
* Synchronous client to perform HTTP requests, exposing a simple, template
|
||||
* method API over underlying HTTP client libraries such as the JDK
|
||||
* {@code HttpURLConnection}, Apache HttpComponents, and others.
|
||||
* {@code HttpURLConnection}, Apache HttpComponents, and others. RestTemplate
|
||||
* offers templates for common scenarios by HTTP method, in addition to the
|
||||
* generalized {@code exchange} and {@code execute} methods that support of
|
||||
* less frequent cases.
|
||||
*
|
||||
* <p>The RestTemplate offers templates for common scenarios by HTTP method, in
|
||||
* addition to the generalized {@code exchange} and {@code execute} methods that
|
||||
* support of less frequent cases.
|
||||
* <p>RestTemplate is typically used as a shared component. However, its
|
||||
* configuration does not support concurrent modification, and as such its
|
||||
* configuration is typically prepared on startup. If necessary, you can create
|
||||
* multiple, differently configured RestTemplate instances on startup. Such
|
||||
* instances may use the same the underlying {@link ClientHttpRequestFactory}
|
||||
* if they need to share HTTP client resources.
|
||||
*
|
||||
* <p><strong>NOTE:</strong> As of 5.0 this class is in maintenance mode, with
|
||||
* only minor requests for changes and bugs to be accepted going forward. Please,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.web.reactive.function.client;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
|
@ -53,6 +54,7 @@ import org.springframework.util.Assert;
|
|||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.reactive.function.BodyExtractor;
|
||||
import org.springframework.web.reactive.function.BodyInserter;
|
||||
import org.springframework.web.reactive.function.BodyInserters;
|
||||
|
@ -713,10 +715,22 @@ class DefaultWebClient implements WebClient {
|
|||
}
|
||||
|
||||
private <T> Mono<T> insertCheckpoint(Mono<T> result, HttpStatusCode statusCode, HttpRequest request) {
|
||||
HttpMethod httpMethod = request.getMethod();
|
||||
HttpMethod method = request.getMethod();
|
||||
URI uri = getUriToLog(request);
|
||||
return result.checkpoint(statusCode + " from " + method + " " + uri + " [DefaultWebClient]");
|
||||
}
|
||||
|
||||
private static URI getUriToLog(HttpRequest request) {
|
||||
URI uri = request.getURI();
|
||||
String description = statusCode + " from " + httpMethod + " " + uri + " [DefaultWebClient]";
|
||||
return result.checkpoint(description);
|
||||
if (StringUtils.hasText(uri.getQuery())) {
|
||||
try {
|
||||
uri = new URI(uri.getScheme(), uri.getHost(), uri.getPath(), null);
|
||||
}
|
||||
catch (URISyntaxException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -73,9 +73,12 @@ public abstract class AbstractWebSocketSession<T> implements WebSocketSession {
|
|||
this.id = id;
|
||||
this.handshakeInfo = info;
|
||||
this.bufferFactory = bufferFactory;
|
||||
this.attributes.putAll(info.getAttributes());
|
||||
this.logPrefix = initLogPrefix(info, id);
|
||||
|
||||
info.getAttributes().entrySet().stream()
|
||||
.filter(entry -> (entry.getKey() != null && entry.getValue() != null))
|
||||
.forEach(entry -> this.attributes.put(entry.getKey(), entry.getValue()));
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(getLogPrefix() + "Session id \"" + getId() + "\" for " + getHandshakeInfo().getUri());
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -62,7 +62,9 @@ public abstract class AbstractWebSocketSession<T> implements NativeWebSocketSess
|
|||
*/
|
||||
public AbstractWebSocketSession(@Nullable Map<String, Object> attributes) {
|
||||
if (attributes != null) {
|
||||
this.attributes.putAll(attributes);
|
||||
attributes.entrySet().stream()
|
||||
.filter(entry -> (entry.getKey() != null && entry.getValue() != null))
|
||||
.forEach(entry -> this.attributes.put(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -36,6 +36,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
public class StandardWebSocketSessionTests {
|
||||
|
||||
private final HttpHeaders headers = new HttpHeaders();
|
||||
|
@ -53,7 +54,6 @@ public class StandardWebSocketSessionTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
public void getPrincipalWithNativeSession() {
|
||||
TestPrincipal user = new TestPrincipal("joe");
|
||||
|
||||
|
@ -67,7 +67,6 @@ public class StandardWebSocketSessionTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
public void getPrincipalNone() {
|
||||
Session nativeSession = Mockito.mock(Session.class);
|
||||
given(nativeSession.getUserPrincipal()).willReturn(null);
|
||||
|
@ -82,7 +81,6 @@ public class StandardWebSocketSessionTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
public void getAcceptedProtocol() {
|
||||
String protocol = "foo";
|
||||
|
||||
|
@ -98,4 +96,14 @@ public class StandardWebSocketSessionTests {
|
|||
verifyNoMoreInteractions(nativeSession);
|
||||
}
|
||||
|
||||
@Test // gh-29315
|
||||
public void addAttributesWithNullKeyOrValue() {
|
||||
this.attributes.put(null, "value");
|
||||
this.attributes.put("key", null);
|
||||
this.attributes.put("foo", "bar");
|
||||
|
||||
assertThat(new StandardWebSocketSession(this.headers, this.attributes, null, null).getAttributes())
|
||||
.hasSize(1).containsEntry("foo", "bar");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue