diff -r 818a23db260c -r 4254bed3c09d src/java.net.http/share/classes/java/net/http/HttpHeaders.java --- a/src/java.net.http/share/classes/java/net/http/HttpHeaders.java Wed Jun 20 17:15:16 2018 +0200 +++ b/src/java.net.http/share/classes/java/net/http/HttpHeaders.java Wed Jun 20 09:05:57 2018 -0700 @@ -25,62 +25,68 @@ package java.net.http; +import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.OptionalLong; -import static java.util.Collections.emptyList; -import static java.util.Collections.unmodifiableList; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.function.BiPredicate; +import static java.lang.String.CASE_INSENSITIVE_ORDER; +import static java.util.Collections.unmodifiableMap; import static java.util.Objects.requireNonNull; /** * A read-only view of a set of HTTP headers. * - *
An {@code HttpHeaders} is not created directly, but rather returned from - * an {@link HttpResponse HttpResponse}. Specific HTTP headers can be set for - * {@linkplain HttpRequest requests} through the one of the request builder's - * {@link HttpRequest.Builder#header(String, String) headers} methods. + *
An {@code HttpHeaders} is not typically created directly, but rather + * returned from an {@link HttpRequest#headers() HttpRequest} or an + * {@link HttpResponse#headers() HttpResponse}. Specific HTTP headers can be + * set for a {@linkplain HttpRequest request} through one of the request + * builder's {@link HttpRequest.Builder#header(String, String) headers} methods. * *
The methods of this class ( that accept a String header name ), and the - * Map returned by the {@link #map() map} method, operate without regard to - * case when retrieving the header value. + * {@code Map} returned by the {@link #map() map} method, operate without regard + * to case when retrieving the header value(s). + * + *
An HTTP header name may appear more than once in the HTTP protocol. As + * such, headers are represented as a name and a list of values. Each occurrence + * of a header value is added verbatim, to the appropriate header name list, + * without interpreting its value. In particular, {@code HttpHeaders} does not + * perform any splitting or joining of comma separated header value strings. The + * order of elements in a header value list is preserved when {@link + * HttpRequest.Builder#header(String, String) building} a request. For + * responses, the order of elements in a header value list is the order in which + * they were received. The {@code Map} returned by the {@code map} method, + * however, does not provide any guarantee with regard to the ordering of its + * entries. * *
{@code HttpHeaders} instances are immutable.
*
* @since 11
*/
-public abstract class HttpHeaders {
-
- /**
- * Creates an HttpHeaders.
- */
- protected HttpHeaders() {}
+public final class HttpHeaders {
/**
- * Returns an {@link Optional} containing the first value of the given named
- * (and possibly multi-valued) header. If the header is not present, then
- * the returned {@code Optional} is empty.
- *
- * @implSpec
- * The default implementation invokes
- * {@code allValues(name).stream().findFirst()}
+ * Returns an {@link Optional} containing the first header string value of
+ * the given named (and possibly multi-valued) header. If the header is not
+ * present, then the returned {@code Optional} is empty.
*
* @param name the header name
- * @return an {@code Optional An HTTP header name may appear more than once in the HTTP protocol.
+ * Such, multi-valued, headers must be represented by a single entry
+ * in the given map, whose entry value is a list that represents the
+ * multiple header string values. Leading and trailing whitespaces are
+ * removed from all string values retrieved from the given map and its lists
+ * before processing. Only headers that, after filtering, contain at least
+ * one, possibly empty string, value will be added to the HTTP headers.
+ *
+ * @apiNote The primary purpose of this method is for testing frameworks.
+ * Per-request headers can be set through one of the {@code HttpRequest}
+ * {@link HttpRequest.Builder#header(String, String) headers} methods.
+ *
+ * @param headerMap the map containing the header names and values
+ * @param filter a filter that can be used to inspect each
+ * header-name-and-value pair in the given map to determine if
+ * it should, or should not, be added to the to the HTTP
+ * headers
+ * @return an HTTP headers instance containing the given headers
+ * @throws NullPointerException if any of: {@code headerMap}, a key or value
+ * in the given map, or an entry in the map's value list, or
+ * {@code filter}, is {@code null}
+ * @throws IllegalArgumentException if the given {@code headerMap} contains
+ * any two keys that are equal ( without regard to case ); or if the
+ * given map contains any key whose length, after trimming
+ * whitespaces, is {@code 0}
+ */
+ public static HttpHeaders of(Map