Skip to content

Commit

Permalink
Implement query parameter management.
Browse files Browse the repository at this point in the history
The tricky part of this is '+' and ' ' management.
  • Loading branch information
squarejesse committed May 12, 2015
1 parent 039614b commit 53ebedf
Show file tree
Hide file tree
Showing 3 changed files with 274 additions and 57 deletions.
145 changes: 144 additions & 1 deletion okhttp-tests/src/test/java/com/squareup/okhttp/HttpUrlTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import org.junit.Ignore;
import org.junit.Test;

import static java.util.Collections.singletonList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

Expand Down Expand Up @@ -414,7 +417,7 @@ public final class HttpUrlTest {
new UrlComponentEncodingTester()
.override(Encoding.IDENTITY, '?', '`')
.override(Encoding.PERCENT, '\'')
.override(Encoding.SKIP, '#')
.override(Encoding.SKIP, '#', ' ')
.skipForUri('%', '\\', '^', '`', '{', '|', '}')
.test(Component.QUERY);
}
Expand Down Expand Up @@ -716,4 +719,144 @@ public final class HttpUrlTest {
URI uri = new URI("/path");
assertEquals(null, HttpUrl.get(uri));
}

@Test public void composeQueryWithComponents() throws Exception {
HttpUrl base = HttpUrl.parse("http://host/");
HttpUrl url = base.newBuilder().addQueryParameter("a+=& b", "c+=& d").build();
assertEquals("http://host/?a%2B%3D%26+b=c%2B%3D%26+d", url.toString());
assertEquals("c+=& d", url.queryParameterValue(0));
assertEquals("a+=& b", url.queryParameterName(0));
assertEquals("c+=& d", url.queryParameter("a+=& b"));
assertEquals(Collections.singleton("a+=& b"), url.queryParameterNames());
assertEquals(singletonList("c+=& d"), url.queryParameterValues("a+=& b"));
assertEquals(1, url.querySize());
assertEquals("a+=& b=c+=& d", url.decodeQuery()); // Ambiguous! (Though working as designed.)
assertEquals("a%2B%3D%26+b=c%2B%3D%26+d", url.query());
}

@Test public void composeQueryWithEncodedComponents() throws Exception {
HttpUrl base = HttpUrl.parse("http://host/");
HttpUrl url = base.newBuilder().addEncodedQueryParameter("a+=& b", "c+=& d").build();
assertEquals("http://host/?a+%3D%26+b=c+%3D%26+d", url.toString());
assertEquals("c =& d", url.queryParameter("a =& b"));
}

@Test public void composeQueryRemoveQueryParameter() throws Exception {
HttpUrl url = HttpUrl.parse("http://host/").newBuilder()
.addQueryParameter("a+=& b", "c+=& d")
.removeAllQueryParameters("a+=& b")
.build();
assertEquals("http://host/", url.toString());
assertEquals(null, url.queryParameter("a+=& b"));
}

@Test public void composeQueryRemoveEncodedQueryParameter() throws Exception {
HttpUrl url = HttpUrl.parse("http://host/").newBuilder()
.addEncodedQueryParameter("a+=& b", "c+=& d")
.removeAllEncodedQueryParameters("a+=& b")
.build();
assertEquals("http://host/", url.toString());
assertEquals(null, url.queryParameter("a =& b"));
}

@Test public void composeQuerySetQueryParameter() throws Exception {
HttpUrl url = HttpUrl.parse("http://host/").newBuilder()
.addQueryParameter("a+=& b", "c+=& d")
.setQueryParameter("a+=& b", "ef")
.build();
assertEquals("http://host/?a%2B%3D%26+b=ef", url.toString());
assertEquals("ef", url.queryParameter("a+=& b"));
}

@Test public void composeQuerySetEncodedQueryParameter() throws Exception {
HttpUrl url = HttpUrl.parse("http://host/").newBuilder()
.addEncodedQueryParameter("a+=& b", "c+=& d")
.setEncodedQueryParameter("a+=& b", "ef")
.build();
assertEquals("http://host/?a+%3D%26+b=ef", url.toString());
assertEquals("ef", url.queryParameter("a =& b"));
}

@Test public void composeQueryMultipleEncodedValuesForParameter() throws Exception {
HttpUrl url = HttpUrl.parse("http://host/").newBuilder()
.addQueryParameter("a+=& b", "c+=& d")
.addQueryParameter("a+=& b", "e+=& f")
.build();
assertEquals("http://host/?a%2B%3D%26+b=c%2B%3D%26+d&a%2B%3D%26+b=e%2B%3D%26+f",
url.toString());
assertEquals(2, url.querySize());
assertEquals(Collections.singleton("a+=& b"), url.queryParameterNames());
assertEquals(Arrays.asList("c+=& d", "e+=& f"), url.queryParameterValues("a+=& b"));
}

@Test public void absentQueryIsZeroNameValuePairs() throws Exception {
HttpUrl url = HttpUrl.parse("http://host/").newBuilder()
.query(null)
.build();
assertEquals(0, url.querySize());
}

@Test public void emptyQueryIsSingleNameValuePairWithEmptyKey() throws Exception {
HttpUrl url = HttpUrl.parse("http://host/").newBuilder()
.query("")
.build();
assertEquals(1, url.querySize());
assertEquals("", url.queryParameterName(0));
assertEquals(null, url.queryParameterValue(0));
}

@Test public void ampersandQueryIsTwoNameValuePairsWithEmptyKeys() throws Exception {
HttpUrl url = HttpUrl.parse("http://host/").newBuilder()
.query("&")
.build();
assertEquals(2, url.querySize());
assertEquals("", url.queryParameterName(0));
assertEquals(null, url.queryParameterValue(0));
assertEquals("", url.queryParameterName(1));
assertEquals(null, url.queryParameterValue(1));
}

@Test public void removeAllDoesNotRemoveQueryIfNoParametersWereRemoved() throws Exception {
HttpUrl url = HttpUrl.parse("http://host/").newBuilder()
.query("")
.removeAllQueryParameters("a")
.build();
assertEquals("http://host/?", url.toString());
}

@Test public void queryParametersWithoutValues() throws Exception {
HttpUrl url = HttpUrl.parse("http://host/?foo&bar&baz");
assertEquals(3, url.querySize());
assertEquals(new LinkedHashSet<>(Arrays.asList("foo", "bar", "baz")),
url.queryParameterNames());
assertEquals(null, url.queryParameterValue(0));
assertEquals(null, url.queryParameterValue(1));
assertEquals(null, url.queryParameterValue(2));
assertEquals(singletonList((String) null), url.queryParameterValues("foo"));
assertEquals(singletonList((String) null), url.queryParameterValues("bar"));
assertEquals(singletonList((String) null), url.queryParameterValues("baz"));
}

@Test public void queryParametersWithEmptyValues() throws Exception {
HttpUrl url = HttpUrl.parse("http://host/?foo=&bar=&baz=");
assertEquals(3, url.querySize());
assertEquals(new LinkedHashSet<>(Arrays.asList("foo", "bar", "baz")),
url.queryParameterNames());
assertEquals("", url.queryParameterValue(0));
assertEquals("", url.queryParameterValue(1));
assertEquals("", url.queryParameterValue(2));
assertEquals(singletonList(""), url.queryParameterValues("foo"));
assertEquals(singletonList(""), url.queryParameterValues("bar"));
assertEquals(singletonList(""), url.queryParameterValues("baz"));
}

@Test public void queryParametersWithRepeatedName() throws Exception {
HttpUrl url = HttpUrl.parse("http://host/?foo[]=1&foo[]=2&foo[]=3");
assertEquals(3, url.querySize());
assertEquals(Collections.singleton("foo[]"), url.queryParameterNames());
assertEquals("1", url.queryParameterValue(0));
assertEquals("2", url.queryParameterValue(1));
assertEquals("3", url.queryParameterValue(2));
assertEquals(Arrays.asList("1", "2", "3"), url.queryParameterValues("foo[]"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ public static List<Object[]> parameters() {
"Parsing: <http://192.168.0.257> against <http://other.com/>",
"Parsing: <http://0Xc0.0250.01> against <http://other.com/>",
"Parsing: <http://[2001::1]> against <http://example.org/foo/bar>",
"Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar>"
"Parsing: <http://[2001::1]:80> against <http://example.org/foo/bar>",
// TODO(jwilson): derive the exact rules on when ' ' maps to '+' vs. '%20'.
"Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>"
);

/** Test how {@link HttpUrl} does against the web platform test suite. */
Expand Down
Loading

0 comments on commit 53ebedf

Please sign in to comment.