Summary
Add a new factory method that creates an HttpRequest.Builder
from an existing HttpRequest
. Builders created from this new factory can be used to build an HttpRequest
, equivalent to the original request, while allowing amendment and/or alteration of the state prior to construction. The factory method accepts an HttpRequest
from which to seed the Builder
, as well as a BiPredicate
that allows header filtering.
Problem
An HttpRequest
is immutable; once constructed its state cannot be altered (which is a fine property). While it is possible to recreate an equivalent HttpRequest
using the existing API, it is a little cumbersome, error prone, and leads to code duplication. Requests used in a particular session tend to share many similarities, so it seems desirable to facilitate the creation of such request more easily.
Solution
HttpRequest
already has two factory methods from which a Builder
can be created; the first newBuilder()
- creates an empty builder, the second newBuilder(URI)
- creates a builder with an initial URI
. This CSR adds a third way to create a Builder
; newBuilder(HttpRequest, BiPredicate)
- creates a builder whose initial internal state matches that of the given HttpRequest
.
HTTP headers are of particular interest when creating a related request, and are quite often the subject of scrutiny. A BiPredicate<String,String>
may be passed to newBuilder
to filter headers from the given request. This provides further control over the initial state of the resulting Builder
.
Specification
src/java.net.http/share/classes/java/net/http/HttpRequest.java
+ /**
+ * Creates a {@code Builder} whose initial state is copied from an existing
+ * {@code HttpRequest}.
+ *
+ * <p> This builder can be used to build an {@code HttpRequest}, equivalent
+ * to the original, while allowing amendment of the request state prior to
+ * construction - for example, adding additional headers.
+ *
+ * <p> The {@code filter} is applied to each header name value pair as they
+ * are copied from the given request. When completed, only headers that
+ * satisfy the condition as laid out by the {@code filter} will be present
+ * in the {@code Builder} returned from this method.
+ *
+ * @apiNote
+ * The following scenarios demonstrate typical use-cases of the filter.
+ * Given an {@code HttpRequest} <em>request</em>:
+ * <br><br>
+ * <ul>
+ * <li> Retain all headers:
+ * <pre>{@code HttpRequest.newBuilder(request, (n, v) -> true)}</pre>
+ *
+ * <li> Remove all headers:
+ * <pre>{@code HttpRequest.newBuilder(request, (n, v) -> false)}</pre>
+ *
+ * <li> Remove a particular header (e.g. Foo-Bar):
+ * <pre>{@code HttpRequest.newBuilder(request, (name, value) -> !name.equalsIgnoreCase("Foo-Bar"))}</pre>
+ * </ul>
+ *
+ * @param request the original request
+ * @param filter a header filter
+ * @return a new request builder
+ * @throws IllegalArgumentException if a new builder cannot be seeded from
+ * the given request (for instance, if the request contains illegal
+ * parameters)
+ * @since 16
+ */
+ public static Builder newBuilder(HttpRequest request, BiPredicate<String, String> filter) {
- csr of
-
JDK-8252304 Seed an HttpRequest.Builder from an existing HttpRequest
-
- Resolved
-