AbstractProxyTest.java revision bf1df887d4b87f7da69cd4fe9306eb0d19166d52
1/* 2 * Copyright (C) 2010 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 android.net.http; 18 19import java.io.IOException; 20import java.io.InputStreamReader; 21import java.io.Reader; 22import java.io.StringWriter; 23import java.util.List; 24import junit.framework.TestCase; 25import libcore.javax.net.ssl.TestSSLContext; 26import org.apache.http.HttpHost; 27import org.apache.http.HttpRequest; 28import org.apache.http.HttpResponse; 29import org.apache.http.client.HttpClient; 30import org.apache.http.client.methods.HttpGet; 31import org.apache.http.conn.params.ConnRoutePNames; 32import org.apache.http.conn.params.ConnRouteParams; 33import org.apache.http.conn.scheme.Scheme; 34import org.apache.http.conn.ssl.AllowAllHostnameVerifier; 35import org.apache.http.conn.ssl.SSLSocketFactory; 36import tests.http.MockResponse; 37import tests.http.MockWebServer; 38import tests.http.RecordedRequest; 39 40public abstract class AbstractProxyTest extends TestCase { 41 42 private MockWebServer server = new MockWebServer(); 43 44 protected abstract HttpClient newHttpClient(); 45 46 @Override protected void tearDown() throws Exception { 47 System.clearProperty("proxyHost"); 48 System.clearProperty("proxyPort"); 49 System.clearProperty("http.proxyHost"); 50 System.clearProperty("http.proxyPort"); 51 System.clearProperty("https.proxyHost"); 52 System.clearProperty("https.proxyPort"); 53 54 server.shutdown(); 55 super.tearDown(); 56 } 57 58 public void testConnectToHttps() throws Exception { 59 TestSSLContext testSSLContext = TestSSLContext.create(); 60 61 server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); 62 server.enqueue(new MockResponse() 63 .setResponseCode(200) 64 .setBody("this response comes via HTTPS")); 65 server.play(); 66 67 HttpClient httpClient = newHttpClient(); 68 69 SSLSocketFactory sslSocketFactory = newSslSocketFactory(testSSLContext); 70 sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier()); 71 httpClient.getConnectionManager().getSchemeRegistry() 72 .register(new Scheme("https", sslSocketFactory, server.getPort())); 73 74 HttpResponse response = httpClient.execute( 75 new HttpGet("https://localhost:" + server.getPort() + "/foo")); 76 assertEquals("this response comes via HTTPS", contentToString(response)); 77 78 RecordedRequest request = server.takeRequest(); 79 assertEquals("GET /foo HTTP/1.1", request.getRequestLine()); 80 } 81 82 private SSLSocketFactory newSslSocketFactory(TestSSLContext testSSLContext) throws Exception { 83 // call through to Apache HTTP's non-public SSLSocketFactory constructor 84 return SSLSocketFactory.class.getConstructor(javax.net.ssl.SSLSocketFactory.class) 85 .newInstance(testSSLContext.clientContext.getSocketFactory()); 86 } 87 88 /** 89 * We had bugs where proxy system properties weren't being honored. 90 * http://b/3254717 91 */ 92 public void testConnectViaProxyUsingProxySystemProperty() throws Exception { 93 testConnectViaProxy(ProxyConfig.PROXY_SYSTEM_PROPERTY); 94 } 95 96 public void testConnectViaProxyUsingHttpProxySystemProperty() throws Exception { 97 testConnectViaProxy(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY); 98 } 99 100 public void testConnectViaProxyUsingRequestParameter() throws Exception { 101 testConnectViaProxy(ProxyConfig.REQUEST_PARAMETER); 102 } 103 104 public void testConnectViaProxyUsingClientParameter() throws Exception { 105 testConnectViaProxy(ProxyConfig.CLIENT_PARAMETER); 106 } 107 108 /** 109 * http://code.google.com/p/android/issues/detail?id=2690 110 */ 111 private void testConnectViaProxy(ProxyConfig proxyConfig) throws Exception { 112 MockResponse mockResponse = new MockResponse() 113 .setResponseCode(200) 114 .setBody("this response comes via a proxy"); 115 server.enqueue(mockResponse); 116 server.play(); 117 118 HttpClient httpProxyClient = newHttpClient(); 119 120 HttpGet request = new HttpGet("http://android.com/foo"); 121 proxyConfig.configure(server, httpProxyClient, request); 122 123 HttpResponse response = httpProxyClient.execute(request); 124 assertEquals("this response comes via a proxy", contentToString(response)); 125 126 RecordedRequest get = server.takeRequest(); 127 assertEquals("GET http://android.com/foo HTTP/1.1", get.getRequestLine()); 128 assertContains(get.getHeaders(), "Host: android.com"); 129 } 130 131 public void testConnectViaHttpProxyToHttpsUsingProxySystemProperty() throws Exception { 132 testConnectViaHttpProxyToHttps(ProxyConfig.PROXY_SYSTEM_PROPERTY); 133 } 134 135 public void testConnectViaHttpProxyToHttpsUsingHttpsProxySystemProperty() throws Exception { 136 testConnectViaHttpProxyToHttps(ProxyConfig.HTTPS_PROXY_SYSTEM_PROPERTY); 137 } 138 139 public void testConnectViaHttpProxyToHttpsUsingClientParameter() throws Exception { 140 testConnectViaHttpProxyToHttps(ProxyConfig.CLIENT_PARAMETER); 141 } 142 143 public void testConnectViaHttpProxyToHttpsUsingRequestParameter() throws Exception { 144 testConnectViaHttpProxyToHttps(ProxyConfig.REQUEST_PARAMETER); 145 } 146 147 private void testConnectViaHttpProxyToHttps(ProxyConfig proxyConfig) throws Exception { 148 TestSSLContext testSSLContext = TestSSLContext.create(); 149 150 server.useHttps(testSSLContext.serverContext.getSocketFactory(), true); 151 MockResponse connectResponse = new MockResponse() 152 .setResponseCode(200); 153 connectResponse.getHeaders().clear(); 154 server.enqueue(connectResponse); 155 server.enqueue(new MockResponse() 156 .setResponseCode(200) 157 .setBody("this response comes via a secure proxy")); 158 server.play(); 159 160 HttpClient httpProxyClient = newHttpClient(); 161 SSLSocketFactory sslSocketFactory = newSslSocketFactory(testSSLContext); 162 sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier()); 163 httpProxyClient.getConnectionManager().getSchemeRegistry() 164 .register(new Scheme("https", sslSocketFactory, 443)); 165 166 HttpGet request = new HttpGet("https://android.com/foo"); 167 proxyConfig.configure(server, httpProxyClient, request); 168 169 HttpResponse response = httpProxyClient.execute(request); 170 assertEquals("this response comes via a secure proxy", contentToString(response)); 171 172 RecordedRequest connect = server.takeRequest(); 173 assertEquals("Connect line failure on proxy " + proxyConfig, 174 "CONNECT android.com:443 HTTP/1.1", connect.getRequestLine()); 175 assertContains(connect.getHeaders(), "Host: android.com"); 176 177 RecordedRequest get = server.takeRequest(); 178 assertEquals("GET /foo HTTP/1.1", get.getRequestLine()); 179 assertContains(get.getHeaders(), "Host: android.com"); 180 } 181 182 public void testClientParamPreferredOverSystemProperty() throws Exception { 183 testParamPreferredOverSystemProperty(ProxyConfig.CLIENT_PARAMETER); 184 } 185 186 public void testRequestParamPreferredOverSystemProperty() throws Exception { 187 testParamPreferredOverSystemProperty(ProxyConfig.REQUEST_PARAMETER); 188 } 189 190 private void testParamPreferredOverSystemProperty(ProxyConfig proxyConfig) throws Exception { 191 server.enqueue(new MockResponse().setBody("Via request parameter proxy!")); 192 server.play(); 193 System.setProperty("http.proxyHost", "proxy.foo"); 194 System.setProperty("http.proxyPort", "8080"); 195 196 HttpClient client = newHttpClient(); 197 HttpGet request = new HttpGet("http://origin.foo/bar"); 198 proxyConfig.configure(server, client, request); 199 HttpResponse response = client.execute(request); 200 assertEquals("Via request parameter proxy!", contentToString(response)); 201 202 RecordedRequest recordedRequest = server.takeRequest(); 203 assertEquals("GET http://origin.foo/bar HTTP/1.1", recordedRequest.getRequestLine()); 204 } 205 206 public void testExplicitNoProxyCancelsSystemProperty() throws Exception { 207 server.enqueue(new MockResponse().setBody("Via the origin server!")); 208 server.play(); 209 System.setProperty("http.proxyHost", "proxy.foo"); 210 System.setProperty("http.proxyPort", "8080"); 211 212 HttpClient client = newHttpClient(); 213 HttpGet request = new HttpGet(server.getUrl("/bar").toURI()); 214 request.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, ConnRouteParams.NO_HOST); 215 HttpResponse response = client.execute(request); 216 assertEquals("Via the origin server!", contentToString(response)); 217 218 RecordedRequest recordedRequest = server.takeRequest(); 219 assertEquals("GET /bar HTTP/1.1", recordedRequest.getRequestLine()); 220 } 221 222 enum ProxyConfig { 223 PROXY_SYSTEM_PROPERTY() { 224 @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) { 225 System.setProperty("proxyHost", "localhost"); 226 System.setProperty("proxyPort", Integer.toString(server.getPort())); 227 } 228 }, 229 HTTP_PROXY_SYSTEM_PROPERTY() { 230 @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) { 231 System.setProperty("http.proxyHost", "localhost"); 232 System.setProperty("http.proxyPort", Integer.toString(server.getPort())); 233 } 234 }, 235 HTTPS_PROXY_SYSTEM_PROPERTY() { 236 @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) { 237 System.setProperty("https.proxyHost", "localhost"); 238 System.setProperty("https.proxyPort", Integer.toString(server.getPort())); 239 } 240 }, 241 CLIENT_PARAMETER() { 242 @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) { 243 client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, 244 new HttpHost("localhost", server.getPort())); 245 } 246 }, 247 REQUEST_PARAMETER() { 248 @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) { 249 request.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, 250 new HttpHost("localhost", server.getPort())); 251 } 252 }; 253 254 abstract void configure(MockWebServer proxy, HttpClient client, HttpRequest request); 255 } 256 257 private void assertContains(List<String> headers, String header) { 258 assertTrue(headers.toString(), headers.contains(header)); 259 } 260 261 private String contentToString(HttpResponse response) throws IOException { 262 StringWriter writer = new StringWriter(); 263 char[] buffer = new char[1024]; 264 Reader reader = new InputStreamReader(response.getEntity().getContent()); 265 int length; 266 while ((length = reader.read(buffer)) != -1) { 267 writer.write(buffer, 0, length); 268 } 269 reader.close(); 270 return writer.toString(); 271 } 272} 273