blob: 0f8edcab70a8527d7b994113bc75c80052d373c8 [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.squareup.okhttp.internal.http;
import com.squareup.okhttp.OkHttpClient;
import java.io.IOException;
import java.net.CacheRequest;
import java.net.CacheResponse;
import java.net.HttpURLConnection;
import java.net.ResponseCache;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.assertEquals;
import org.junit.Ignore;
import org.junit.Test;
/**
* Exercises HttpURLConnection to convert URL to a URI. Unlike URL#toURI,
* HttpURLConnection recovers from URLs with unescaped but unsupported URI
* characters like '{' and '|' by escaping these characters.
*/
public final class URLEncodingTest {
/**
* This test goes through the exhaustive set of interesting ASCII characters
* because most of those characters are interesting in some way according to
* RFC 2396 and RFC 2732. http://b/1158780
*/
@Test @Ignore public void lenientUrlToUri() throws Exception {
// alphanum
testUrlToUriMapping("abzABZ09", "abzABZ09", "abzABZ09", "abzABZ09", "abzABZ09");
// control characters
testUrlToUriMapping("\u0001", "%01", "%01", "%01", "%01");
testUrlToUriMapping("\u001f", "%1F", "%1F", "%1F", "%1F");
// ascii characters
testUrlToUriMapping("%20", "%20", "%20", "%20", "%20");
testUrlToUriMapping("%20", "%20", "%20", "%20", "%20");
testUrlToUriMapping(" ", "%20", "%20", "%20", "%20");
testUrlToUriMapping("!", "!", "!", "!", "!");
testUrlToUriMapping("\"", "%22", "%22", "%22", "%22");
testUrlToUriMapping("#", null, null, null, "%23");
testUrlToUriMapping("$", "$", "$", "$", "$");
testUrlToUriMapping("&", "&", "&", "&", "&");
testUrlToUriMapping("'", "'", "'", "'", "'");
testUrlToUriMapping("(", "(", "(", "(", "(");
testUrlToUriMapping(")", ")", ")", ")", ")");
testUrlToUriMapping("*", "*", "*", "*", "*");
testUrlToUriMapping("+", "+", "+", "+", "+");
testUrlToUriMapping(",", ",", ",", ",", ",");
testUrlToUriMapping("-", "-", "-", "-", "-");
testUrlToUriMapping(".", ".", ".", ".", ".");
testUrlToUriMapping("/", null, "/", "/", "/");
testUrlToUriMapping(":", null, ":", ":", ":");
testUrlToUriMapping(";", ";", ";", ";", ";");
testUrlToUriMapping("<", "%3C", "%3C", "%3C", "%3C");
testUrlToUriMapping("=", "=", "=", "=", "=");
testUrlToUriMapping(">", "%3E", "%3E", "%3E", "%3E");
testUrlToUriMapping("?", null, null, "?", "?");
testUrlToUriMapping("@", "@", "@", "@", "@");
testUrlToUriMapping("[", null, "%5B", null, "%5B");
testUrlToUriMapping("\\", "%5C", "%5C", "%5C", "%5C");
testUrlToUriMapping("]", null, "%5D", null, "%5D");
testUrlToUriMapping("^", "%5E", "%5E", "%5E", "%5E");
testUrlToUriMapping("_", "_", "_", "_", "_");
testUrlToUriMapping("`", "%60", "%60", "%60", "%60");
testUrlToUriMapping("{", "%7B", "%7B", "%7B", "%7B");
testUrlToUriMapping("|", "%7C", "%7C", "%7C", "%7C");
testUrlToUriMapping("}", "%7D", "%7D", "%7D", "%7D");
testUrlToUriMapping("~", "~", "~", "~", "~");
testUrlToUriMapping("~", "~", "~", "~", "~");
testUrlToUriMapping("\u007f", "%7F", "%7F", "%7F", "%7F");
// beyond ascii
testUrlToUriMapping("\u0080", "%C2%80", "%C2%80", "%C2%80", "%C2%80");
testUrlToUriMapping("\u20ac", "\u20ac", "\u20ac", "\u20ac", "\u20ac");
testUrlToUriMapping("\ud842\udf9f",
"\ud842\udf9f", "\ud842\udf9f", "\ud842\udf9f", "\ud842\udf9f");
}
@Test @Ignore public void lenientUrlToUriNul() throws Exception {
testUrlToUriMapping("\u0000", "%00", "%00", "%00", "%00"); // RI fails this
}
private void testUrlToUriMapping(String string, String asAuthority, String asFile,
String asQuery, String asFragment) throws Exception {
if (asAuthority != null) {
assertEquals("http://host" + asAuthority + ".tld/",
backdoorUrlToUri(new URL("http://host" + string + ".tld/")).toString());
}
if (asFile != null) {
assertEquals("http://host.tld/file" + asFile + "/",
backdoorUrlToUri(new URL("http://host.tld/file" + string + "/")).toString());
}
if (asQuery != null) {
assertEquals("http://host.tld/file?q" + asQuery + "=x",
backdoorUrlToUri(new URL("http://host.tld/file?q" + string + "=x")).toString());
}
assertEquals("http://host.tld/file#" + asFragment + "-x",
backdoorUrlToUri(new URL("http://host.tld/file#" + asFragment + "-x")).toString());
}
private URI backdoorUrlToUri(URL url) throws Exception {
final AtomicReference<URI> uriReference = new AtomicReference<URI>();
OkHttpClient client = new OkHttpClient();
client.setResponseCache(new ResponseCache() {
@Override public CacheRequest put(URI uri, URLConnection connection)
throws IOException {
return null;
}
@Override public CacheResponse get(URI uri, String requestMethod,
Map<String, List<String>> requestHeaders) throws IOException {
uriReference.set(uri);
throw new UnsupportedOperationException();
}
});
try {
HttpURLConnection connection = client.open(url);
connection.getResponseCode();
} catch (Exception expected) {
if (expected.getCause() instanceof URISyntaxException) {
expected.printStackTrace();
}
}
return uriReference.get();
}
}