Skip to content

Commit 384d274

Browse files
committed
Polishing in HttpServiceMethod
1 parent 5150a9a commit 384d274

File tree

4 files changed

+43
-60
lines changed

4 files changed

+43
-60
lines changed

framework-docs/modules/ROOT/pages/web/webflux/controller/ann-requestmapping.adoc

+1-6
Original file line numberDiff line numberDiff line change
@@ -605,9 +605,4 @@ For method parameters and returns values, generally, `@HttpExchange` supports a
605605
subset of the method parameters that `@RequestMapping` does. Notably, it excludes any
606606
server-side specific parameter types. For details, see the list for
607607
xref:integration/rest-clients.adoc#rest-http-interface-method-parameters[@HttpExchange] and
608-
xref:web/webflux/controller/ann-methods/arguments.adoc[@RequestMapping].
609-
610-
`@HttpExchange` also supports a `headers()` parameter which accepts `"name=value"`-like
611-
pairs like in `@RequestMapping(headers={})` on the client side. On the server side,
612-
this extends to the full syntax that
613-
xref:#webflux-ann-requestmapping-params-and-headers[`@RequestMapping`] supports.
608+
xref:web/webflux/controller/ann-methods/arguments.adoc[@RequestMapping].

spring-web/src/main/java/org/springframework/web/service/invoker/HttpServiceMethod.java

+35-50
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.util.ArrayList;
2323
import java.util.List;
2424
import java.util.Optional;
25-
import java.util.Set;
2625
import java.util.function.Function;
2726
import java.util.function.Supplier;
2827

@@ -160,7 +159,7 @@ private void applyArguments(HttpRequestValues.Builder requestValues, Object[] ar
160159
private record HttpRequestValuesInitializer(
161160
@Nullable HttpMethod httpMethod, @Nullable String url,
162161
@Nullable MediaType contentType, @Nullable List<MediaType> acceptMediaTypes,
163-
@Nullable MultiValueMap<String, String> otherHeaders,
162+
MultiValueMap<String, String> headers,
164163
Supplier<HttpRequestValues.Builder> requestValuesSupplier) {
165164

166165
public HttpRequestValues.Builder initializeRequestValuesBuilder() {
@@ -177,16 +176,8 @@ public HttpRequestValues.Builder initializeRequestValuesBuilder() {
177176
if (this.acceptMediaTypes != null) {
178177
requestValues.setAccept(this.acceptMediaTypes);
179178
}
180-
if (this.otherHeaders != null) {
181-
this.otherHeaders.forEach((name, values) -> {
182-
if (values.size() == 1) {
183-
requestValues.addHeader(name, values.get(0));
184-
}
185-
else {
186-
requestValues.addHeader(name, values.toArray(new String[0]));
187-
}
188-
});
189-
}
179+
this.headers.forEach((name, values) ->
180+
values.forEach(value -> requestValues.addHeader(name, value)));
190181
return requestValues;
191182
}
192183

@@ -217,10 +208,10 @@ public static HttpRequestValuesInitializer create(
217208
String url = initUrl(typeAnnotation, methodAnnotation, embeddedValueResolver);
218209
MediaType contentType = initContentType(typeAnnotation, methodAnnotation);
219210
List<MediaType> acceptableMediaTypes = initAccept(typeAnnotation, methodAnnotation);
220-
MultiValueMap<String, String> headers = initHeaders(typeAnnotation, methodAnnotation,
221-
embeddedValueResolver);
222-
return new HttpRequestValuesInitializer(httpMethod, url, contentType,
223-
acceptableMediaTypes, headers, requestValuesSupplier);
211+
MultiValueMap<String, String> headers = initHeaders(typeAnnotation, methodAnnotation, embeddedValueResolver);
212+
213+
return new HttpRequestValuesInitializer(
214+
httpMethod, url, contentType, acceptableMediaTypes, headers, requestValuesSupplier);
224215
}
225216

226217
@Nullable
@@ -296,48 +287,42 @@ private static List<MediaType> initAccept(@Nullable HttpExchange typeAnnotation,
296287
return null;
297288
}
298289

299-
private static MultiValueMap<String, String> parseHeaders(String[] headersArray,
290+
private static MultiValueMap<String, String> initHeaders(
291+
@Nullable HttpExchange typeAnnotation, HttpExchange methodAnnotation,
300292
@Nullable StringValueResolver embeddedValueResolver) {
293+
301294
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
302-
for (String h: headersArray) {
303-
String[] headerPair = StringUtils.split(h, "=");
304-
if (headerPair != null) {
305-
String headerName = headerPair[0].trim();
306-
List<String> headerValues = new ArrayList<>();
307-
Set<String> parsedValues = StringUtils.commaDelimitedListToSet(headerPair[1]);
308-
for (String headerValue : parsedValues) {
309-
if (embeddedValueResolver != null) {
310-
headerValue = embeddedValueResolver.resolveStringValue(headerValue);
311-
}
312-
if (headerValue != null) {
313-
headerValue = headerValue.trim();
314-
headerValues.add(headerValue);
315-
}
316-
}
317-
if (!headerValues.isEmpty()) {
318-
headers.addAll(headerName, headerValues);
319-
}
320-
}
295+
if (typeAnnotation != null) {
296+
addHeaders(typeAnnotation.headers(), embeddedValueResolver, headers);
321297
}
298+
addHeaders(methodAnnotation.headers(), embeddedValueResolver, headers);
322299
return headers;
323300
}
324301

325-
@Nullable
326-
private static MultiValueMap<String, String> initHeaders(@Nullable HttpExchange typeAnnotation, HttpExchange methodAnnotation,
327-
@Nullable StringValueResolver embeddedValueResolver) {
328-
MultiValueMap<String, String> methodLevelHeaders = parseHeaders(methodAnnotation.headers(),
329-
embeddedValueResolver);
330-
if (!ObjectUtils.isEmpty(methodLevelHeaders)) {
331-
return methodLevelHeaders;
332-
}
302+
private static void addHeaders(
303+
String[] rawValues, @Nullable StringValueResolver embeddedValueResolver,
304+
MultiValueMap<String, String> outputHeaders) {
333305

334-
MultiValueMap<String, String> typeLevelHeaders = (typeAnnotation != null ?
335-
parseHeaders(typeAnnotation.headers(), embeddedValueResolver) : null);
336-
if (!ObjectUtils.isEmpty(typeLevelHeaders)) {
337-
return typeLevelHeaders;
306+
for (String rawValue: rawValues) {
307+
String[] pair = StringUtils.split(rawValue, "=");
308+
if (pair == null) {
309+
continue;
310+
}
311+
String name = pair[0].trim();
312+
List<String> values = new ArrayList<>();
313+
for (String value : StringUtils.commaDelimitedListToSet(pair[1])) {
314+
if (embeddedValueResolver != null) {
315+
value = embeddedValueResolver.resolveStringValue(value);
316+
}
317+
if (value != null) {
318+
value = value.trim();
319+
values.add(value);
320+
}
321+
}
322+
if (!values.isEmpty()) {
323+
outputHeaders.addAll(name, values);
324+
}
338325
}
339-
340-
return null;
341326
}
342327

343328
private static List<AnnotationDescriptor> getAnnotationDescriptors(AnnotatedElement element) {

spring-web/src/test/java/org/springframework/web/service/invoker/HttpServiceMethodTests.java

+5-3
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-2025 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.
@@ -348,8 +348,10 @@ private interface MethodLevelAnnotatedService {
348348
@PostExchange(url = "/url", contentType = APPLICATION_JSON_VALUE, accept = APPLICATION_JSON_VALUE)
349349
void performPost();
350350

351-
@HttpExchange(contentType = APPLICATION_JSON_VALUE, headers = {"CustomHeader=a,b, c",
352-
"Content-Type=" + APPLICATION_NDJSON_VALUE}, method = "GET")
351+
@HttpExchange(
352+
method = "GET",
353+
contentType = APPLICATION_JSON_VALUE,
354+
headers = {"CustomHeader=a,b, c", "Content-Type=" + APPLICATION_NDJSON_VALUE})
353355
void performGetWithHeaders();
354356

355357
}

spring-webflux/src/test/java/org/springframework/web/reactive/result/method/annotation/RequestMappingHandlerMappingTests.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ public void defaultValuesExchange() {}
430430
@PostExchange(url = "/custom", contentType = "application/json", accept = "text/plain;charset=UTF-8")
431431
public void customValuesExchange(){}
432432

433-
@HttpExchange(method="GET", url = "/headers",
433+
@HttpExchange(
434+
method="GET", url = "/headers",
434435
headers = {"h1=hv1", "!h2", "Accept=application/ignored"})
435436
public String customHeadersExchange() {
436437
return "info";

0 commit comments

Comments
 (0)