| /* |
| * 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(); |
| } |
| } |