This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 852a97c REST refactoring.
852a97c is described below
commit 852a97c7d611b24c2ba52ca036f99dbae71fe738
Author: JamesBognar <[email protected]>
AuthorDate: Thu Mar 4 13:36:32 2021 -0500
REST refactoring.
---
.../java/org/apache/juneau/http/HttpHeaders.java | 42 +++
.../org/apache/juneau/http/header/HeaderList.java | 79 +++++-
.../juneau/http/header/HeaderListBuilder.java | 134 +++++++++-
.../apache/juneau/http/header/HeaderSupplier.java | 292 ---------------------
.../java/org/apache/juneau/http/remote/Remote.java | 6 +-
.../rest/test/client/ThirdPartyProxyTest.java | 4 +-
.../org/apache/juneau/rest/client/RestClient.java | 9 +-
.../juneau/rest/client/RestClientBuilder.java | 4 +-
.../org/apache/juneau/rest/client/RestRequest.java | 16 +-
.../juneau/rest/client/remote/RemoteMeta.java | 17 +-
...aderSupplier_Test.java => HeaderList_Test.java} | 59 ++---
.../http/remote/Remote_HeaderAnnotation_Test.java | 20 +-
.../org/apache/juneau/http/remote/Remote_Test.java | 15 +-
.../rest/client/RestClient_Headers_Test.java | 2 +-
14 files changed, 326 insertions(+), 373 deletions(-)
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpHeaders.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpHeaders.java
index 289a2bf..2c3cc5a 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpHeaders.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpHeaders.java
@@ -3133,4 +3133,46 @@ public class HttpHeaders {
public static final BasicUriHeader uriHeader(String name, Supplier<?>
value) {
return BasicUriHeader.of(name, value);
}
+
+ /**
+ * Instantiates a new {@link HeaderListBuilder}.
+ *
+ * @return A new empty builder.
+ */
+ public static final HeaderListBuilder headerListBuilder() {
+ return HeaderList.create();
+ }
+
+ /**
+ * Creates a new {@link HeaderList} initialized with the specified
headers.
+ *
+ * @param headers The headers to add to the list. Can be
<jk>null</jk>. <jk>null</jk> entries are ignored.
+ * @return A new unmodifiable instance, never <jk>null</jk>.
+ */
+ public static final HeaderList headerList(List<Header> headers) {
+ return HeaderList.of(headers);
+ }
+
+ /**
+ * Creates a new {@link HeaderList} initialized with the specified
headers.
+ *
+ * @param headers The headers to add to the list. <jk>null</jk>
entries are ignored.
+ * @return A new unmodifiable instance, never <jk>null</jk>.
+ */
+ public static final HeaderList headerList(Header...headers) {
+ return HeaderList.of(headers);
+ }
+
+ /**
+ * Creates a new {@link HeaderList} initialized with the specified
name/value pairs.
+ *
+ * @param pairs
+ * Initial list of pairs.
+ * <br>Must be an even number of parameters representing key/value
pairs.
+ * @throws RuntimeException If odd number of parameters were specified.
+ * @return A new instance.
+ */
+ public static HeaderList headerList(Object...pairs) {
+ return HeaderList.ofPairs(pairs);
+ }
}
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderList.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderList.java
index 97b6d81..153e0a8 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderList.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderList.java
@@ -13,12 +13,16 @@
package org.apache.juneau.http.header;
import static java.util.Collections.*;
+import static org.apache.juneau.internal.StringUtils.*;
+import static java.util.Arrays.*;
+
import java.util.*;
import org.apache.http.*;
import org.apache.http.message.*;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.*;
+import org.apache.juneau.*;
/**
* An unmodifiable list of HTTP headers.
@@ -28,8 +32,11 @@ import org.apache.http.util.*;
*/
public class HeaderList implements Iterable<Header> {
+ /** Represents no header supplier in annotations. */
+ public static final class Null extends HeaderList {}
+
/** Predefined instance. */
- public static final HeaderList EMPTY = create().build();
+ public static final HeaderList EMPTY = new HeaderList();
private final List<Header> headers;
@@ -43,12 +50,78 @@ public class HeaderList implements Iterable<Header> {
}
/**
+ * Creates a new {@link HeaderList} initialized with the specified
headers.
+ *
+ * @param headers The headers to add to the list. Can be
<jk>null</jk>. <jk>null</jk> entries are ignored.
+ * @return A new unmodifiable instance, never <jk>null</jk>.
+ */
+ public static HeaderList of(List<Header> headers) {
+ return headers == null || headers.isEmpty() ? EMPTY : new
HeaderList(headers);
+ }
+
+ /**
+ * Creates a new {@link HeaderList} initialized with the specified
headers.
+ *
+ * @param headers The headers to add to the list. <jk>null</jk>
entries are ignored.
+ * @return A new unmodifiable instance, never <jk>null</jk>.
+ */
+ public static HeaderList of(Header...headers) {
+ return headers == null || headers.length == 0 ? EMPTY : new
HeaderList(asList(headers));
+ }
+
+ /**
+ * Creates a new {@link HeaderList} initialized with the specified
name/value pairs.
+ *
+ * @param pairs
+ * Initial list of pairs.
+ * <br>Must be an even number of parameters representing key/value
pairs.
+ * @throws RuntimeException If odd number of parameters were specified.
+ * @return A new instance.
+ */
+ public static HeaderList ofPairs(Object...pairs) {
+ if (pairs.length == 0)
+ return EMPTY;
+ if (pairs.length % 2 != 0)
+ throw new BasicRuntimeException("Odd number of
parameters passed into HeaderList.ofPairs()");
+ HeaderListBuilder b = create();
+ for (int i = 0; i < pairs.length; i+=2)
+ b.add(stringify(pairs[i]), pairs[i+1]);
+ return new HeaderList(b);
+ }
+
+ /**
* Constructor.
*
* @param builder The builder containing the settings for this bean.
*/
public HeaderList(HeaderListBuilder builder) {
- this.headers = new ArrayList<>(builder.headers);
+ this.headers = unmodifiableList(new
ArrayList<>(builder.headers));
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param headers The initial list of headers. <jk>null</jk> entries
are ignored.
+ */
+ public HeaderList(List<Header> headers) {
+ if (headers == null || headers.isEmpty())
+ this.headers = emptyList();
+ else {
+ List<Header> l = new ArrayList<>();
+ for (int i = 0; i < headers.size(); i++) {
+ Header x = headers.get(i);
+ if (x != null)
+ l.add(x);
+ }
+ this.headers = unmodifiableList(l);
+ }
+ }
+
+ /**
+ * Default constructor.
+ */
+ protected HeaderList() {
+ this.headers = emptyList();
}
/**
@@ -159,7 +232,7 @@ public class HeaderList implements Iterable<Header> {
* @return An unmodifiable list of all the headers in this list, or an
empty list if no headers are present.
*/
public List<Header> getAll() {
- return unmodifiableList(headers);
+ return headers;
}
/**
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderListBuilder.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderListBuilder.java
index 9f5e3e0..bb42e7e 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderListBuilder.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderListBuilder.java
@@ -12,10 +12,16 @@
//
***************************************************************************************************************************
package org.apache.juneau.http.header;
+import static org.apache.juneau.internal.StringUtils.*;
+
import java.util.*;
+import java.util.function.*;
import org.apache.http.*;
+import org.apache.juneau.httppart.*;
import org.apache.juneau.internal.*;
+import org.apache.juneau.oapi.*;
+import org.apache.juneau.svl.*;
/**
* Builder for {@link HeaderList} objects.
@@ -24,6 +30,10 @@ import org.apache.juneau.internal.*;
public class HeaderListBuilder {
final List<Header> headers = new ArrayList<>();
+ private volatile VarResolver varResolver;
+
+ /** Predefined instance. */
+ private static final HeaderList EMPTY = new HeaderList();
/**
* Constructor.
@@ -36,7 +46,46 @@ public class HeaderListBuilder {
* @return A new {@link HeaderList} bean.
*/
public HeaderList build() {
- return new HeaderList(this);
+ return headers.isEmpty() ? EMPTY : new HeaderList(this);
+ }
+
+ /**
+ * Allows header values to contain SVL variables.
+ *
+ * <p>
+ * Resolves variables in header values when using the following methods:
+ * <ul>
+ * <li class='jm'>{@link #add(String, Object) add(String,Object)}
+ * <li class='jm'>{@link #add(String, Supplier)
add(String,Supplier<?>)}
+ * <li class='jm'>{@link #add(String, Object,
HttpPartSerializerSession, HttpPartSchema, boolean)
add(String,Object,HttpPartSerializerSession,HttpPartSchema,boolean)}
+ * </ul>
+ *
+ * <p>
+ * Uses {@link VarResolver#DEFAULT} to resolve variables.
+ *
+ * @return This object (for method chaining).
+ */
+ public HeaderListBuilder resolving() {
+ return resolving(VarResolver.DEFAULT);
+ }
+
+ /**
+ * Allows header values to contain SVL variables.
+ *
+ * <p>
+ * Resolves variables in header values when using the following methods:
+ * <ul>
+ * <li class='jm'>{@link #add(String, Object) add(String,Object)}
+ * <li class='jm'>{@link #add(String, Supplier)
add(String,Supplier<?>)}
+ * <li class='jm'>{@link #add(String, Object,
HttpPartSerializerSession, HttpPartSchema, boolean)
add(String,Object,HttpPartSerializerSession,HttpPartSchema,boolean)}
+ * </ul>
+ *
+ * @param varResolver The variable resolver to use for resolving
variables.
+ * @return This object (for method chaining).
+ */
+ public HeaderListBuilder resolving(VarResolver varResolver) {
+ this.varResolver = varResolver;
+ return this;
}
/**
@@ -72,8 +121,61 @@ public class HeaderListBuilder {
*/
@FluentSetter
public HeaderListBuilder add(String name, String value) {
- headers.add(new BasicHeader(name, value));
- return this;
+ Header x = isResolving() ? new BasicHeader(name,
resolver(value)) : new BasicHeader(name, value);
+ return add(x);
+ }
+
+ /**
+ * Appends the specified header to the end of this list.
+ *
+ * <p>
+ * The header is added as a {@link BasicHeader}.
+ *
+ * @param name The header name.
+ * @param value The header value.
+ * @return This object (for method chaining).
+ */
+ public HeaderListBuilder add(String name, Object value) {
+ Header x = isResolving() ? new BasicHeader(name,
resolver(value)) : new BasicHeader(name, value);
+ return add(x);
+ }
+
+ /**
+ * Appends the specified header to the end of this list using a value
supplier.
+ *
+ * <p>
+ * The header is added as a {@link BasicHeader}.
+ *
+ * <p>
+ * Value is re-evaluated on each call to {@link BasicHeader#getValue()}.
+ *
+ * @param name The header name.
+ * @param value The header value supplier.
+ * @return This object (for method chaining).
+ */
+ public HeaderListBuilder add(String name, Supplier<?> value) {
+ Header x = isResolving() ? new BasicHeader(name,
resolver(value)) : new BasicHeader(name, value);
+ return add(x);
+ }
+
+ /**
+ * Appends the specified header to the end of this list.
+ *
+ * @param name The header name.
+ * @param value The header value.
+ * @param serializer
+ * The serializer to use for serializing the value to a string
value.
+ * @param schema
+ * The schema object that defines the format of the output.
+ * <br>If <jk>null</jk>, defaults to the schema defined on the
parser.
+ * <br>If that's also <jk>null</jk>, defaults to {@link
HttpPartSchema#DEFAULT}.
+ * <br>Only used if serializer is schema-aware (e.g. {@link
OpenApiSerializer}).
+ * @param skipIfEmpty If value is a blank string, the value should
return as <jk>null</jk>.
+ * @return This object (for method chaining).
+ */
+ public HeaderListBuilder add(String name, Object value,
HttpPartSerializerSession serializer, HttpPartSchema schema, boolean
skipIfEmpty) {
+ Header x = isResolving() ? new SerializedHeader(name,
resolver(value), serializer, schema, skipIfEmpty) : new SerializedHeader(name,
value, serializer, schema, skipIfEmpty);
+ return add(x);
}
/**
@@ -103,6 +205,18 @@ public class HeaderListBuilder {
}
/**
+ * Adds the specified headers to the end of the headers in this builder.
+ *
+ * @param values The headers to add. <jk>null</jk> values are ignored.
+ * @return This object (for method chaining).
+ */
+ public HeaderListBuilder add(HeaderList values) {
+ if (values != null)
+ add(values.getAll());
+ return this;
+ }
+
+ /**
* Removes the specified header from this builder.
*
* @param value The header to remove. <jk>null</jk> values are ignored.
@@ -300,6 +414,20 @@ public class HeaderListBuilder {
return this;
}
+ private boolean isResolving() {
+ return varResolver != null;
+ }
+
+ private Supplier<Object> resolver(Object input) {
+ return ()->(varResolver == null ? unwrap(input) :
varResolver.resolve(stringify(unwrap(input))));
+ }
+
+ private Object unwrap(Object o) {
+ while (o instanceof Supplier)
+ o = ((Supplier<?>)o).get();
+ return o;
+ }
+
// <FluentSetters>
// </FluentSetters>
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderSupplier.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderSupplier.java
deleted file mode 100644
index f14dd24..0000000
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/header/HeaderSupplier.java
+++ /dev/null
@@ -1,292 +0,0 @@
-//
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
-// * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
-// * with the License. You may obtain a copy of the License at
*
-// *
*
-// * http://www.apache.org/licenses/LICENSE-2.0
*
-// *
*
-// * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
-// * specific language governing permissions and limitations under the
License. *
-//
***************************************************************************************************************************
-package org.apache.juneau.http.header;
-
-import static org.apache.juneau.internal.StringUtils.*;
-
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.function.*;
-import java.util.stream.*;
-
-import org.apache.http.*;
-import org.apache.juneau.*;
-import org.apache.juneau.httppart.*;
-import org.apache.juneau.internal.*;
-import org.apache.juneau.marshall.*;
-import org.apache.juneau.oapi.*;
-import org.apache.juneau.svl.*;
-
-/**
- * Specifies a dynamic supplier of {@link Header} objects.
- *
- * This class is thread safe.
- */
-public class HeaderSupplier implements Iterable<Header> {
-
- /** Represents no header supplier */
- public static final class Null extends HeaderSupplier {}
-
- private final List<Iterable<Header>> headers = new
CopyOnWriteArrayList<>();
-
- private volatile VarResolver varResolver;
-
- /**
- * Convenience creator.
- *
- * @return A new {@link HeaderSupplier} object.
- */
- public static HeaderSupplier create() {
- return new HeaderSupplier();
- }
-
- /**
- * Creates an empty instance.
- *
- * @return A new empty instance.
- */
- public static HeaderSupplier of() {
- return new HeaderSupplier();
- }
-
- /**
- * Creates an instance initialized with the specified headers.
- *
- * @param headers The headers to add to this list.
- * @return A new instance.
- */
- public static HeaderSupplier of(Collection<Header> headers) {
- return new HeaderSupplier().addAll(headers);
- }
-
- /**
- * Creates an instance initialized with the specified name/value pairs.
- *
- * @param parameters
- * Initial list of parameters.
- * <br>Must be an even number of parameters representing key/value
pairs.
- * @throws RuntimeException If odd number of parameters were specified.
- * @return A new instance.
- */
- public static HeaderSupplier ofPairs(Object...parameters) {
- HeaderSupplier s = HeaderSupplier.create();
- if (parameters.length % 2 != 0)
- throw new BasicRuntimeException("Odd number of
parameters passed into HeaderSupplier.ofPairs()");
- for (int i = 0; i < parameters.length; i+=2)
- s.add(stringify(parameters[i]), parameters[i+1]);
- return s;
- }
-
- /**
- * Convenience creator.
- *
- * @param values
- * The values to populate this supplier with.
- * <br>Can be any of the following types:
- * <ul>
- * <li>{@link Header}.
- * <li>{@link HeaderSupplier}.
- * </ul>
- * @return A new {@link HeaderSupplier} object.
- */
- public static HeaderSupplier of(Object...values) {
- HeaderSupplier s = HeaderSupplier.create();
- for (Object v : values) {
- if (v instanceof Header)
- s.add((Header)v);
- else if (v instanceof HeaderSupplier)
- s.add((HeaderSupplier)v);
- else if (v != null)
- throw new BasicRuntimeException("Invalid type
passed to HeaderSupplier.of(): {0}", v.getClass().getName());
- }
- return s;
- }
-
- /**
- * Allows header values to contain SVL variables.
- *
- * <p>
- * Resolves variables in header values when using the following methods:
- * <ul>
- * <li class='jm'>{@link #ofPairs(Object...) ofPairs(Object...)}
- * <li class='jm'>{@link #add(String, Object) add(String,Object)}
- * <li class='jm'>{@link #add(String, Supplier)
add(String,Supplier<?>)}
- * <li class='jm'>{@link #add(String, Object,
HttpPartSerializerSession, HttpPartSchema, boolean)
add(String,Object,HttpPartSerializerSession,HttpPartSchema,boolean)}
- * </ul>
- *
- * <p>
- * Uses {@link VarResolver#DEFAULT} to resolve variables.
- *
- * @return This object (for method chaining).
- */
- public HeaderSupplier resolving() {
- return resolving(VarResolver.DEFAULT);
- }
-
- /**
- * Allows header values to contain SVL variables.
- *
- * <p>
- * Resolves variables in header values when using the following methods:
- * <ul>
- * <li class='jm'>{@link #ofPairs(Object...) ofPairs(Object...)}
- * <li class='jm'>{@link #add(String, Object) add(String,Object)}
- * <li class='jm'>{@link #add(String, Supplier)
add(String,Supplier<?>)}
- * <li class='jm'>{@link #add(String, Object,
HttpPartSerializerSession, HttpPartSchema, boolean)
add(String,Object,HttpPartSerializerSession,HttpPartSchema,boolean)}
- * </ul>
- *
- * @param varResolver The variable resolver to use for resolving
variables.
- * @return This object (for method chaining).
- */
- public HeaderSupplier resolving(VarResolver varResolver) {
- this.varResolver = varResolver;
- return this;
- }
-
- /**
- * Add a header to this supplier.
- *
- * @param h The header to add. <jk>null</jk> values are ignored.
- * @return This object (for method chaining).
- */
- public HeaderSupplier add(Header h) {
- if (h != null)
- headers.add(Collections.singleton(h));
- return this;
- }
-
- /**
- * Add a supplier to this supplier.
- *
- * @param h The supplier to add. <jk>null</jk> values are ignored.
- * @return This object (for method chaining).
- */
- public HeaderSupplier add(HeaderSupplier h) {
- if (h != null)
- headers.add(h);
- return this;
- }
-
- /**
- * Adds all the specified headers to this supplier.
- *
- * @param headers The headers to add to this supplier.
- * @return This object(for method chaining).
- */
- private HeaderSupplier addAll(Collection<Header> headers) {
- this.headers.addAll(headers.stream().filter(x->x !=
null).map(x->Collections.singleton(x)).collect(Collectors.toList()));
- return this;
- }
-
-
//------------------------------------------------------------------------------------------------------------------
- // Appenders
-
//------------------------------------------------------------------------------------------------------------------
-
- /**
- * Appends the specified header to the end of this list.
- *
- * <p>
- * The header is added as a {@link BasicHeader}.
- *
- * @param name The header name.
- * @param value The header value.
- * @return This object (for method chaining).
- */
- public HeaderSupplier add(String name, Object value) {
- return add(new BasicHeader(name, resolver(value)));
- }
-
- /**
- * Appends the specifiedheader to the end of this list using a value
supplier.
- *
- * <p>
- * The header is added as a {@link BasicHeader}.
- *
- * <p>
- * Value is re-evaluated on each call to {@link BasicHeader#getValue()}.
- *
- * @param name The header name.
- * @param value The header value supplier.
- * @return This object (for method chaining).
- */
- public HeaderSupplier add(String name, Supplier<?> value) {
- return add(new BasicHeader(name, resolver(value)));
- }
-
- /**
- * Appends the specified header to the end of this list.
- *
- * @param name The header name.
- * @param value The header value.
- * @param serializer
- * The serializer to use for serializing the value to a string
value.
- * @param schema
- * The schema object that defines the format of the output.
- * <br>If <jk>null</jk>, defaults to the schema defined on the
parser.
- * <br>If that's also <jk>null</jk>, defaults to {@link
HttpPartSchema#DEFAULT}.
- * <br>Only used if serializer is schema-aware (e.g. {@link
OpenApiSerializer}).
- * @param skipIfEmpty If value is a blank string, the value should
return as <jk>null</jk>.
- * @return This object (for method chaining).
- */
- public HeaderSupplier add(String name, Object value,
HttpPartSerializerSession serializer, HttpPartSchema schema, boolean
skipIfEmpty) {
- return add(new SerializedHeader(name, resolver(value),
serializer, schema, skipIfEmpty));
- }
-
- /**
- * Returns this list as a JSON list of strings.
- */
- @Override /* Object */
- public String toString() {
- return SimpleJson.DEFAULT.toString(toArray());
- }
-
- @Override
- public Iterator<Header> iterator() {
- return CollectionUtils.iterator(headers);
- }
-
- /**
- * Returns these headers as an array.
- *
- * @return These headers as an array.
- */
- public Header[] toArray() {
- ArrayList<Header> l = new ArrayList<>();
- for (Header p : this)
- l.add(p);
- return l.toArray(new Header[l.size()]);
- }
-
- /**
- * Returns these headers as an array.
- *
- * @param array The array to copy in to.
- * @return These headers as an array.
- */
- public <T extends Header> T[] toArray(T[] array) {
- ArrayList<Header> l = new ArrayList<>();
- for (Header p : this)
- l.add(p);
- return l.toArray(array);
- }
-
- private Supplier<Object> resolver(Object input) {
- return ()->(varResolver == null ? unwrap(input) :
varResolver.resolve(stringify(unwrap(input))));
- }
-
- private Object unwrap(Object o) {
- while (o instanceof Supplier)
- o = ((Supplier<?>)o).get();
- return o;
- }
-}
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/remote/Remote.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/remote/Remote.java
index c33758d..68fde15 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/remote/Remote.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/remote/Remote.java
@@ -66,17 +66,17 @@ public @interface Remote {
String[] headers() default {};
/**
- * Default request header supplier.
+ * Default request header list.
*
* <p>
- * Specifies a dynamic supplier of headers to set on all requests.
+ * Specifies a supplier of headers to set on all requests.
*
* <ul class='notes'>
* <li>
* Supplier class must provide a public no-arg constructor.
* </ul>
*/
- Class<? extends HeaderSupplier> headerSupplier() default
HeaderSupplier.Null.class;
+ Class<? extends HeaderList> headerList() default HeaderList.Null.class;
/**
* Specifies the client version of this interface.
diff --git
a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyTest.java
b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyTest.java
index 7b1ce5b..04914fb 100644
---
a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyTest.java
+++
b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyTest.java
@@ -234,7 +234,7 @@ public class ThirdPartyProxyTest extends RestTestcase {
@Test
public void a10_nameValuePairsHeader() throws Exception {
String r = proxy.nameValuePairsHeader(
- HeaderSupplier.ofPairs("a","foo","b","","c",null)
+ HeaderList.ofPairs("a","foo","b","","c",null)
);
assertEquals("OK", r);
}
@@ -1619,7 +1619,7 @@ public class ThirdPartyProxyTest extends RestTestcase {
@RemoteOp(method="GET", path="/nameValuePairsHeader")
String nameValuePairsHeader(
- @Header(value="*", allowEmptyValue=true) HeaderSupplier
a
+ @Header(value="*", allowEmptyValue=true) HeaderList a
);
//-------------------------------------------------------------------------------------------------------------
diff --git
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index 63c36a4..a68eabb 100644
---
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -1971,7 +1971,7 @@ public class RestClient extends BeanContext implements
HttpClient, Closeable, Re
static final String RESTCLIENT_httpClient = PREFIX + "httpClient.o";
static final String RESTCLIENT_httpClientBuilder= PREFIX +
"httpClientBuilder.o";
- private final HeaderSupplier headers;
+ private final HeaderList headers;
private final PartSupplier query, formData;
final CloseableHttpClient httpClient;
private final HttpClientConnectionManager connectionManager;
@@ -2088,14 +2088,15 @@ public class RestClient extends BeanContext implements
HttpClient, Closeable, Re
HttpPartSerializerSession partSerializerSession =
partSerializer.createPartSession(null);
- this.headers = HeaderSupplier.create();
+ HeaderListBuilder headers = HeaderList.create();
for (Object o : cp.getList(RESTCLIENT_headers,
Object.class).orElse(emptyList())) {
o = buildBuilders(o, partSerializerSession);
- if (o instanceof HeaderSupplier)
- headers.add((HeaderSupplier)o);
+ if (o instanceof HeaderList)
+ headers.add((HeaderList)o);
else
headers.add(BasicHeader.cast(o));
}
+ this.headers = headers.build();
this.query = PartSupplier.create();
for (Object o : cp.getList(RESTCLIENT_query,
Object.class).orElse(emptyList())) {
diff --git
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
index 47e4dc0..8344a5a 100644
---
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
+++
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
@@ -1280,7 +1280,7 @@ public class RestClientBuilder extends BeanContextBuilder
{
* <li>{@link Header} (including any subclasses such as
{@link Accept})
* <li>{@link Headerable}
* <li>{@link java.util.Map.Entry}
- * <li>{@link HeaderSupplier}
+ * <li>{@link HeaderList}
* <li>{@link Map}
* <ul>
* <li>Values can be any POJO.
@@ -1293,7 +1293,7 @@ public class RestClientBuilder extends BeanContextBuilder
{
@FluentSetter
public RestClientBuilder headers(Object...headers) {
for (Object h : headers) {
- if (BasicHeader.canCast(h) || h instanceof
HeaderSupplier) {
+ if (BasicHeader.canCast(h) || h instanceof HeaderList) {
appendTo(RESTCLIENT_headers, h);
} else if (h instanceof Map) {
for (Map.Entry<Object,Object> e :
toMap(h).entrySet())
diff --git
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
index b5e8dd0..2b9ec73 100644
---
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
+++
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
@@ -2166,7 +2166,7 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
* <li>{@link Header} (including any subclasses such as
{@link Accept})
* <li>{@link Headerable}
* <li>{@link java.util.Map.Entry}
- * <li>{@link HeaderSupplier}
+ * <li>{@link HeaderList}
* <li>{@link Map}
* <ul>
* <li>Values can be any POJO.
@@ -2210,7 +2210,7 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
* <li>{@link Header} (including any subclasses such as
{@link Accept})
* <li>{@link Headerable}
* <li>{@link java.util.Map.Entry}
- * <li>{@link HeaderSupplier}
+ * <li>{@link HeaderList}
* <li>{@link Map}
* <ul>
* <li>Values can be any POJO.
@@ -2226,8 +2226,8 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
for (Object o : headers) {
if (BasicHeader.canCast(o)) {
l.add(BasicHeader.cast(o));
- } else if (o instanceof HeaderSupplier) {
- for (Header h : (HeaderSupplier)o)
+ } else if (o instanceof HeaderList) {
+ for (Header h : (HeaderList)o)
l.add(h);
} else if (o instanceof Collection) {
for (Object o2 : (Collection<?>)o)
@@ -2279,7 +2279,7 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
RestRequest headerArg(EnumSet<AddFlag> flags, String name, Object
value, HttpPartSchema schema, HttpPartSerializerSession serializer) throws
RestCallException {
flags = AddFlag.orDefault(flags);
- boolean isMulti = isEmpty(name) || "*".equals(name) || value
instanceof HeaderSupplier || isHeaderArray(value);
+ boolean isMulti = isEmpty(name) || "*".equals(name) || value
instanceof HeaderList || isHeaderArray(value);
if (! isMulti)
return innerHeaders(flags,
AList.of(serializedHeader(name, value, serializer, schema, flags)));
@@ -2288,9 +2288,9 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
if (BasicHeader.canCast(value)) {
l.add(BasicHeader.cast(value));
- } else if (value instanceof HeaderSupplier) {
- for (Object o : (HeaderSupplier)value)
- l.add(BasicHeader.cast(o));
+ } else if (value instanceof HeaderList) {
+ for (Header o : (HeaderList)value)
+ l.add(o);
} else if (value instanceof Collection) {
for (Object o : (Collection<?>)value)
l.add(BasicHeader.cast(o));
diff --git
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMeta.java
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMeta.java
index 37e8120..f2e0b60 100644
---
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMeta.java
+++
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/remote/RemoteMeta.java
@@ -17,7 +17,6 @@ import static org.apache.juneau.internal.StringUtils.*;
import java.lang.reflect.*;
import java.util.*;
-import org.apache.http.*;
import org.apache.juneau.collections.*;
import org.apache.juneau.http.header.*;
import org.apache.juneau.http.remote.*;
@@ -38,7 +37,7 @@ import org.apache.juneau.svl.*;
public class RemoteMeta {
private final Map<Method,RemoteOperationMeta> operations;
- private final HeaderSupplier headerSupplier =
HeaderSupplier.create().resolving();
+ private final HeaderList headerList;
/**
* Constructor.
@@ -54,19 +53,20 @@ public class RemoteMeta {
path = trimSlashes(r.path());
String versionHeader = "Client-Version", clientVersion = null;
+ HeaderListBuilder headerListBuilder =
HeaderList.create().resolving();
for (Remote r : ci.getAnnotations(Remote.class)) {
if (! r.path().isEmpty())
path = trimSlashes(resolve(r.path()));
for (String h : r.headers())
- headerSupplier.add(basicHeader(resolve(h)));
+ headerListBuilder.add(basicHeader(resolve(h)));
if (! r.version().isEmpty())
clientVersion = resolve(r.version());
if (! r.versionHeader().isEmpty())
versionHeader = resolve(r.versionHeader());
- if (r.headerSupplier() != HeaderSupplier.Null.class) {
+ if (r.headerList() != HeaderList.Null.class) {
try {
-
headerSupplier.add(r.headerSupplier().newInstance());
+
headerListBuilder.add(r.headerList().newInstance().getAll());
} catch (Exception e) {
throw new RuntimeException("Could not
instantiate HeaderSupplier class.", e);
}
@@ -74,13 +74,14 @@ public class RemoteMeta {
}
if (clientVersion != null)
- headerSupplier.add(stringHeader(versionHeader,
clientVersion));
+ headerListBuilder.add(stringHeader(versionHeader,
clientVersion));
AMap<Method,RemoteOperationMeta> operations = AMap.create();
for (MethodInfo m : ci.getPublicMethods())
operations.put(m.inner(), new RemoteOperationMeta(path,
m.inner(), "GET"));
this.operations = operations.unmodifiable();
+ this.headerList = headerListBuilder.build();
}
/**
@@ -98,8 +99,8 @@ public class RemoteMeta {
*
* @return The headers to set on all requests.
*/
- public Iterable<Header> getHeaders() {
- return headerSupplier;
+ public HeaderList getHeaders() {
+ return headerList;
}
//------------------------------------------------------------------------------------------------------------------
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/http/HeaderSupplier_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/http/HeaderList_Test.java
similarity index 60%
rename from
juneau-utest/src/test/java/org/apache/juneau/http/HeaderSupplier_Test.java
rename to juneau-utest/src/test/java/org/apache/juneau/http/HeaderList_Test.java
index 4d96cff..0de66ae 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/HeaderSupplier_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/HeaderList_Test.java
@@ -24,56 +24,54 @@ import org.apache.juneau.oapi.*;
import org.junit.*;
@FixMethodOrder(NAME_ASCENDING)
-public class HeaderSupplier_Test {
+public class HeaderList_Test {
@Test
public void a01_basic() {
- HeaderSupplier x = HeaderSupplier.of();
+ HeaderListBuilder x = HeaderList.create();
- assertObject(x.iterator()).asJson().is("[]");
+ assertObject(x.build().iterator()).asJson().is("[]");
x.add(header("Foo","bar"));
- assertObject(x.iterator()).asJson().is("['Foo: bar']");
+ assertObject(x.build().iterator()).asJson().is("['Foo: bar']");
x.add(header("Foo","baz"));
- assertObject(x.iterator()).asJson().is("['Foo: bar','Foo:
baz']");
- x.add(HeaderSupplier.of());
- assertObject(x.iterator()).asJson().is("['Foo: bar','Foo:
baz']");
- x.add(HeaderSupplier.of(header("Foo","qux")));
- assertObject(x.iterator()).asJson().is("['Foo: bar','Foo:
baz','Foo: qux']");
- x.add(HeaderSupplier.of(header("Foo","q2x"),
header("Foo","q3x")));
- assertObject(x.iterator()).asJson().is("['Foo: bar','Foo:
baz','Foo: qux','Foo: q2x','Foo: q3x']");
-
x.add(HeaderSupplier.of(HeaderSupplier.of(header("Foo","q4x"),header("Foo","q5x"))));
- assertObject(x.iterator()).asJson().is("['Foo: bar','Foo:
baz','Foo: qux','Foo: q2x','Foo: q3x','Foo: q4x','Foo: q5x']");
+ assertObject(x.build().iterator()).asJson().is("['Foo:
bar','Foo: baz']");
+ x.add(HeaderList.of());
+ assertObject(x.build().iterator()).asJson().is("['Foo:
bar','Foo: baz']");
+ x.add(HeaderList.of(header("Foo","qux")));
+ assertObject(x.build().iterator()).asJson().is("['Foo:
bar','Foo: baz','Foo: qux']");
+ x.add(HeaderList.of(header("Foo","q2x"), header("Foo","q3x")));
+ assertObject(x.build().iterator()).asJson().is("['Foo:
bar','Foo: baz','Foo: qux','Foo: q2x','Foo: q3x']");
+ x.add(HeaderList.of(header("Foo","q4x"), header("Foo","q5x")));
+ assertObject(x.build().iterator()).asJson().is("['Foo:
bar','Foo: baz','Foo: qux','Foo: q2x','Foo: q3x','Foo: q4x','Foo: q5x']");
x.add((Header)null);
- assertObject(x.iterator()).asJson().is("['Foo: bar','Foo:
baz','Foo: qux','Foo: q2x','Foo: q3x','Foo: q4x','Foo: q5x']");
- x.add((HeaderSupplier)null);
- assertObject(x.iterator()).asJson().is("['Foo: bar','Foo:
baz','Foo: qux','Foo: q2x','Foo: q3x','Foo: q4x','Foo: q5x']");
+ assertObject(x.build().iterator()).asJson().is("['Foo:
bar','Foo: baz','Foo: qux','Foo: q2x','Foo: q3x','Foo: q4x','Foo: q5x']");
+ x.add((HeaderList)null);
+ assertObject(x.build().iterator()).asJson().is("['Foo:
bar','Foo: baz','Foo: qux','Foo: q2x','Foo: q3x','Foo: q4x','Foo: q5x']");
- assertObject(new
HeaderSupplier.Null().iterator()).asJson().is("[]");
+ assertObject(new
HeaderList.Null().iterator()).asJson().is("[]");
}
@Test
public void a02_creators() {
- HeaderSupplier x;
+ HeaderList x;
- x = HeaderSupplier.of(header("Foo","bar"), header("Foo","baz"),
null);
+ x = HeaderList.of(header("Foo","bar"), header("Foo","baz"),
null);
assertObject(x.iterator()).asJson().is("['Foo: bar','Foo:
baz']");
- x = HeaderSupplier.of(AList.of(header("Foo","bar"),
header("Foo","baz"), null));
+ x = HeaderList.of(AList.of(header("Foo","bar"),
header("Foo","baz"), null));
assertObject(x.iterator()).asJson().is("['Foo: bar','Foo:
baz']");
- x = HeaderSupplier.ofPairs("Foo","bar","Foo","baz");
+ x = HeaderList.ofPairs("Foo","bar","Foo","baz");
assertObject(x.iterator()).asJson().is("['Foo: bar','Foo:
baz']");
- assertThrown(()->HeaderSupplier.ofPairs("Foo")).is("Odd number
of parameters passed into HeaderSupplier.ofPairs()");
-
- assertThrown(()->HeaderSupplier.of("Foo")).is("Invalid type
passed to HeaderSupplier.of(): java.lang.String");
+ assertThrown(()->HeaderList.ofPairs("Foo")).is("Odd number of
parameters passed into HeaderList.ofPairs()");
}
@Test
public void a03_addMethods() {
String pname = "HeaderSupplierTest.x";
- HeaderSupplier x = HeaderSupplier.create().resolving();
+ HeaderListBuilder x = HeaderList.create().resolving();
System.setProperty(pname, "y");
x.add("X1","bar");
@@ -83,23 +81,22 @@ public class HeaderSupplier_Test {
x.add("X5","bar",openApiSession(),null,false);
x.add("X6","$S{"+pname+"}",openApiSession(),null,false);
- assertString(x.toString()).is("['X1: bar','X2: y','X3:
bar','X4: y','X5: bar','X6: y']");
+ assertString(x.build().toString()).is("[X1: bar, X2: y, X3:
bar, X4: y, X5: bar, X6: y]");
System.setProperty(pname, "z");
- assertString(x.toString()).is("['X1: bar','X2: z','X3:
bar','X4: z','X5: bar','X6: z']");
+ assertString(x.build().toString()).is("[X1: bar, X2: z, X3:
bar, X4: z, X5: bar, X6: z]");
System.clearProperty(pname);
}
@Test
public void a04_toArrayMethods() {
- HeaderSupplier x = HeaderSupplier
+ HeaderListBuilder x = HeaderList
.create()
.add("X1","1")
- .add(HeaderSupplier.ofPairs("X2","2"));
- assertObject(x.toArray()).asJson().is("['X1: 1','X2: 2']");
- assertObject(x.toArray(new Header[0])).asJson().is("['X1:
1','X2: 2']");
+ .add(HeaderList.ofPairs("X2","2"));
+ assertObject(x.build().getAll()).asJson().is("['X1: 1','X2:
2']");
}
//-----------------------------------------------------------------------------------------------------------------
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
index 546ff5b..b577487 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
@@ -77,8 +77,8 @@ public class Remote_HeaderAnnotation_Test {
@RemoteOp(path="a") String getX12(@Header Map<String,Bean> b);
@RemoteOp(path="a") String getX13(@Header(n="x",f="uon")
Map<String,Bean> b);
@RemoteOp(path="a") String getX14(@Header(format="uon")
Map<String,Bean> b);
- @RemoteOp(path="a") String getX15(@Header("*") HeaderSupplier
b);
- @RemoteOp(path="a") String getX16(@Header HeaderSupplier b);
+ @RemoteOp(path="a") String getX15(@Header("*") HeaderList b);
+ @RemoteOp(path="a") String getX16(@Header HeaderList b);
@RemoteOp(path="a") String getX17(@Header
org.apache.http.Header b);
@RemoteOp(path="a") String getX18(@Header
org.apache.http.Header[] b);
@RemoteOp(path="a") String getX19(@Header String b);
@@ -794,28 +794,28 @@ public class Remote_HeaderAnnotation_Test {
public static class K3a {
@Header(aev=true)
- public HeaderSupplier getA() {
+ public HeaderList getA() {
return headers("a1","v1","a2",123,"a3",null,"a4","");
}
@Header(value="*",aev=true)
- public HeaderSupplier getB() {
+ public HeaderList getB() {
return headers("b1","true","b2","123","b3","null");
}
@Header(n="*",aev=true)
- public HeaderSupplier getC() {
+ public HeaderList getC() {
return headers("c1","v1","c2",123,"c3",null,"c4","");
}
@Header(value="*",aev=true)
- public HeaderSupplier getD() {
+ public HeaderList getD() {
return null;
}
@Header(aev=true)
public org.apache.http.Header[] getE() {
- return
headers("e1","v1","e2",123,"e3",null,"e4","").toArray();
+ return
headers("e1","v1","e2",123,"e3",null,"e4","").getAll().toArray(new
org.apache.http.Header[0]);
}
@Header(aev=true)
public BasicHeader[] getF() {
- return
headers("f1","v1","f2",123,"f3",null,"f4","").toArray(new BasicHeader[0]);
+ return
headers("f1","v1","f2",123,"f3",null,"f4","").getAll().toArray(new
BasicHeader[0]);
}
}
@@ -890,8 +890,8 @@ public class Remote_HeaderAnnotation_Test {
// Helper methods.
//------------------------------------------------------------------------------------------------------------------
- private static HeaderSupplier headers(Object...pairs) {
- return HeaderSupplier.ofPairs(pairs);
+ private static HeaderList headers(Object...pairs) {
+ return HeaderList.ofPairs(pairs);
}
private static org.apache.http.Header header(String key,Object val) {
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_Test.java
index bb60ff9..a438c80 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_Test.java
@@ -574,15 +574,18 @@ public class Remote_Test {
}
}
- @Remote(headers="Foo:bar",headerSupplier=F1b.class,version="1.2.3")
+ @Remote(headers="Foo:bar",headerList=F1b.class,version="1.2.3")
public static interface F1a {
String[] getHeaders();
}
- public static class F1b extends HeaderSupplier {
+ public static class F1b extends HeaderList {
public F1b() {
- add(basicHeader("Foo","baz"));
- add(HeaderSupplier.of(basicHeader("Foo",()->"qux")));
+ super(
+ create()
+ .add(basicHeader("Foo","baz"))
+
.add(HeaderList.create().add(basicHeader("Foo",()->"qux")).build())
+ );
}
}
@@ -594,12 +597,12 @@ public class Remote_Test {
assertEquals("['1.2.3']",SimpleJson.DEFAULT.toString(x.getHeaders()));
}
- @Remote(headerSupplier=F2b.class)
+ @Remote(headerList=F2b.class)
public static interface F2a {
String[] getHeaders();
}
- public static class F2b extends HeaderSupplier {
+ public static class F2b extends HeaderList {
public F2b() {
throw new NullPointerException("foo");
}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Headers_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Headers_Test.java
index e03d423..b72c768 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Headers_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Headers_Test.java
@@ -114,7 +114,7 @@ public class RestClient_Headers_Test {
checkFooClient().headers(serializedHeader("Foo","Bar").serializer(OpenApiSerializer.DEFAULT)).build().get("/headers").headers(serializedHeader("Foo","Baz").serializer(OpenApiSerializer.DEFAULT)).run().assertBody().is("['Bar','Baz']");
checkFooClient().headers(serializedHeader("Foo",()->"Bar").serializer(OpenApiSerializer.DEFAULT)).build().get("/headers").headers(serializedHeader("Foo",()->"Baz").serializer(OpenApiSerializer.DEFAULT)).run().assertBody().is("['Bar','Baz']");
checkFooClient().headers((Object)new
Header[]{header("Foo","bar")}).build().get("/headers").headers((Object)new
Header[]{header("Foo","baz")}).run().assertBody().is("['bar','baz']");
-
checkFooClient().headers(HeaderSupplier.of(header("Foo","bar"))).build().get("/headers").headers(HeaderSupplier.of(header("Foo","baz"))).run().assertBody().is("['bar','baz']");
+
checkFooClient().headers(HeaderList.of(header("Foo","bar"))).build().get("/headers").headers(HeaderList.of(header("Foo","baz"))).run().assertBody().is("['bar','baz']");
checkFooClient().headers(AList.of(header("Foo","bar"))).build().get("/headers").headers(AList.of(header("Foo","baz"))).run().assertBody().is("['bar','baz']");
checkClient("f").build().get("/headers").headers(bean).run().assertBody().is("['1']");
checkClient("f").build().get("/headers").headers((Object)null).run().assertBody().is("[]");