Skip to content

Commit 6767f70

Browse files
committed
Polishing contribution
Closes gh-29958
1 parent 8af1d8e commit 6767f70

File tree

10 files changed

+62
-50
lines changed

10 files changed

+62
-50
lines changed

spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpRequest.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -48,16 +48,17 @@ public interface ClientHttpRequest extends ReactiveHttpOutputMessage {
4848
*/
4949
MultiValueMap<String, HttpCookie> getCookies();
5050

51+
/**
52+
* Return a mutable map of the request attributes.
53+
* @since 6.2
54+
*/
55+
Map<String, Object> getAttributes();
56+
5157
/**
5258
* Return the request from the underlying HTTP library.
5359
* @param <T> the expected type of the request to cast to
5460
* @since 5.3
5561
*/
5662
<T> T getNativeRequest();
5763

58-
/**
59-
* Return a mutable map of the request attributes.
60-
*/
61-
Map<String, Object> getAttributes();
62-
6364
}

spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpRequestDecorator.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -76,6 +76,11 @@ public MultiValueMap<String, HttpCookie> getCookies() {
7676
return this.delegate.getCookies();
7777
}
7878

79+
@Override
80+
public Map<String, Object> getAttributes() {
81+
return this.delegate.getAttributes();
82+
}
83+
7984
@Override
8085
public DataBufferFactory bufferFactory() {
8186
return this.delegate.bufferFactory();
@@ -86,11 +91,6 @@ public <T> T getNativeRequest() {
8691
return this.delegate.getNativeRequest();
8792
}
8893

89-
@Override
90-
public Map<String, Object> getAttributes() {
91-
return this.delegate.getAttributes();
92-
}
93-
9494
@Override
9595
public void beforeCommit(Supplier<? extends Mono<Void>> action) {
9696
this.delegate.beforeCommit(action);

spring-web/src/main/java/org/springframework/http/client/reactive/HttpComponentsClientHttpRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ protected void applyCookies() {
163163
@Override
164164
protected void applyAttributes() {
165165
getAttributes().forEach((key, value) -> {
166-
if(this.context.getAttribute(key) == null) {
166+
if (this.context.getAttribute(key) == null) {
167167
this.context.setAttribute(key, value);
168168
}
169169
});

spring-web/src/main/java/org/springframework/http/client/reactive/JettyClientHttpRequest.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,6 @@ protected void applyCookies() {
138138
.forEach(this.jettyRequest::cookie);
139139
}
140140

141-
/**
142-
* Applies the attributes to {@link Request#getAttributes()}.
143-
*/
144-
@Override
145-
protected void applyAttributes() {
146-
getAttributes().forEach(this.jettyRequest::attribute);
147-
}
148-
149141
@Override
150142
protected void applyHeaders() {
151143
HttpHeaders headers = getHeaders();
@@ -162,6 +154,15 @@ protected HttpHeaders initReadOnlyHeaders() {
162154
return HttpHeaders.readOnlyHttpHeaders(new JettyHeadersAdapter(this.jettyRequest.getHeaders()));
163155
}
164156

157+
@Override
158+
protected void applyAttributes() {
159+
getAttributes().forEach((key, value) -> {
160+
if (this.jettyRequest.getAttributes().get(key) == null) {
161+
this.jettyRequest.attribute(key, value);
162+
}
163+
});
164+
}
165+
165166
public ReactiveRequest toReactiveRequest() {
166167
return this.builder.build();
167168
}

spring-web/src/main/java/org/springframework/http/client/reactive/ReactorClientHttpConnector.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,9 +17,11 @@
1717
package org.springframework.http.client.reactive;
1818

1919
import java.net.URI;
20+
import java.util.Map;
2021
import java.util.concurrent.atomic.AtomicReference;
2122
import java.util.function.Function;
2223

24+
import io.netty.util.AttributeKey;
2325
import org.apache.commons.logging.Log;
2426
import org.apache.commons.logging.LogFactory;
2527
import reactor.core.publisher.Mono;
@@ -49,6 +51,13 @@
4951
*/
5052
public class ReactorClientHttpConnector implements ClientHttpConnector, SmartLifecycle {
5153

54+
/**
55+
* Channel attribute key under which {@code WebClient} request attributes are stored as a Map.
56+
* @since 6.2
57+
*/
58+
public static final AttributeKey<Map<String, Object>> ATTRIBUTES_KEY =
59+
AttributeKey.valueOf(ReactorClientHttpRequest.class.getName() + ".ATTRIBUTES");
60+
5261
private static final Log logger = LogFactory.getLog(ReactorClientHttpConnector.class);
5362

5463
private static final Function<HttpClient, HttpClient> defaultInitializer = client -> client.compress(true);

spring-web/src/main/java/org/springframework/http/client/reactive/ReactorClientHttpRequest.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,11 +18,9 @@
1818

1919
import java.net.URI;
2020
import java.nio.file.Path;
21-
import java.util.Map;
2221

2322
import io.netty.buffer.ByteBuf;
2423
import io.netty.handler.codec.http.cookie.DefaultCookie;
25-
import io.netty.util.AttributeKey;
2624
import org.reactivestreams.Publisher;
2725
import reactor.core.publisher.Flux;
2826
import reactor.core.publisher.Mono;
@@ -48,8 +46,6 @@
4846
*/
4947
class ReactorClientHttpRequest extends AbstractClientHttpRequest implements ZeroCopyHttpOutputMessage {
5048

51-
public static final String ATTRIBUTES_CHANNEL_KEY = "attributes";
52-
5349
private final HttpMethod httpMethod;
5450

5551
private final URI uri;
@@ -141,14 +137,16 @@ protected void applyCookies() {
141137
}
142138

143139
/**
144-
* Applies the request attributes to the {@link reactor.netty.http.client.HttpClientRequest} by setting
145-
* a single {@link Map} into the {@link reactor.netty.channel.ChannelOperations#channel()},
146-
* with {@link io.netty5.util.AttributeKey#name()} equal to {@link #ATTRIBUTES_CHANNEL_KEY}.
140+
* Saves the {@link #getAttributes() request attributes} to the
141+
* {@link reactor.netty.channel.ChannelOperations#channel() channel} as a single map
142+
* attribute under the key {@link ReactorClientHttpConnector#ATTRIBUTES_KEY}.
147143
*/
148144
@Override
149145
protected void applyAttributes() {
150-
((ChannelOperations<?, ?>) this.request)
151-
.channel().attr(AttributeKey.valueOf(ATTRIBUTES_CHANNEL_KEY)).set(getAttributes());
146+
if (!getAttributes().isEmpty()) {
147+
((ChannelOperations<?, ?>) this.request).channel()
148+
.attr(ReactorClientHttpConnector.ATTRIBUTES_KEY).set(getAttributes());
149+
}
152150
}
153151

154152
@Override

spring-web/src/main/java/org/springframework/http/client/reactive/ReactorNetty2ClientHttpConnector.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,9 +17,11 @@
1717
package org.springframework.http.client.reactive;
1818

1919
import java.net.URI;
20+
import java.util.Map;
2021
import java.util.concurrent.atomic.AtomicReference;
2122
import java.util.function.Function;
2223

24+
import io.netty5.util.AttributeKey;
2325
import reactor.core.publisher.Mono;
2426
import reactor.netty5.NettyOutbound;
2527
import reactor.netty5.http.client.HttpClient;
@@ -41,6 +43,13 @@
4143
*/
4244
public class ReactorNetty2ClientHttpConnector implements ClientHttpConnector {
4345

46+
/**
47+
* Channel attribute key under which {@code WebClient} request attributes are stored as a Map.
48+
* @since 6.2
49+
*/
50+
public static final AttributeKey<Map<String, Object>> ATTRIBUTES_KEY =
51+
AttributeKey.valueOf(ReactorNetty2ClientHttpRequest.class.getName() + ".ATTRIBUTES");
52+
4453
private static final Function<HttpClient, HttpClient> defaultInitializer = client -> client.compress(true);
4554

4655

spring-web/src/main/java/org/springframework/http/client/reactive/ReactorNetty2ClientHttpRequest.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@
1818

1919
import java.net.URI;
2020
import java.nio.file.Path;
21-
import java.util.Map;
2221

2322
import io.netty5.buffer.Buffer;
2423
import io.netty5.handler.codec.http.headers.DefaultHttpCookiePair;
25-
import io.netty5.util.AttributeKey;
2624
import org.reactivestreams.Publisher;
2725
import reactor.core.publisher.Flux;
2826
import reactor.core.publisher.Mono;
@@ -49,8 +47,6 @@
4947
*/
5048
class ReactorNetty2ClientHttpRequest extends AbstractClientHttpRequest implements ZeroCopyHttpOutputMessage {
5149

52-
public static final String ATTRIBUTES_CHANNEL_KEY = "attributes";
53-
5450
private final HttpMethod httpMethod;
5551

5652
private final URI uri;
@@ -144,14 +140,16 @@ protected void applyCookies() {
144140
}
145141

146142
/**
147-
* Applies the request attributes to the {@link reactor.netty.http.client.HttpClientRequest} by setting
148-
* a single {@link Map} into the {@link reactor.netty.channel.ChannelOperations#channel()},
149-
* with {@link AttributeKey#name()} equal to {@link #ATTRIBUTES_CHANNEL_KEY}.
143+
* Saves the {@link #getAttributes() request attributes} to the
144+
* {@link reactor.netty.channel.ChannelOperations#channel() channel} as a single map
145+
* attribute under the key {@link ReactorNetty2ClientHttpConnector#ATTRIBUTES_KEY}.
150146
*/
151147
@Override
152148
protected void applyAttributes() {
153-
((ChannelOperations<?, ?>) this.request)
154-
.channel().attr(AttributeKey.valueOf(ATTRIBUTES_CHANNEL_KEY)).set(getAttributes());
149+
if (!getAttributes().isEmpty()) {
150+
((ChannelOperations<?, ?>) this.request).channel()
151+
.attr(ReactorNetty2ClientHttpConnector.ATTRIBUTES_KEY).set(getAttributes());
152+
}
155153
}
156154

157155
@Override

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,7 @@ public Mono<Void> writeTo(ClientHttpRequest request, ExchangeStrategies strategi
266266
}));
267267
}
268268

269-
Map<String, Object> requestAttributes = request.getAttributes();
270-
if (!this.attributes.isEmpty()) {
271-
this.attributes.forEach((key, value) -> requestAttributes.put(key, value));
272-
}
269+
request.getAttributes().putAll(this.attributes);
273270

274271
if (this.httpRequestConsumer != null) {
275272
this.httpRequestConsumer.accept(request);

spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import java.util.stream.Stream;
4242

4343
import io.netty.util.Attribute;
44-
import io.netty.util.AttributeKey;
4544
import okhttp3.mockwebserver.MockResponse;
4645
import okhttp3.mockwebserver.MockWebServer;
4746
import okhttp3.mockwebserver.RecordedRequest;
@@ -207,21 +206,21 @@ void applyAttributesToNativeRequest(ClientHttpConnector connector) {
207206
StepVerifier.create(result).expectComplete().verify();
208207

209208
if (nativeRequest.get() instanceof ChannelOperations<?,?> nativeReq) {
210-
Attribute<Map<String, Object>> attributes = nativeReq.channel().attr(AttributeKey.valueOf("attributes"));
209+
Attribute<Map<String, Object>> attributes = nativeReq.channel().attr(ReactorClientHttpConnector.ATTRIBUTES_KEY);
211210
assertThat(attributes.get()).isNotNull();
212211
assertThat(attributes.get()).containsEntry("foo", "bar");
213212
}
214213
else if (nativeRequest.get() instanceof reactor.netty5.channel.ChannelOperations<?,?> nativeReq) {
215214
io.netty5.util.Attribute<Map<String, Object>> attributes =
216-
nativeReq.channel().attr(io.netty5.util.AttributeKey.valueOf("attributes"));
215+
nativeReq.channel().attr(ReactorNetty2ClientHttpConnector.ATTRIBUTES_KEY);
217216
assertThat(attributes.get()).isNotNull();
218217
assertThat(attributes.get()).containsEntry("foo", "bar");
219218
}
220219
else if (nativeRequest.get() instanceof Request nativeReq) {
221220
assertThat(nativeReq.getAttributes()).containsEntry("foo", "bar");
222221
}
223222
else if (nativeRequest.get() instanceof org.apache.hc.core5.http.HttpRequest nativeReq) {
224-
// TODO get attributes from HttpClientContext
223+
// Attributes are not in the request, but in separate HttpClientContext
225224
}
226225
}
227226

0 commit comments

Comments
 (0)