23e5117a55
Reviewed-by: cstein, dfuchs
479 lines
23 KiB
Java
479 lines
23 KiB
Java
/*
|
|
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/*
|
|
* @test
|
|
* @bug 8276559
|
|
* @summary HttpRequest[.Builder] API and behaviour checks
|
|
* @run testng RequestBuilderTest
|
|
*/
|
|
|
|
import java.net.URI;
|
|
import java.net.URISyntaxException;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import java.net.http.HttpRequest;
|
|
import java.net.http.HttpRequest.BodyPublishers;
|
|
import static java.time.Duration.ofNanos;
|
|
import static java.time.Duration.ofMinutes;
|
|
import static java.time.Duration.ofSeconds;
|
|
import static java.time.Duration.ZERO;
|
|
import static java.net.http.HttpClient.Version.HTTP_1_1;
|
|
import static java.net.http.HttpClient.Version.HTTP_2;
|
|
import static java.net.http.HttpRequest.newBuilder;
|
|
import static org.testng.Assert.*;
|
|
|
|
import org.testng.annotations.Test;
|
|
|
|
public class RequestBuilderTest {
|
|
|
|
static final URI uri = URI.create("http://foo.com/");
|
|
static final Class<NullPointerException> NPE = NullPointerException.class;
|
|
static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
|
|
static final Class<IllegalStateException> ISE = IllegalStateException.class;
|
|
static final Class<NumberFormatException> NFE = NumberFormatException.class;
|
|
static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class;
|
|
|
|
@Test
|
|
public void testDefaults() {
|
|
List<HttpRequest.Builder> builders = List.of(newBuilder().uri(uri),
|
|
newBuilder(uri),
|
|
newBuilder().copy().uri(uri),
|
|
newBuilder(uri).copy());
|
|
for (HttpRequest.Builder builder : builders) {
|
|
assertFalse(builder.build().expectContinue());
|
|
assertEquals(builder.build().method(), "GET");
|
|
assertFalse(builder.build().bodyPublisher().isPresent());
|
|
assertFalse(builder.build().version().isPresent());
|
|
assertFalse(builder.build().timeout().isPresent());
|
|
assertTrue(builder.build().headers() != null);
|
|
assertEquals(builder.build().headers().map().size(), 0);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testNull() {
|
|
HttpRequest.Builder builder = newBuilder();
|
|
|
|
assertThrows(NPE, () -> newBuilder(null).build());
|
|
assertThrows(NPE, () -> newBuilder(uri).uri(null).build());
|
|
assertThrows(NPE, () -> builder.uri(null));
|
|
assertThrows(NPE, () -> builder.version(null));
|
|
assertThrows(NPE, () -> builder.header(null, null));
|
|
assertThrows(NPE, () -> builder.header("name", null));
|
|
assertThrows(NPE, () -> builder.header(null, "value"));
|
|
assertThrows(NPE, () -> builder.headers(null));
|
|
assertThrows(NPE, () -> builder.headers(new String[] { null, null }));
|
|
assertThrows(NPE, () -> builder.headers(new String[] { "name", null }));
|
|
assertThrows(NPE, () -> builder.headers(new String[] { null, "value" }));
|
|
assertThrows(NPE, () -> builder.method(null, null));
|
|
assertThrows(NPE, () -> builder.method("GET", null));
|
|
assertThrows(NPE, () -> builder.method("POST", null));
|
|
assertThrows(NPE, () -> builder.method("PUT", null));
|
|
assertThrows(NPE, () -> builder.method("DELETE", null));
|
|
assertThrows(NPE, () -> builder.setHeader(null, null));
|
|
assertThrows(NPE, () -> builder.setHeader("name", null));
|
|
assertThrows(NPE, () -> builder.setHeader(null, "value"));
|
|
assertThrows(NPE, () -> builder.timeout(null));
|
|
assertThrows(NPE, () -> builder.POST(null));
|
|
assertThrows(NPE, () -> builder.PUT(null));
|
|
}
|
|
|
|
@Test
|
|
public void testURI() {
|
|
assertThrows(ISE, () -> newBuilder().build());
|
|
List<URI> uris = List.of(
|
|
URI.create("ws://foo.com"),
|
|
URI.create("wss://foo.com"),
|
|
URI.create("ftp://foo.com"),
|
|
URI.create("mailto:a@b.com"),
|
|
URI.create("scheme:example.com"),
|
|
URI.create("scheme:example.com"),
|
|
URI.create("scheme:example.com/path"),
|
|
URI.create("path"),
|
|
URI.create("/path")
|
|
);
|
|
for (URI u : uris) {
|
|
assertThrows(IAE, () -> newBuilder(u));
|
|
assertThrows(IAE, () -> newBuilder().uri(u));
|
|
}
|
|
|
|
assertEquals(newBuilder(uri).build().uri(), uri);
|
|
assertEquals(newBuilder().uri(uri).build().uri(), uri);
|
|
URI https = URI.create("https://foo.com");
|
|
assertEquals(newBuilder(https).build().uri(), https);
|
|
assertEquals(newBuilder().uri(https).build().uri(), https);
|
|
}
|
|
|
|
@Test
|
|
public void testMethod() {
|
|
HttpRequest request = newBuilder(uri).build();
|
|
assertEquals(request.method(), "GET");
|
|
assertTrue(!request.bodyPublisher().isPresent());
|
|
|
|
request = newBuilder(uri).GET().build();
|
|
assertEquals(request.method(), "GET");
|
|
assertTrue(!request.bodyPublisher().isPresent());
|
|
|
|
request = newBuilder(uri).POST(BodyPublishers.ofString("")).GET().build();
|
|
assertEquals(request.method(), "GET");
|
|
assertTrue(!request.bodyPublisher().isPresent());
|
|
|
|
request = newBuilder(uri).PUT(BodyPublishers.ofString("")).GET().build();
|
|
assertEquals(request.method(), "GET");
|
|
assertTrue(!request.bodyPublisher().isPresent());
|
|
|
|
request = newBuilder(uri).DELETE().GET().build();
|
|
assertEquals(request.method(), "GET");
|
|
assertTrue(!request.bodyPublisher().isPresent());
|
|
|
|
request = newBuilder(uri).POST(BodyPublishers.ofString("")).build();
|
|
assertEquals(request.method(), "POST");
|
|
assertTrue(request.bodyPublisher().isPresent());
|
|
|
|
request = newBuilder(uri).PUT(BodyPublishers.ofString("")).build();
|
|
assertEquals(request.method(), "PUT");
|
|
assertTrue(request.bodyPublisher().isPresent());
|
|
|
|
request = newBuilder(uri).DELETE().build();
|
|
assertEquals(request.method(), "DELETE");
|
|
assertTrue(!request.bodyPublisher().isPresent());
|
|
|
|
request = newBuilder(uri).HEAD().build();
|
|
assertEquals(request.method(), "HEAD");
|
|
assertFalse(request.bodyPublisher().isPresent());
|
|
|
|
request = newBuilder(uri).GET().POST(BodyPublishers.ofString("")).build();
|
|
assertEquals(request.method(), "POST");
|
|
assertTrue(request.bodyPublisher().isPresent());
|
|
|
|
request = newBuilder(uri).GET().PUT(BodyPublishers.ofString("")).build();
|
|
assertEquals(request.method(), "PUT");
|
|
assertTrue(request.bodyPublisher().isPresent());
|
|
|
|
request = newBuilder(uri).GET().DELETE().build();
|
|
assertEquals(request.method(), "DELETE");
|
|
assertTrue(!request.bodyPublisher().isPresent());
|
|
|
|
// CONNECT is disallowed in the implementation, since it is used for
|
|
// tunneling, and is handled separately for security checks.
|
|
assertThrows(IAE, () -> newBuilder(uri).method("CONNECT", BodyPublishers.noBody()).build());
|
|
|
|
request = newBuilder(uri).method("GET", BodyPublishers.noBody()).build();
|
|
assertEquals(request.method(), "GET");
|
|
assertTrue(request.bodyPublisher().isPresent());
|
|
|
|
request = newBuilder(uri).method("POST", BodyPublishers.ofString("")).build();
|
|
assertEquals(request.method(), "POST");
|
|
assertTrue(request.bodyPublisher().isPresent());
|
|
}
|
|
|
|
@Test
|
|
public void testHeaders() {
|
|
HttpRequest.Builder builder = newBuilder(uri);
|
|
|
|
String[] empty = new String[0];
|
|
assertThrows(IAE, () -> builder.headers(empty).build());
|
|
assertThrows(IAE, () -> builder.headers("1").build());
|
|
assertThrows(IAE, () -> builder.headers("1", "2", "3").build());
|
|
assertThrows(IAE, () -> builder.headers("1", "2", "3", "4", "5").build());
|
|
assertEquals(builder.build().headers().map().size(),0);
|
|
|
|
List<HttpRequest> requests = List.of(
|
|
// same header built from different combinations of the API
|
|
newBuilder(uri).header("A", "B").build(),
|
|
newBuilder(uri).headers("A", "B").build(),
|
|
newBuilder(uri).setHeader("A", "B").build(),
|
|
newBuilder(uri).header("A", "F").setHeader("A", "B").build(),
|
|
newBuilder(uri).headers("A", "F").setHeader("A", "B").build()
|
|
);
|
|
|
|
for (HttpRequest r : requests) {
|
|
assertEquals(r.headers().map().size(), 1);
|
|
assertTrue(r.headers().firstValue("A").isPresent());
|
|
assertTrue(r.headers().firstValue("a").isPresent());
|
|
assertEquals(r.headers().firstValue("A").get(), "B");
|
|
assertEquals(r.headers().allValues("A"), List.of("B"));
|
|
assertEquals(r.headers().allValues("C").size(), 0);
|
|
assertEquals(r.headers().map().get("A"), List.of("B"));
|
|
assertThrows(NFE, () -> r.headers().firstValueAsLong("A"));
|
|
assertFalse(r.headers().firstValue("C").isPresent());
|
|
// a non-exhaustive list of mutators
|
|
assertThrows(UOE, () -> r.headers().map().put("Z", List.of("Z")));
|
|
assertThrows(UOE, () -> r.headers().map().remove("A"));
|
|
assertThrows(UOE, () -> r.headers().map().remove("A", "B"));
|
|
assertThrows(UOE, () -> r.headers().map().clear());
|
|
assertThrows(UOE, () -> r.headers().allValues("A").remove("B"));
|
|
assertThrows(UOE, () -> r.headers().allValues("A").remove(1));
|
|
assertThrows(UOE, () -> r.headers().allValues("A").clear());
|
|
assertThrows(UOE, () -> r.headers().allValues("A").add("Z"));
|
|
assertThrows(UOE, () -> r.headers().allValues("A").addAll(List.of("Z")));
|
|
assertThrows(UOE, () -> r.headers().allValues("A").add(1, "Z"));
|
|
}
|
|
|
|
requests = List.of(
|
|
// same headers built from different combinations of the API
|
|
newBuilder(uri).header("A", "B")
|
|
.header("C", "D").build(),
|
|
newBuilder(uri).header("A", "B")
|
|
.headers("C", "D").build(),
|
|
newBuilder(uri).header("A", "B")
|
|
.setHeader("C", "D").build(),
|
|
newBuilder(uri).headers("A", "B")
|
|
.headers("C", "D").build(),
|
|
newBuilder(uri).headers("A", "B")
|
|
.header("C", "D").build(),
|
|
newBuilder(uri).headers("A", "B")
|
|
.setHeader("C", "D").build(),
|
|
newBuilder(uri).setHeader("A", "B")
|
|
.setHeader("C", "D").build(),
|
|
newBuilder(uri).setHeader("A", "B")
|
|
.header("C", "D").build(),
|
|
newBuilder(uri).setHeader("A", "B")
|
|
.headers("C", "D").build(),
|
|
newBuilder(uri).headers("A", "B", "C", "D").build()
|
|
);
|
|
|
|
for (HttpRequest r : requests) {
|
|
assertEquals(r.headers().map().size(), 2);
|
|
assertTrue(r.headers().firstValue("A").isPresent());
|
|
assertEquals(r.headers().firstValue("A").get(), "B");
|
|
assertEquals(r.headers().allValues("A"), List.of("B"));
|
|
assertTrue(r.headers().firstValue("C").isPresent());
|
|
assertEquals(r.headers().firstValue("C").get(), "D");
|
|
assertEquals(r.headers().allValues("C"), List.of("D"));
|
|
assertEquals(r.headers().map().get("C"), List.of("D"));
|
|
assertThrows(NFE, () -> r.headers().firstValueAsLong("C"));
|
|
assertFalse(r.headers().firstValue("E").isPresent());
|
|
// a smaller non-exhaustive list of mutators
|
|
assertThrows(UOE, () -> r.headers().map().put("Z", List.of("Z")));
|
|
assertThrows(UOE, () -> r.headers().map().remove("C"));
|
|
assertThrows(UOE, () -> r.headers().allValues("A").remove("B"));
|
|
assertThrows(UOE, () -> r.headers().allValues("A").clear());
|
|
assertThrows(UOE, () -> r.headers().allValues("C").add("Z"));
|
|
}
|
|
|
|
requests = List.of(
|
|
// same multi-value headers built from different combinations of the API
|
|
newBuilder(uri).header("A", "B")
|
|
.header("A", "C").build(),
|
|
newBuilder(uri).header("A", "B")
|
|
.headers("A", "C").build(),
|
|
newBuilder(uri).headers("A", "B")
|
|
.headers("A", "C").build(),
|
|
newBuilder(uri).headers("A", "B")
|
|
.header("A", "C").build(),
|
|
newBuilder(uri).setHeader("A", "B")
|
|
.header("A", "C").build(),
|
|
newBuilder(uri).setHeader("A", "B")
|
|
.headers("A", "C").build(),
|
|
newBuilder(uri).header("A", "D")
|
|
.setHeader("A", "B")
|
|
.headers("A", "C").build(),
|
|
newBuilder(uri).headers("A", "B", "A", "C").build()
|
|
);
|
|
|
|
for (HttpRequest r : requests) {
|
|
assertEquals(r.headers().map().size(), 1);
|
|
assertTrue(r.headers().firstValue("A").isPresent());
|
|
assertTrue(r.headers().allValues("A").containsAll(List.of("B", "C")));
|
|
assertEquals(r.headers().allValues("C").size(), 0);
|
|
assertEquals(r.headers().map().get("A"), List.of("B", "C"));
|
|
assertThrows(NFE, () -> r.headers().firstValueAsLong("A"));
|
|
assertFalse(r.headers().firstValue("C").isPresent());
|
|
// a non-exhaustive list of mutators
|
|
assertThrows(UOE, () -> r.headers().map().put("Z", List.of("Z")));
|
|
assertThrows(UOE, () -> r.headers().map().remove("A"));
|
|
assertThrows(UOE, () -> r.headers().map().remove("A", "B"));
|
|
assertThrows(UOE, () -> r.headers().map().clear());
|
|
assertThrows(UOE, () -> r.headers().allValues("A").remove("B"));
|
|
assertThrows(UOE, () -> r.headers().allValues("A").remove(1));
|
|
assertThrows(UOE, () -> r.headers().allValues("A").clear());
|
|
assertThrows(UOE, () -> r.headers().allValues("A").add("Z"));
|
|
assertThrows(UOE, () -> r.headers().allValues("A").addAll(List.of("Z")));
|
|
assertThrows(UOE, () -> r.headers().allValues("A").add(1, "Z"));
|
|
}
|
|
|
|
// case-insensitivity
|
|
requests = List.of(
|
|
newBuilder(uri)
|
|
.header("Accept-Encoding", "gzip, deflate").build(),
|
|
newBuilder(uri)
|
|
.header("accept-encoding", "gzip, deflate").build(),
|
|
newBuilder(uri)
|
|
.header("AccePt-EncodINg", "gzip, deflate").build(),
|
|
newBuilder(uri)
|
|
.header("AcCEpt-EncoDIng", "gzip, deflate").build()
|
|
);
|
|
for (HttpRequest r : requests) {
|
|
for (String name : List.of("Accept-Encoding", "accept-encoding",
|
|
"aCCept-EnCODing", "accepT-encodinG")) {
|
|
assertTrue(r.headers().firstValue(name).isPresent());
|
|
assertTrue(r.headers().allValues(name).contains("gzip, deflate"));
|
|
assertEquals(r.headers().firstValue(name).get(), "gzip, deflate");
|
|
assertEquals(r.headers().allValues(name).size(), 1);
|
|
assertEquals(r.headers().map().size(), 1);
|
|
assertEquals(r.headers().map().get(name).size(), 1);
|
|
assertEquals(r.headers().map().get(name).get(0), "gzip, deflate");
|
|
}
|
|
}
|
|
}
|
|
|
|
// headers that are allowed now, but weren't before
|
|
private static final Set<String> FORMERLY_RESTRICTED = Set.of("referer", "origin",
|
|
"OriGin", "Referer", "Date", "via", "WarnIng");
|
|
|
|
@Test
|
|
public void testFormerlyRestricted() throws URISyntaxException {
|
|
URI uri = new URI("http://localhost:80/test/");
|
|
URI otherURI = new URI("http://www.foo.com/test/");
|
|
for (String header : FORMERLY_RESTRICTED) {
|
|
HttpRequest req = HttpRequest.newBuilder(uri)
|
|
.header(header, otherURI.toString())
|
|
.GET()
|
|
.build();
|
|
}
|
|
}
|
|
|
|
private static final Set<String> RESTRICTED = Set.of("connection", "content-length",
|
|
"expect", "host", "upgrade", "Connection", "Content-Length",
|
|
"eXpect", "hosT", "upgradE", "CONNection", "CONTENT-LENGTH",
|
|
"EXPECT", "Host", "Upgrade");
|
|
|
|
interface WithHeader {
|
|
HttpRequest.Builder withHeader(HttpRequest.Builder builder, String name, String value);
|
|
}
|
|
|
|
@Test
|
|
public void testRestricted() throws URISyntaxException {
|
|
URI uri = new URI("http://localhost:80/test/");
|
|
Map<String, WithHeader> lambdas = Map.of(
|
|
"Builder::header", HttpRequest.Builder::header,
|
|
"Builder::headers", (b, n, v) -> b.headers(n,v),
|
|
"Builder::setHeader", HttpRequest.Builder::setHeader
|
|
);
|
|
for (Map.Entry<String, WithHeader> e : lambdas.entrySet()) {
|
|
System.out.println("Testing restricted headers with " + e.getKey());
|
|
WithHeader f = e.getValue();
|
|
for (String name : RESTRICTED) {
|
|
String value = name + "-value";
|
|
HttpRequest req = f.withHeader(HttpRequest.newBuilder(uri)
|
|
.GET(), "x-" + name, value).build();
|
|
String v = req.headers().firstValue("x-" + name).orElseThrow(
|
|
() -> new RuntimeException("header x-" + name + " not set"));
|
|
assertEquals(v, value);
|
|
try {
|
|
f.withHeader(HttpRequest.newBuilder(uri)
|
|
.GET(), name, value).build();
|
|
throw new RuntimeException("Expected IAE not thrown for " + name);
|
|
} catch (IllegalArgumentException x) {
|
|
System.out.println("Got expected IAE for " + name + ": " + x);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@Test
|
|
public void testCopy() {
|
|
HttpRequest.Builder builder = newBuilder(uri).expectContinue(true)
|
|
.header("A", "B")
|
|
.POST(BodyPublishers.ofString(""))
|
|
.timeout(ofSeconds(30))
|
|
.version(HTTP_1_1);
|
|
HttpRequest.Builder copy = builder.copy();
|
|
assertTrue(builder != copy);
|
|
|
|
// modify the original builder before building from the copy
|
|
builder.GET().timeout(ofSeconds(5)).version(HTTP_2).setHeader("A", "C");
|
|
|
|
HttpRequest copyRequest = copy.build();
|
|
assertEquals(copyRequest.uri(), uri);
|
|
assertEquals(copyRequest.expectContinue(), true);
|
|
assertEquals(copyRequest.headers().map().get("A"), List.of("B"));
|
|
assertEquals(copyRequest.method(), "POST");
|
|
assertEquals(copyRequest.bodyPublisher().isPresent(), true);
|
|
assertEquals(copyRequest.timeout().get(), ofSeconds(30));
|
|
assertTrue(copyRequest.version().isPresent());
|
|
assertEquals(copyRequest.version().get(), HTTP_1_1);
|
|
|
|
// lazy set URI ( maybe builder as a template )
|
|
copyRequest = newBuilder().copy().uri(uri).build();
|
|
assertEquals(copyRequest.uri(), uri);
|
|
|
|
builder = newBuilder().header("C", "D");
|
|
copy = builder.copy();
|
|
copy.uri(uri);
|
|
copyRequest = copy.build();
|
|
assertEquals(copyRequest.uri(), uri);
|
|
assertEquals(copyRequest.headers().firstValue("C").get(), "D");
|
|
}
|
|
|
|
@Test
|
|
public void testTimeout() {
|
|
HttpRequest.Builder builder = newBuilder(uri);
|
|
assertThrows(IAE, () -> builder.timeout(ZERO));
|
|
assertThrows(IAE, () -> builder.timeout(ofSeconds(0)));
|
|
assertThrows(IAE, () -> builder.timeout(ofSeconds(-1)));
|
|
assertThrows(IAE, () -> builder.timeout(ofNanos(-100)));
|
|
assertEquals(builder.timeout(ofNanos(15)).build().timeout().get(), ofNanos(15));
|
|
assertEquals(builder.timeout(ofSeconds(50)).build().timeout().get(), ofSeconds(50));
|
|
assertEquals(builder.timeout(ofMinutes(30)).build().timeout().get(), ofMinutes(30));
|
|
}
|
|
|
|
@Test
|
|
public void testExpect() {
|
|
HttpRequest.Builder builder = newBuilder(uri);
|
|
assertEquals(builder.build().expectContinue(), false);
|
|
assertEquals(builder.expectContinue(true).build().expectContinue(), true);
|
|
assertEquals(builder.expectContinue(false).build().expectContinue(), false);
|
|
assertEquals(builder.expectContinue(true).build().expectContinue(), true);
|
|
}
|
|
|
|
@Test
|
|
public void testEquals() {
|
|
assertNotEquals(newBuilder(URI.create("http://foo.com")),
|
|
newBuilder(URI.create("http://bar.com")));
|
|
|
|
HttpRequest.Builder builder = newBuilder(uri);
|
|
assertEquals(builder.build(), builder.build());
|
|
assertEquals(builder.build(), newBuilder(uri).build());
|
|
|
|
builder.POST(BodyPublishers.noBody());
|
|
assertEquals(builder.build(), builder.build());
|
|
assertEquals(builder.build(), newBuilder(uri).POST(BodyPublishers.noBody()).build());
|
|
assertEquals(builder.build(), newBuilder(uri).POST(BodyPublishers.ofString("")).build());
|
|
assertNotEquals(builder.build(), newBuilder(uri).build());
|
|
assertNotEquals(builder.build(), newBuilder(uri).GET().build());
|
|
assertNotEquals(builder.build(), newBuilder(uri).PUT(BodyPublishers.noBody()).build());
|
|
|
|
builder = newBuilder(uri).header("x", "y");
|
|
assertEquals(builder.build(), builder.build());
|
|
assertEquals(builder.build(), newBuilder(uri).header("x", "y").build());
|
|
assertNotEquals(builder.build(), newBuilder(uri).header("x", "Z").build());
|
|
assertNotEquals(builder.build(), newBuilder(uri).header("z", "y").build());
|
|
}
|
|
}
|