8203850: java.net.http HTTP client should allow specifying Origin and Referer headers
Reviewed-by: chegar, dfuchs
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java Fri Oct 12 03:51:02 2018 -0400
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java Fri Oct 12 11:12:51 2018 +0100
@@ -133,9 +133,7 @@
// A case insensitive TreeSet of strings.
TreeSet<String> treeSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
treeSet.addAll(Set.of("connection", "content-length",
- "date", "expect", "from", "host", "origin",
- "referer", "upgrade",
- "via", "warning"));
+ "date", "expect", "from", "host", "upgrade", "via", "warning"));
DISALLOWED_HEADERS_SET = Collections.unmodifiableSet(treeSet);
}
--- a/test/jdk/java/net/httpclient/RequestBuilderTest.java Fri Oct 12 03:51:02 2018 -0400
+++ b/test/jdk/java/net/httpclient/RequestBuilderTest.java Fri Oct 12 11:12:51 2018 +0100
@@ -337,15 +337,31 @@
}
}
+ // headers that are allowed now, but weren't before
+ private static final Set<String> FORMERLY_RESTRICTED = Set.of("referer", "origin",
+ "OriGin", "Referer");
+
+ @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",
- "date", "expect", "from", "host", "origin",
- "referer", "upgrade", "via", "warning",
+ "date", "expect", "from", "host",
+ "upgrade", "via", "warning",
"Connection", "Content-Length",
- "DATE", "eXpect", "frOm", "hosT", "origIN",
- "ReFerer", "upgradE", "vIa", "Warning",
+ "DATE", "eXpect", "frOm", "hosT",
+ "upgradE", "vIa", "Warning",
"CONNection", "CONTENT-LENGTH",
- "Date", "EXPECT", "From", "Host", "Origin",
- "Referer", "Upgrade", "Via", "WARNING");
+ "Date", "EXPECT", "From", "Host",
+ "Upgrade", "Via", "WARNING");
interface WithHeader {
HttpRequest.Builder withHeader(HttpRequest.Builder builder, String name, String value);
--- a/test/jdk/java/net/httpclient/SpecialHeadersTest.java Fri Oct 12 03:51:02 2018 -0400
+++ b/test/jdk/java/net/httpclient/SpecialHeadersTest.java Fri Oct 12 11:12:51 2018 +0100
@@ -57,21 +57,25 @@
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.http.HttpClient;
+import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Optional;
import static java.lang.System.err;
import static java.lang.System.out;
import static java.net.http.HttpClient.Builder.NO_PROXY;
import static java.nio.charset.StandardCharsets.US_ASCII;
+import org.testng.Assert;
import static org.testng.Assert.assertEquals;
public class SpecialHeadersTest implements HttpServerAdapters {
@@ -91,6 +95,13 @@
{"User-Agent: camel-cased"},
{"user-agent: all-lower-case"},
{"user-Agent: mixed"},
+ // headers which were restricted before and are now allowable
+ {"referer: lower"},
+ {"Referer: normal"},
+ {"REFERER: upper"},
+ {"origin: lower"},
+ {"Origin: normal"},
+ {"ORIGIN: upper"},
};
@DataProvider(name = "variants")
@@ -169,6 +180,50 @@
}
@Test(dataProvider = "variants")
+ void testHomeMadeIllegalHeader(String uriString, String headerNameAndValue, boolean sameClient) throws Exception {
+ out.println("\n--- Starting ");
+ final URI uri = URI.create(uriString);
+
+ HttpClient client = HttpClient.newBuilder()
+ .proxy(NO_PROXY)
+ .sslContext(sslContext)
+ .build();
+
+ // Test a request which contains an illegal header created
+ HttpRequest req = new HttpRequest() {
+ @Override public Optional<BodyPublisher> bodyPublisher() {
+ return Optional.of(BodyPublishers.noBody());
+ }
+ @Override public String method() {
+ return "GET";
+ }
+ @Override public Optional<Duration> timeout() {
+ return Optional.empty();
+ }
+ @Override public boolean expectContinue() {
+ return false;
+ }
+ @Override public URI uri() {
+ return uri;
+ }
+ @Override public Optional<HttpClient.Version> version() {
+ return Optional.empty();
+ }
+ @Override public HttpHeaders headers() {
+ Map<String, List<String>> map = Map.of("via", List.of("http://foo.com"));
+ return HttpHeaders.of(map, (x, y) -> true);
+ }
+ };
+
+ try {
+ HttpResponse<String> response = client.send(req, BodyHandlers.ofString());
+ Assert.fail("Unexpected reply: " + response);
+ } catch (IllegalArgumentException ee) {
+ out.println("Got IAE as expected");
+ }
+ }
+
+ @Test(dataProvider = "variants")
void testAsync(String uriString, String headerNameAndValue, boolean sameClient) {
out.println("\n--- Starting ");
int index = headerNameAndValue.indexOf(":");
@@ -259,7 +314,10 @@
https2TestServer.stop();
}
- /** A handler that returns, as its body, the exact received request URI. */
+ /** A handler that returns, as its body, the exact received request URI.
+ * The header whose name is in the URI query and is set in the request is
+ * returned in the response with its name prefixed by X-
+ */
static class HttpUriStringHandler implements HttpTestHandler {
@Override
public void handle(HttpTestExchange t) throws IOException {