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.Arrays; 24import java.util.List; 25import junit.framework.TestCase; 26import libcore.javax.net.ssl.TestSSLContext; 27import org.apache.http.HttpHost; 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.scheme.Scheme; 33import org.apache.http.conn.ssl.AllowAllHostnameVerifier; 34import org.apache.http.conn.ssl.SSLSocketFactory; 35import org.apache.http.impl.client.DefaultHttpClient; 36import tests.http.MockResponse; 37import tests.http.MockWebServer; 38import tests.http.RecordedRequest; 39 40public class HttpsThroughHttpProxyTest extends TestCase { 41 42 public void testConnectViaHttps() throws IOException, InterruptedException { 43 TestSSLContext testSSLContext = TestSSLContext.create(); 44 45 MockWebServer server = new MockWebServer(); 46 server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); 47 server.enqueue(new MockResponse() 48 .setResponseCode(200) 49 .setBody("this response comes via HTTPS")); 50 server.play(); 51 52 HttpClient httpClient = new DefaultHttpClient(); 53 SSLSocketFactory sslSocketFactory = new SSLSocketFactory( 54 testSSLContext.clientContext.getSocketFactory()); 55 sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier()); 56 httpClient.getConnectionManager().getSchemeRegistry() 57 .register(new Scheme("https", sslSocketFactory, server.getPort())); 58 59 HttpResponse response = httpClient.execute( 60 new HttpGet("https://localhost:" + server.getPort() + "/foo")); 61 assertEquals("this response comes via HTTPS", contentToString(response)); 62 63 RecordedRequest request = server.takeRequest(); 64 assertEquals("GET /foo HTTP/1.1", request.getRequestLine()); 65 } 66 67 /** 68 * http://code.google.com/p/android/issues/detail?id=2690 69 */ 70 public void testConnectViaProxy() throws IOException, InterruptedException { 71 MockWebServer proxy = new MockWebServer(); 72 MockResponse mockResponse = new MockResponse() 73 .setResponseCode(200) 74 .setBody("this response comes via a proxy"); 75 proxy.enqueue(mockResponse); 76 proxy.play(); 77 78 HttpClient httpProxyClient = new DefaultHttpClient(); 79 httpProxyClient.getParams().setParameter( 80 ConnRoutePNames.DEFAULT_PROXY, new HttpHost("localhost", proxy.getPort())); 81 82 HttpResponse response = httpProxyClient.execute(new HttpGet("http://android.com/foo")); 83 assertEquals("this response comes via a proxy", contentToString(response)); 84 85 RecordedRequest request = proxy.takeRequest(); 86 assertEquals("GET http://android.com/foo HTTP/1.1", request.getRequestLine()); 87 assertContains(request.getHeaders(), "Host: android.com"); 88 } 89 90 public void testConnectViaHttpProxyToHttps() throws IOException, InterruptedException { 91 TestSSLContext testSSLContext = TestSSLContext.create(); 92 93 MockWebServer proxy = new MockWebServer(); 94 proxy.useHttps(testSSLContext.serverContext.getSocketFactory(), true); 95 MockResponse connectResponse = new MockResponse() 96 .setResponseCode(200); 97 connectResponse.getHeaders().clear(); 98 proxy.enqueue(connectResponse); 99 proxy.enqueue(new MockResponse() 100 .setResponseCode(200) 101 .setBody("this response comes via a secure proxy")); 102 proxy.play(); 103 104 HttpClient httpProxyClient = new DefaultHttpClient(); 105 HttpHost proxyHost = new HttpHost("localhost", proxy.getPort()); 106 httpProxyClient.getParams().setParameter( 107 ConnRoutePNames.DEFAULT_PROXY, proxyHost); 108 SSLSocketFactory sslSocketFactory = new SSLSocketFactory( 109 testSSLContext.clientContext.getSocketFactory()); 110 sslSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier()); 111 httpProxyClient.getConnectionManager().getSchemeRegistry() 112 .register(new Scheme("https", sslSocketFactory, 443)); 113 114 HttpResponse response = httpProxyClient.execute(new HttpGet("https://android.com/foo")); 115 assertEquals("this response comes via a secure proxy", contentToString(response)); 116 117 RecordedRequest connect = proxy.takeRequest(); 118 assertEquals("Connect line failure on proxy " + proxyHost.toHostString(), 119 "CONNECT android.com:443 HTTP/1.1", connect.getRequestLine()); 120 assertContains(connect.getHeaders(), "Host: android.com"); 121 122 RecordedRequest get = proxy.takeRequest(); 123 assertEquals("GET /foo HTTP/1.1", get.getRequestLine()); 124 assertContains(get.getHeaders(), "Host: android.com"); 125 } 126 127 private void assertContains(List<String> headers, String header) { 128 assertTrue(headers.toString(), headers.contains(header)); 129 } 130 131 private String contentToString(HttpResponse response) throws IOException { 132 StringWriter writer = new StringWriter(); 133 char[] buffer = new char[1024]; 134 Reader reader = new InputStreamReader(response.getEntity().getContent()); 135 int length; 136 while ((length = reader.read(buffer)) != -1) { 137 writer.write(buffer, 0, length); 138 } 139 reader.close(); 140 return writer.toString(); 141 } 142} 143