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 01e9741  Improvements to fluent assertions on headers.
01e9741 is described below

commit 01e97411975981a13339c55a00dbf28f67224512
Author: JamesBognar <[email protected]>
AuthorDate: Mon May 25 17:59:23 2020 -0400

    Improvements to fluent assertions on headers.
---
 .../main/java/org/apache/juneau/http/Accept.java   |   2 +-
 .../java/org/apache/juneau/http/AcceptRanges.java  |   2 +-
 .../java/org/apache/juneau/http/Authorization.java |   2 +-
 .../apache/juneau/http/BasicCsvArrayHeader.java    |  13 +-
 .../org/apache/juneau/http/BasicDateHeader.java    |  36 ++++-
 .../http/BasicEntityValidatorArrayHeader.java      |   4 +-
 .../org/apache/juneau/http/BasicEnumHeader.java    |   3 +-
 .../java/org/apache/juneau/http/BasicHeader.java   | 156 ---------------------
 .../org/apache/juneau/http/BasicIntegerHeader.java |  26 ++++
 .../org/apache/juneau/http/BasicLongHeader.java    |  26 ++++
 ...{BasicUriHeader.java => BasicStringHeader.java} |  59 ++++----
 .../org/apache/juneau/http/BasicUriHeader.java     |   2 +-
 .../java/org/apache/juneau/http/CacheControl.java  |   2 +-
 .../java/org/apache/juneau/http/ClientVersion.java |   2 +-
 .../java/org/apache/juneau/http/Connection.java    |   2 +-
 .../org/apache/juneau/http/ContentDisposition.java |   2 +-
 .../java/org/apache/juneau/http/ContentRange.java  |   2 +-
 .../src/main/java/org/apache/juneau/http/ETag.java |   2 +-
 .../main/java/org/apache/juneau/http/Expect.java   |   2 +-
 .../java/org/apache/juneau/http/Forwarded.java     |   2 +-
 .../src/main/java/org/apache/juneau/http/From.java |   2 +-
 .../src/main/java/org/apache/juneau/http/Host.java |   2 +-
 .../main/java/org/apache/juneau/http/IfRange.java  |   2 +-
 .../main/java/org/apache/juneau/http/NoTrace.java  |   2 +-
 .../main/java/org/apache/juneau/http/Origin.java   |   2 +-
 .../main/java/org/apache/juneau/http/Pragma.java   |   2 +-
 .../org/apache/juneau/http/ProxyAuthenticate.java  |   2 +-
 .../org/apache/juneau/http/ProxyAuthorization.java |   2 +-
 .../main/java/org/apache/juneau/http/Range.java    |   2 +-
 .../java/org/apache/juneau/http/RetryAfter.java    |   2 +-
 .../org/apache/juneau/http/SerializedHeader.java   |   2 +-
 .../main/java/org/apache/juneau/http/Server.java   |   2 +-
 .../main/java/org/apache/juneau/http/Trailer.java  |   2 +-
 .../org/apache/juneau/http/TransferEncoding.java   |   2 +-
 .../java/org/apache/juneau/http/UserAgent.java     |   2 +-
 .../src/main/java/org/apache/juneau/http/Vary.java |   2 +-
 .../main/java/org/apache/juneau/http/Warning.java  |   2 +-
 .../org/apache/juneau/http/WwwAuthenticate.java    |   2 +-
 .../java/org/apache/juneau/internal/Cache.java     |   4 +-
 .../juneau/rest/client2/RestResponseHeader.java    |  65 +++++----
 40 files changed, 190 insertions(+), 262 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Accept.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Accept.java
index c8415fe..cf7a853 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Accept.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Accept.java
@@ -143,7 +143,7 @@ import org.apache.juneau.internal.*;
  * </ul>
  */
 @Header("Accept")
-public class Accept extends BasicHeader {
+public class Accept extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/AcceptRanges.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/AcceptRanges.java
index 35846b3..69cfc15 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/AcceptRanges.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/AcceptRanges.java
@@ -61,7 +61,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Accept-Ranges")
-public class AcceptRanges extends BasicHeader {
+public class AcceptRanges extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Authorization.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Authorization.java
index 48843ea..f2e049c 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Authorization.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Authorization.java
@@ -70,7 +70,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Authorization")
-public class Authorization extends BasicHeader {
+public class Authorization extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicCsvArrayHeader.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicCsvArrayHeader.java
index c1324c5..26094d7 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicCsvArrayHeader.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicCsvArrayHeader.java
@@ -12,8 +12,9 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.http;
 
+import static org.apache.juneau.internal.StringUtils.*;
+
 import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.internal.*;
 import org.apache.juneau.jsonschema.annotation.Items;
 
 /**
@@ -43,7 +44,7 @@ public class BasicCsvArrayHeader extends BasicHeader {
         * @param value The raw header value.
         */
        protected BasicCsvArrayHeader(String name, String[] value) {
-               super(name, StringUtils.joine(value, ','));
+               super(name, joine(value, ','));
                this.value = value;
        }
 
@@ -58,10 +59,6 @@ public class BasicCsvArrayHeader extends BasicHeader {
                this.value = split(value);
        }
 
-       private static String[] split(String value) {
-               return StringUtils.split(value);
-       }
-
        /**
         * Returns <jk>true</jk> if this header contains the specified value.
         *
@@ -69,7 +66,7 @@ public class BasicCsvArrayHeader extends BasicHeader {
         * @return <jk>true</jk> if this header contains the specified value.
         */
        public boolean contains(String val) {
-               if (val != null)
+               if (val != null && value != null)
                        for (String v : value)
                                if (val.equals(v))
                                        return true;
@@ -83,7 +80,7 @@ public class BasicCsvArrayHeader extends BasicHeader {
         * @return <jk>true</jk> if this header contains the specified value.
         */
        public boolean containsIC(String val) {
-               if (val != null)
+               if (val != null && value != null)
                        for (String v : value)
                                if (val.equalsIgnoreCase(v))
                                        return true;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicDateHeader.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicDateHeader.java
index 7005997..942bcff 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicDateHeader.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicDateHeader.java
@@ -18,6 +18,7 @@ import java.time.*;
 import java.util.*;
 
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.assertions.*;
 
 /**
  * Category of headers that consist of a single HTTP-date.
@@ -47,7 +48,7 @@ public class BasicDateHeader extends BasicHeader {
         */
        public BasicDateHeader(String name, String value) {
                super(name, value);
-               this.zdt = ZonedDateTime.from(RFC_1123_DATE_TIME.parse(value));
+               this.zdt = value == null ? null : 
ZonedDateTime.from(RFC_1123_DATE_TIME.parse(value));
        }
 
        /**
@@ -67,7 +68,7 @@ public class BasicDateHeader extends BasicHeader {
         * @param value The header value.
         */
        public BasicDateHeader(String name, ZonedDateTime value) {
-               super(name, RFC_1123_DATE_TIME.format(value));
+               super(name, value == null ? null : 
RFC_1123_DATE_TIME.format(value));
                this.zdt = value;
        }
 
@@ -77,7 +78,7 @@ public class BasicDateHeader extends BasicHeader {
         * @return This header value as a {@link java.util.Calendar}, or 
<jk>null</jk> if the header could not be parsed.
         */
        public Calendar asCalendar() {
-               return GregorianCalendar.from(zdt);
+               return zdt == null ? null : GregorianCalendar.from(zdt);
        }
 
        /**
@@ -100,6 +101,33 @@ public class BasicDateHeader extends BasicHeader {
        }
 
        private static ZonedDateTime asZdt(Calendar o) {
-               return o instanceof GregorianCalendar ? 
((GregorianCalendar)o).toZonedDateTime() : 
o.toInstant().atZone(ZoneId.systemDefault());
+               if (o == null)
+                       return null;
+               if (o instanceof GregorianCalendar)
+                       return ((GregorianCalendar)o).toZonedDateTime();
+               return o.toInstant().atZone(ZoneId.systemDefault());
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Assertions.
+       
//------------------------------------------------------------------------------------------------------------------
+
+       /**
+        * Provides the ability to perform fluent-style assertions on this 
header.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Validates the response body content is not expired.</jc>
+        *      client
+        *              .get(<jsf>URL</jsf>)
+        *              .run()
+        *              
.getDateHeader(<js>"Expires"</js>).assertThat().isLessThan(<jk>new</jk> Date());
+        * </p>
+        *
+        * @return A new fluent assertion object.
+        * @throws AssertionError If assertion failed.
+        */
+       public FluentDateAssertion<BasicDateHeader> assertThat() {
+               return new FluentDateAssertion<>(asDate(), this);
        }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicEntityValidatorArrayHeader.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicEntityValidatorArrayHeader.java
index a236989..cde2401 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicEntityValidatorArrayHeader.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicEntityValidatorArrayHeader.java
@@ -12,7 +12,7 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.http;
 
-import org.apache.juneau.internal.*;
+import static org.apache.juneau.internal.StringUtils.*;
 
 /**
  * Category of headers that consist of a comma-delimited list of entity 
validator values.
@@ -43,7 +43,7 @@ public class BasicEntityValidatorArrayHeader extends 
BasicHeader {
         */
        public BasicEntityValidatorArrayHeader(String name, String value) {
                super(name, value);
-               String[] s = StringUtils.split(value);
+               String[] s = value == null ? new String[0] : split(value);
                this.value = new EntityValidator[s.length];
                for (int i = 0; i < s.length; i++) {
                        this.value[i] = new EntityValidator(s[i]);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicEnumHeader.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicEnumHeader.java
index 9ca960b..03de4a5 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicEnumHeader.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicEnumHeader.java
@@ -45,7 +45,8 @@ public class BasicEnumHeader<E extends Enum<E>> extends 
BasicHeader {
                super(name, value);
                E _enumValue = def;
                try {
-                       _enumValue = Enum.valueOf(enumClass, 
value.toUpperCase());
+                       if (value != null)
+                               _enumValue = Enum.valueOf(enumClass, 
value.toUpperCase());
                } catch (Exception e) {
                        _enumValue = def;
                }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicHeader.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicHeader.java
index 72b6589..569d935 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicHeader.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicHeader.java
@@ -12,12 +12,7 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.http;
 
-import java.util.function.*;
-import java.util.regex.*;
-
-import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Superclass of all headers defined in this package.
@@ -69,157 +64,6 @@ public class BasicHeader extends 
org.apache.http.message.BasicHeader {
                return asString().equals(compare);
        }
 
-       
//------------------------------------------------------------------------------------------------------------------
-       // Assertions.
-       
//------------------------------------------------------------------------------------------------------------------
-
-       /**
-        * Asserts that the header value is not <jk>null</jk>.
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      <jc>// Validates the content type header is provided.</jc>
-        *      Accept accept = ...;
-        *      accept.assertExists();
-        * </p>
-        *
-        * @return The response object (for method chaining).
-        * @throws AssertionError If assertion failed.
-        */
-       public BasicHeader assertExists() throws AssertionError {
-               if (getValue() == null)
-                       throw new BasicAssertionError("Response did not have 
the expected header {0}.", getName());
-               return this;
-       }
-
-       /**
-        * Asserts that the header equals the specified value.
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      <jc>// Validates the content type is JSON.</jc>
-        *      Accept accept = ...;
-        *      accept.assertValue(<js>"application/json"</js>);
-        * </p>
-        *
-        * @param value The value to test for.
-        * @return The response object (for method chaining).
-        * @throws AssertionError If assertion failed.
-        */
-       public BasicHeader assertValue(String value) throws AssertionError {
-               if (! StringUtils.isEquals(value, asString()))
-                       throw new BasicAssertionError("Response did not have 
the expected value for header {0}.\n\tExpected=[{1}]\n\tActual=[{2}]", 
getName(), value, asString());
-               return this;
-       }
-
-       /**
-        * Asserts that the header passes the specified predicate test.
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      <jc>// Validates the content type is JSON.</jc>
-        *      Accept accept = ...;
-        *      accept.assertValue(x -&gt; 
x.equals(<js>"application/json"</js>);
-        * </p>
-        *
-        * @param test The predicate to test for.
-        * @return The response object (for method chaining).
-        * @throws AssertionError If assertion failed.
-        */
-       public BasicHeader assertValue(Predicate<String> test) throws 
AssertionError {
-               String text = asString();
-               if (! test.test(text))
-                       throw new BasicAssertionError("Response did not have 
the expected value for header {0}.\n\tActual=[{1}]", getName(), text);
-               return this;
-       }
-
-       /**
-        * Asserts that the header contains all the specified substrings.
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      <jc>// Validates the content type is JSON.</jc>
-        *      Accept accept = ...;
-        *      accept.assertContains(<js>"json"</js>);
-        * </p>
-        *
-        * @param values The substrings to test for.
-        * @return The response object (for method chaining).
-        * @throws AssertionError If assertion failed.
-        */
-       public BasicHeader assertContains(String...values) throws 
AssertionError {
-               String text = asString();
-               for (String substring : values)
-                       if (! StringUtils.contains(text, substring))
-                               throw new BasicAssertionError("Response did not 
have the expected substring in header {0}.\n\tExpected=[{1}]\n\tHeader=[{2}]", 
getName(), substring, text);
-               return this;
-       }
-
-       /**
-        * Asserts that the header matches the specified regular expression.
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      <jc>// Validates the content type is JSON.</jc>
-        *      Accept accept = ...;
-        *      accept.assertValueMatches(<js>".*json.*"</js>);
-        * </p>
-        *
-        * @param regex The pattern to test for.
-        * @return The response object (for method chaining).
-        * @throws AssertionError If assertion failed.
-        */
-       public BasicHeader assertMatches(String regex) throws AssertionError {
-               return assertMatches(regex, 0);
-       }
-
-       /**
-        * Asserts that the header matches the specified regular expression.
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      <jc>// Validates the content type is JSON.</jc>
-        *      Accept accept = ...;
-        *      accept.assertValueMatches(<js>".*json.*"</js>, 
<jsf>CASE_INSENSITIVE</jsf>);
-        * </p>
-        *
-        * @param regex The pattern to test for.
-        * @param flags Pattern match flags.  See {@link 
Pattern#compile(String, int)}.
-        * @return The response object (for method chaining).
-        * @throws AssertionError If assertion failed.
-        */
-       public BasicHeader assertMatches(String regex, int flags) throws 
AssertionError {
-               String text = asString();
-               if (! Pattern.compile(regex, flags).matcher(text).matches())
-                       throw new BasicAssertionError("Response did not match 
expected pattern in header {0}.\n\tpattern=[{1}]\n\tHeader=[{2}]", getName(), 
regex, text);
-               return this;
-       }
-
-       /**
-        * Asserts that the header matches the specified pattern.
-        *
-        * <p>
-        * The pattern can contain <js>"*"</js> to represent zero or more 
arbitrary characters.
-        *
-        * <h5 class='section'>Example:</h5>
-        * <p class='bcode w800'>
-        *      <jc>// Validates the content type is JSON.</jc>
-        *      Pattern p = 
Pattern.<jsm>compile</jsm>(<js>".*application\\/json.*"</js>);
-        *      Accept accept = ...;
-        *      accept.assertValueMatches(p);
-        * </p>
-        *
-        * @param pattern The pattern to test for.
-        * @return The response object (for method chaining).
-        * @throws AssertionError If assertion failed.
-        */
-       public BasicHeader assertMatches(Pattern pattern) throws AssertionError 
{
-               String text = asString();
-               if (! pattern.matcher(text).matches())
-                       throw new BasicAssertionError("Response did not match 
expected pattern in header {0}.\n\tpattern=[{1}]\n\tHeader=[{2}]", getName(), 
pattern.pattern(), text);
-               return this;
-       }
-
        @Override /* Object */
        public String toString() {
                return asString();
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicIntegerHeader.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicIntegerHeader.java
index 3eb9ee2..224e559 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicIntegerHeader.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicIntegerHeader.java
@@ -12,6 +12,7 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.http;
 
+import org.apache.juneau.assertions.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.internal.*;
 
@@ -47,6 +48,8 @@ public class BasicIntegerHeader extends BasicHeader {
        }
 
        private static Integer toInt(Object value) {
+               if (value == null)
+                       return null;
                if (value instanceof Integer)
                        return (Integer)value;
                String s = value.toString();
@@ -72,4 +75,27 @@ public class BasicIntegerHeader extends BasicHeader {
        public int asInt() {
                return value;
        }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Assertions.
+       
//------------------------------------------------------------------------------------------------------------------
+
+       /**
+        * Provides the ability to perform fluent-style assertions on this 
header.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Validates the response content is older than 1.</jc>
+        *      client
+        *              .get(<jsf>URL</jsf>)
+        *              .run()
+        *              
.getIntegerHeader(<js>"Age"</js>).assertThat().isGreaterThan(1);
+        * </p>
+        *
+        * @return A new fluent assertion object.
+        * @throws AssertionError If assertion failed.
+        */
+       public FluentIntegerAssertion<BasicIntegerHeader> assertThat() {
+               return new FluentIntegerAssertion<>(value, this);
+       }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicLongHeader.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicLongHeader.java
index 83ce426..c723201 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicLongHeader.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicLongHeader.java
@@ -12,6 +12,7 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.http;
 
+import org.apache.juneau.assertions.*;
 import org.apache.juneau.http.annotation.*;
 import org.apache.juneau.internal.*;
 
@@ -47,6 +48,8 @@ public class BasicLongHeader extends BasicHeader {
        }
 
        private static Long toLong(Object value) {
+               if (value == null)
+                       return null;
                if (value instanceof Long)
                        return (Long)value;
                String s = value.toString();
@@ -67,4 +70,27 @@ public class BasicLongHeader extends BasicHeader {
        public long asLong() {
                return value;
        }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Assertions.
+       
//------------------------------------------------------------------------------------------------------------------
+
+       /**
+        * Provides the ability to perform fluent-style assertions on this 
header.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Validates the response body is not too large.</jc>
+        *      client
+        *              .get(<jsf>URL</jsf>)
+        *              .run()
+        *              
.getLongHeader(<js>"Length"</js>).assertThat().isLessThan(100000);
+        * </p>
+        *
+        * @return A new fluent assertion object.
+        * @throws AssertionError If assertion failed.
+        */
+       public FluentLongAssertion<BasicLongHeader> assertThat() {
+               return new FluentLongAssertion<>(value, this);
+       }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicUriHeader.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicStringHeader.java
similarity index 62%
copy from 
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicUriHeader.java
copy to 
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicStringHeader.java
index 5e9b714..1539def 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicUriHeader.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicStringHeader.java
@@ -12,64 +12,55 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.http;
 
-import java.net.*;
-
-import org.apache.juneau.internal.*;
+import org.apache.juneau.assertions.*;
 
 /**
- * Category of headers that consist of a single URL value.
+ * Category of headers that consist of a single string value.
  *
  * <p>
  * <h5 class='figure'>Example</h5>
  * <p class='bcode w800'>
- *     Location: http://www.w3.org/pub/WWW/People.html
+ *     Host: www.myhost.com:8080
  * </p>
  *
  * <ul class='seealso'>
  *     <li class='extlink'>{@doc RFC2616}
  * </ul>
- */
-public class BasicUriHeader extends BasicHeader {
+*/
+public class BasicStringHeader extends BasicHeader {
 
        private static final long serialVersionUID = 1L;
 
-       final String value;
-
        /**
-        * Constructor.
+        * Constructor
         *
-        * @param name The HTTP header name.
-        * @param value The raw header value.
+        * @param name Header name.
+        * @param value Header value.
         */
-       public BasicUriHeader(String name, String value) {
+       public BasicStringHeader(String name, String value) {
                super(name, value);
-               this.value = StringUtils.trim(value);
        }
 
-       /**
-        * Returns this header as a {@link URI}.
-        *
-        * @return This header as a {@link URI}.
-        */
-       public URI asURI() {
-               return URI.create(toString());
-       }
+       
//------------------------------------------------------------------------------------------------------------------
+       // Assertions.
+       
//------------------------------------------------------------------------------------------------------------------
 
        /**
-        * Returns this header as a simple string value.
+        * Provides the ability to perform fluent-style assertions on this 
header.
         *
-        * <p>
-        * Functionally equivalent to calling {@link #toString()}.
+        * <h5 class='section'>Examples:</h5>
+        * <p class='bcode w800'>
+        *      <jc>// Validates the content type header is provided.</jc>
+        *      client
+        *              .get(<jsf>URL</jsf>)
+        *              .run()
+        *              
.getStringHeader(<js>"Content-Type"</js>).assertThat().exists();
+        * </p>
         *
-        * @return This header as a simple string.
+        * @return A new fluent assertion object.
+        * @throws AssertionError If assertion failed.
         */
-       @Override
-       public String asString() {
-               return value;
-       }
-
-       @Override /* Object */
-       public String toString() {
-               return value == null ? "" : value;
+       public FluentStringAssertion<BasicStringHeader> assertThat() {
+               return new FluentStringAssertion<>(asString(), this);
        }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicUriHeader.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicUriHeader.java
index 5e9b714..f5eef7e 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicUriHeader.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/BasicUriHeader.java
@@ -52,7 +52,7 @@ public class BasicUriHeader extends BasicHeader {
         * @return This header as a {@link URI}.
         */
        public URI asURI() {
-               return URI.create(toString());
+               return value == null ? null : URI.create(toString());
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/CacheControl.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/CacheControl.java
index c5346e3..e8877ee 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/CacheControl.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/CacheControl.java
@@ -94,7 +94,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Cache-Control")
-public class CacheControl extends BasicHeader {
+public class CacheControl extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ClientVersion.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ClientVersion.java
index 2c3a6cf..f56a6c0 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ClientVersion.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ClientVersion.java
@@ -21,7 +21,7 @@ import org.apache.juneau.internal.*;
  * Represents a parsed <l>X-Client-Version</l> HTTP request header.
  */
 @Header("X-Client-Version")
-public class ClientVersion extends BasicHeader {
+public class ClientVersion extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Connection.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Connection.java
index cf72e23..40beacb 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Connection.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Connection.java
@@ -78,7 +78,7 @@ import org.apache.juneau.internal.*;
  * </ul>
  */
 @Header("Connection")
-public class Connection extends BasicHeader {
+public class Connection extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ContentDisposition.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ContentDisposition.java
index d6832f6..db4b31e 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ContentDisposition.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ContentDisposition.java
@@ -48,7 +48,7 @@ import org.apache.juneau.internal.*;
  * </ul>
  */
 @Header("Content-Disposition")
-public class ContentDisposition extends BasicHeader {
+public class ContentDisposition extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ContentRange.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ContentRange.java
index b93a11b..f340f5d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ContentRange.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ContentRange.java
@@ -127,7 +127,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Content-Range")
-public class ContentRange extends BasicHeader {
+public class ContentRange extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ETag.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ETag.java
index bbe9abd..a2a3009 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ETag.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ETag.java
@@ -48,7 +48,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("ETag")
-public class ETag extends BasicHeader {
+public class ETag extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Expect.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Expect.java
index 165554a..6beb297 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Expect.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Expect.java
@@ -67,7 +67,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Expect")
-public class Expect extends BasicHeader {
+public class Expect extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Forwarded.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Forwarded.java
index b86049e..d200927 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Forwarded.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Forwarded.java
@@ -18,7 +18,7 @@ import org.apache.juneau.http.annotation.*;
  * Represents a parsed <l>Forwarded</l> HTTP request header.
  */
 @Header("Forwarded")
-public class Forwarded extends BasicHeader {
+public class Forwarded extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/From.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/From.java
index 926d339..2ffc503 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/From.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/From.java
@@ -65,7 +65,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("From")
-public class From extends BasicHeader {
+public class From extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Host.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Host.java
index 7c4d953..257c4f6 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Host.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Host.java
@@ -67,7 +67,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Host")
-public class Host extends BasicHeader {
+public class Host extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/IfRange.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/IfRange.java
index d1c7331..33870a6 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/IfRange.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/IfRange.java
@@ -62,7 +62,7 @@ import org.apache.juneau.internal.*;
  * </ul>
  */
 @Header("If-Range")
-public class IfRange extends BasicHeader {
+public class IfRange extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/NoTrace.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/NoTrace.java
index 7c18bec..6648d47 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/NoTrace.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/NoTrace.java
@@ -18,7 +18,7 @@ import org.apache.juneau.http.annotation.*;
  * Represents a parsed <l>No-Trace</l> HTTP request header.
  */
 @Header("No-Trace")
-public class NoTrace extends BasicHeader {
+public class NoTrace extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Origin.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Origin.java
index e3c309b..84159a9 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Origin.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Origin.java
@@ -18,7 +18,7 @@ import org.apache.juneau.http.annotation.*;
  * Represents a parsed <l>Origin</l> HTTP request header.
  */
 @Header("Origin")
-public class Origin extends BasicHeader {
+public class Origin extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Pragma.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Pragma.java
index 747a794..94737db 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Pragma.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Pragma.java
@@ -65,7 +65,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Pragma")
-public class Pragma extends BasicHeader {
+public class Pragma extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ProxyAuthenticate.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ProxyAuthenticate.java
index 4bba037..1408b3f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ProxyAuthenticate.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ProxyAuthenticate.java
@@ -48,7 +48,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Proxy-Authenticate")
-public class ProxyAuthenticate extends BasicHeader {
+public class ProxyAuthenticate extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ProxyAuthorization.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ProxyAuthorization.java
index ef833cc..62faa95 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ProxyAuthorization.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/ProxyAuthorization.java
@@ -50,7 +50,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Proxy-Authorization")
-public class ProxyAuthorization extends BasicHeader {
+public class ProxyAuthorization extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Range.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Range.java
index 244626d..2e99580 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Range.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Range.java
@@ -140,7 +140,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Range")
-public class Range extends BasicHeader {
+public class Range extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/RetryAfter.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/RetryAfter.java
index daa17d7..bf5c745 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/RetryAfter.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/RetryAfter.java
@@ -58,7 +58,7 @@ import org.apache.juneau.internal.*;
  * </ul>
  */
 @Header("Retry-After")
-public class RetryAfter extends BasicHeader {
+public class RetryAfter extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHeader.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHeader.java
index 1d6bb10..d4791cc 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHeader.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/SerializedHeader.java
@@ -33,7 +33,7 @@ import org.apache.juneau.urlencoding.*;
  *     request.setEntity(<jk>new</jk> UrlEncodedFormEntity(params));
  * </p>
  */
-public class SerializedHeader extends BasicHeader {
+public class SerializedHeader extends BasicStringHeader {
        private static final long serialVersionUID = 1L;
 
        private Object value;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Server.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Server.java
index fd123ba..71d4ff3 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Server.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Server.java
@@ -57,7 +57,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Server")
-public class Server extends BasicHeader {
+public class Server extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Trailer.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Trailer.java
index e08b01f..b9eede0 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Trailer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Trailer.java
@@ -57,7 +57,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Trailer")
-public class Trailer extends BasicHeader {
+public class Trailer extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/TransferEncoding.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/TransferEncoding.java
index 3e21e55..398f94f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/TransferEncoding.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/TransferEncoding.java
@@ -57,7 +57,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Transfer-Encoding")
-public class TransferEncoding extends BasicHeader {
+public class TransferEncoding extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/UserAgent.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/UserAgent.java
index 8c0f53a..5dad7ea 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/UserAgent.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/UserAgent.java
@@ -50,7 +50,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("User-Agent")
-public class UserAgent extends BasicHeader {
+public class UserAgent extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Vary.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Vary.java
index 6d0de1e..7c97c7b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Vary.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Vary.java
@@ -70,7 +70,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Vary")
-public class Vary extends BasicHeader {
+public class Vary extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Warning.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Warning.java
index 375fac4..cdfdae0 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Warning.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/Warning.java
@@ -124,7 +124,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("Warning")
-public class Warning extends BasicHeader {
+public class Warning extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/WwwAuthenticate.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/WwwAuthenticate.java
index ba8bba1..b255005 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/WwwAuthenticate.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/WwwAuthenticate.java
@@ -46,7 +46,7 @@ import org.apache.juneau.http.annotation.*;
  * </ul>
  */
 @Header("WWW-Authenticate")
-public class WwwAuthenticate extends BasicHeader {
+public class WwwAuthenticate extends BasicStringHeader {
 
        private static final long serialVersionUID = 1L;
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Cache.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Cache.java
index 65bf6f6..3950d66 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Cache.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/Cache.java
@@ -50,7 +50,7 @@ public class Cache<K,V> {
         * @return The value, or <jk>null</jk> if the value is not in the 
cache, or the cache is disabled.
         */
        public V get(K key) {
-               if (nocache)
+               if (nocache || key == null)
                        return null;
                return cache.get(key);
        }
@@ -65,7 +65,7 @@ public class Cache<K,V> {
         *      Always returns the same value if the cache is disabled.
         */
        public V put(K key, V value) {
-               if (nocache)
+               if (nocache || key == null)
                        return value;
 
                // Prevent OOM in case of DDOS
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestResponseHeader.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestResponseHeader.java
index 8a920b0..d7d455d 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestResponseHeader.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client2/RestResponseHeader.java
@@ -24,6 +24,7 @@ import org.apache.juneau.http.*;
 import org.apache.juneau.httppart.*;
 import org.apache.juneau.oapi.*;
 import org.apache.juneau.parser.ParseException;
+import org.apache.juneau.reflect.*;
 import org.apache.juneau.utils.*;
 
 /**
@@ -136,83 +137,97 @@ public class RestResponseHeader implements Header {
        }
 
        /**
+        * Returns the value of this header as a {@link BasicHeader}.
+        *
+        * @param c The subclass of {@link BasicHeader} to instantiate.
+        * @param <T> The subclass of {@link BasicHeader} to instantiate.
+        * @return The value of this header as a string, never <jk>null</jk>.
+        */
+       public <T extends BasicHeader> T asHeader(Class<T> c) {
+               try {
+                       ClassInfo ci = ClassInfo.of(c);
+                       ConstructorInfo cc = 
ci.getConstructor(Visibility.PUBLIC, String.class);
+                       if (cc != null)
+                               return cc.invoke(asString());
+                       cc = ci.getConstructor(Visibility.PUBLIC, String.class, 
String.class);
+                       if (cc != null)
+                               return cc.invoke(getName(), asString());
+               } catch (Exception e) {
+                       throw new RuntimeException(e);
+               }
+               throw new BasicRuntimeException("Could not determine a method 
to construct type {0}", c.getClass().getName());
+       }
+
+       /**
         * Returns the value of this header as a CSV array header.
         *
-        * @return The value of this header as a CSV array header, or 
<jk>null</jk> if header was not present.
+        * @return The value of this header as a CSV array header, never 
<jk>null</jk>.
         */
        public BasicCsvArrayHeader asCsvArrayHeader() {
-               String v = getValue();
-               return v == null ? null : new BasicCsvArrayHeader(getName(), v);
+               return new BasicCsvArrayHeader(getName(), getValue());
        }
 
        /**
         * Returns the value of this header as a date header.
         *
-        * @return The value of this header as a date header, or <jk>null</jk> 
if header was not present.
+        * @return The value of this header as a date header, never 
<jk>null</jk>.
         */
        public BasicDateHeader asDateHeader() {
-               String v = getValue();
-               return v == null ? null : new BasicDateHeader(getName(), v);
+               return new BasicDateHeader(getName(), getValue());
        }
 
        /**
         * Returns the value of this header as an entity validator array header.
         *
-        * @return The value of this header as an entity validator array 
header, or <jk>null</jk> if header was not present.
+        * @return The value of this header as an entity validator array 
header, never <jk>null</jk>.
         */
        public BasicEntityValidatorArrayHeader asEntityValidatorArrayHeader() {
-               String v = getValue();
-               return v == null ? null : new 
BasicEntityValidatorArrayHeader(getName(), v);
+               return new BasicEntityValidatorArrayHeader(getName(), 
getValue());
        }
 
        /**
         * Returns the value of this header as an integer header.
         *
-        * @return The value of this header as an integer header, or 
<jk>null</jk> if header was not present.
+        * @return The value of this header as an integer header, never 
<jk>null</jk>.
         */
        public BasicIntegerHeader asIntegerHeader() {
-               String v = getValue();
-               return v == null ? null : new BasicIntegerHeader(getName(), v);
+               return new BasicIntegerHeader(getName(), getValue());
        }
 
        /**
         * Returns the value of this header as a long header.
         *
-        * @return The value of this header as a long header, or <jk>null</jk> 
if header was not present.
+        * @return The value of this header as a long header, never 
<jk>null</jk>.
         */
        public BasicLongHeader asLongHeader() {
-               String v = getValue();
-               return v == null ? null : new BasicLongHeader(getName(), v);
+               return new BasicLongHeader(getName(), getValue());
        }
 
        /**
         * Returns the value of this header as a range array header.
         *
-        * @return The value of this header as a range array header, or 
<jk>null</jk> if header was not present.
+        * @return The value of this header as a range array header, never 
<jk>null</jk>.
         */
        public BasicRangeArrayHeader asRangeArrayHeader() {
-               String v = getValue();
-               return v == null ? null : new BasicRangeArrayHeader(getName(), 
v);
+               return new BasicRangeArrayHeader(getName(), getValue());
        }
 
        /**
         * Returns the value of this header as a string header.
         *
-        * @return The value of this header as a string header, or 
<jk>null</jk> if header was not present.
+        * @return The value of this header as a string header, never 
<jk>null</jk>.
         */
-       public BasicHeader asHeader() {
-               String v = getValue();
-               return v == null ? null : new BasicHeader(getName(), v);
+       public BasicStringHeader asStringHeader() {
+               return new BasicStringHeader(getName(), getValue());
        }
 
        /**
         * Returns the value of this header as a URI header.
         *
-        * @return The value of this header as a URI header, or <jk>null</jk> 
if header was not present.
+        * @return The value of this header as a URI header, never 
<jk>null</jk>.
         */
        public BasicUriHeader asUriHeader() {
-               String v = getValue();
-               return v == null ? null : new BasicUriHeader(getName(), v);
+               return new BasicUriHeader(getName(), getValue());
        }
 
        /**

Reply via email to