URLEncodingTest.java revision 3c938a3f6b61ce5e2dba0d039b03fe73b89fd26c
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.squareup.okhttp.internal.http;
18
19import com.squareup.okhttp.OkHttpClient;
20import java.io.IOException;
21import java.net.CacheRequest;
22import java.net.CacheResponse;
23import java.net.HttpURLConnection;
24import java.net.ResponseCache;
25import java.net.URI;
26import java.net.URISyntaxException;
27import java.net.URL;
28import java.net.URLConnection;
29import java.util.List;
30import java.util.Map;
31import java.util.concurrent.atomic.AtomicReference;
32import org.junit.Ignore;
33import org.junit.Test;
34
35import static org.junit.Assert.assertEquals;
36
37/**
38 * Exercises HttpURLConnection to convert URL to a URI. Unlike URL#toURI,
39 * HttpURLConnection recovers from URLs with unescaped but unsupported URI
40 * characters like '{' and '|' by escaping these characters.
41 */
42public final class URLEncodingTest {
43  /**
44   * This test goes through the exhaustive set of interesting ASCII characters
45   * because most of those characters are interesting in some way according to
46   * RFC 2396 and RFC 2732. http://b/1158780
47   */
48  @Test @Ignore public void lenientUrlToUri() throws Exception {
49    // alphanum
50    testUrlToUriMapping("abzABZ09", "abzABZ09", "abzABZ09", "abzABZ09", "abzABZ09");
51
52    // control characters
53    testUrlToUriMapping("\u0001", "%01", "%01", "%01", "%01");
54    testUrlToUriMapping("\u001f", "%1F", "%1F", "%1F", "%1F");
55
56    // ascii characters
57    testUrlToUriMapping("%20", "%20", "%20", "%20", "%20");
58    testUrlToUriMapping("%20", "%20", "%20", "%20", "%20");
59    testUrlToUriMapping(" ", "%20", "%20", "%20", "%20");
60    testUrlToUriMapping("!", "!", "!", "!", "!");
61    testUrlToUriMapping("\"", "%22", "%22", "%22", "%22");
62    testUrlToUriMapping("#", null, null, null, "%23");
63    testUrlToUriMapping("$", "$", "$", "$", "$");
64    testUrlToUriMapping("&", "&", "&", "&", "&");
65    testUrlToUriMapping("'", "'", "'", "'", "'");
66    testUrlToUriMapping("(", "(", "(", "(", "(");
67    testUrlToUriMapping(")", ")", ")", ")", ")");
68    testUrlToUriMapping("*", "*", "*", "*", "*");
69    testUrlToUriMapping("+", "+", "+", "+", "+");
70    testUrlToUriMapping(",", ",", ",", ",", ",");
71    testUrlToUriMapping("-", "-", "-", "-", "-");
72    testUrlToUriMapping(".", ".", ".", ".", ".");
73    testUrlToUriMapping("/", null, "/", "/", "/");
74    testUrlToUriMapping(":", null, ":", ":", ":");
75    testUrlToUriMapping(";", ";", ";", ";", ";");
76    testUrlToUriMapping("<", "%3C", "%3C", "%3C", "%3C");
77    testUrlToUriMapping("=", "=", "=", "=", "=");
78    testUrlToUriMapping(">", "%3E", "%3E", "%3E", "%3E");
79    testUrlToUriMapping("?", null, null, "?", "?");
80    testUrlToUriMapping("@", "@", "@", "@", "@");
81    testUrlToUriMapping("[", null, "%5B", null, "%5B");
82    testUrlToUriMapping("\\", "%5C", "%5C", "%5C", "%5C");
83    testUrlToUriMapping("]", null, "%5D", null, "%5D");
84    testUrlToUriMapping("^", "%5E", "%5E", "%5E", "%5E");
85    testUrlToUriMapping("_", "_", "_", "_", "_");
86    testUrlToUriMapping("`", "%60", "%60", "%60", "%60");
87    testUrlToUriMapping("{", "%7B", "%7B", "%7B", "%7B");
88    testUrlToUriMapping("|", "%7C", "%7C", "%7C", "%7C");
89    testUrlToUriMapping("}", "%7D", "%7D", "%7D", "%7D");
90    testUrlToUriMapping("~", "~", "~", "~", "~");
91    testUrlToUriMapping("~", "~", "~", "~", "~");
92    testUrlToUriMapping("\u007f", "%7F", "%7F", "%7F", "%7F");
93
94    // beyond ascii
95    testUrlToUriMapping("\u0080", "%C2%80", "%C2%80", "%C2%80", "%C2%80");
96    testUrlToUriMapping("\u20ac", "\u20ac", "\u20ac", "\u20ac", "\u20ac");
97    testUrlToUriMapping("\ud842\udf9f", "\ud842\udf9f", "\ud842\udf9f", "\ud842\udf9f",
98        "\ud842\udf9f");
99  }
100
101  @Test @Ignore public void lenientUrlToUriNul() throws Exception {
102    testUrlToUriMapping("\u0000", "%00", "%00", "%00", "%00"); // RI fails this
103  }
104
105  private void testUrlToUriMapping(String string, String asAuthority, String asFile, String asQuery,
106      String asFragment) throws Exception {
107    if (asAuthority != null) {
108      assertEquals("http://host" + asAuthority + ".tld/",
109          backdoorUrlToUri(new URL("http://host" + string + ".tld/")).toString());
110    }
111    if (asFile != null) {
112      assertEquals("http://host.tld/file" + asFile + "/",
113          backdoorUrlToUri(new URL("http://host.tld/file" + string + "/")).toString());
114    }
115    if (asQuery != null) {
116      assertEquals("http://host.tld/file?q" + asQuery + "=x",
117          backdoorUrlToUri(new URL("http://host.tld/file?q" + string + "=x")).toString());
118    }
119    assertEquals("http://host.tld/file#" + asFragment + "-x",
120        backdoorUrlToUri(new URL("http://host.tld/file#" + asFragment + "-x")).toString());
121  }
122
123  private URI backdoorUrlToUri(URL url) throws Exception {
124    final AtomicReference<URI> uriReference = new AtomicReference<URI>();
125
126    OkHttpClient client = new OkHttpClient();
127    client.setResponseCache(new ResponseCache() {
128      @Override public CacheRequest put(URI uri, URLConnection connection) throws IOException {
129        return null;
130      }
131
132      @Override public CacheResponse get(URI uri, String requestMethod,
133          Map<String, List<String>> requestHeaders) throws IOException {
134        uriReference.set(uri);
135        throw new UnsupportedOperationException();
136      }
137    });
138
139    try {
140      HttpURLConnection connection = client.open(url);
141      connection.getResponseCode();
142    } catch (Exception expected) {
143      if (expected.getCause() instanceof URISyntaxException) {
144        expected.printStackTrace();
145      }
146    }
147
148    return uriReference.get();
149  }
150}
151