1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.harmony.luni.tests.internal.net.www.protocol.http; 19 20 import java.io.IOException; 21 import java.net.Authenticator; 22 import java.net.HttpURLConnection; 23 import java.net.InetSocketAddress; 24 import java.net.PasswordAuthentication; 25 import java.net.Proxy; 26 import java.net.ProxySelector; 27 import java.net.ServerSocket; 28 import java.net.Socket; 29 import java.net.SocketAddress; 30 import java.net.SocketTimeoutException; 31 import java.net.URI; 32 import java.net.URL; 33 import java.util.ArrayList; 34 35 import junit.framework.TestCase; 36 37 38 /** 39 * Tests for <code>HTTPURLConnection</code> class constructors and methods. 40 * 41 */ 42 public class HttpURLConnectionTest extends TestCase { 43 44 private final static Object bound = new Object(); 45 46 static class MockServer extends Thread { 47 ServerSocket serverSocket; 48 boolean accepted = false; 49 boolean started = false; 50 51 public MockServer(String name) throws IOException { 52 super(name); 53 serverSocket = new ServerSocket(0); 54 serverSocket.setSoTimeout(1000); 55 } 56 57 public int port() { 58 return serverSocket.getLocalPort(); 59 } 60 61 @Override 62 public void run() { 63 try { 64 synchronized (bound) { 65 started = true; 66 bound.notify(); 67 } 68 try { 69 serverSocket.accept().close(); 70 accepted = true; 71 } catch (SocketTimeoutException ignore) { 72 } 73 serverSocket.close(); 74 } catch (IOException e) { 75 throw new RuntimeException(e); 76 } 77 } 78 } 79 80 static class MockProxyServer extends MockServer { 81 82 boolean acceptedAuthorizedRequest; 83 84 public MockProxyServer(String name) throws Exception { 85 super(name); 86 } 87 88 @Override 89 public void run() { 90 try { 91 Socket socket = serverSocket.accept(); 92 socket.setSoTimeout(1000); 93 byte[] buff = new byte[1024]; 94 int num = socket.getInputStream().read(buff); 95 socket.getOutputStream().write(( 96 "HTTP/1.0 407 Proxy authentication required\n" 97 + "Proxy-authenticate: Basic realm=\"remotehost\"\n\n") 98 .getBytes()); 99 num = socket.getInputStream().read(buff); 100 if (num == -1) { 101 // this connection was closed, create new one: 102 socket = serverSocket.accept(); 103 socket.setSoTimeout(1000); 104 num = socket.getInputStream().read(buff); 105 } 106 String request = new String(buff, 0, num); 107 acceptedAuthorizedRequest = 108 request.toLowerCase().indexOf("proxy-authorization:") > 0; 109 if (acceptedAuthorizedRequest) { 110 socket.getOutputStream().write(( 111 "HTTP/1.1 200 OK\n\n").getBytes()); 112 } 113 } catch (IOException e) { 114 } 115 } 116 } 117 118 /** 119 * ProxySelector implementation used in the test. 120 */ 121 static class TestProxySelector extends ProxySelector { 122 // proxy port 123 private int proxy_port; 124 // server port 125 private int server_port; 126 127 /** 128 * Creates proxy selector instance. 129 * Selector will return the proxy, only if the connection 130 * is made to localhost:server_port. Otherwise it will 131 * return NO_PROXY. 132 * Address of the returned proxy will be localhost:proxy_port. 133 */ 134 public TestProxySelector(int server_port, int proxy_port) { 135 this.server_port = server_port; 136 this.proxy_port = proxy_port; 137 } 138 139 @Override 140 public java.util.List<Proxy> select(URI uri) { 141 Proxy proxy = Proxy.NO_PROXY; 142 if (("localhost".equals(uri.getHost())) 143 && (server_port == uri.getPort())) { 144 proxy = new Proxy(Proxy.Type.HTTP, 145 new InetSocketAddress("localhost", proxy_port)); 146 } 147 ArrayList<Proxy> result = new ArrayList<Proxy>(); 148 result.add(proxy); 149 return result; 150 } 151 152 @Override 153 public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { 154 // do nothing 155 } 156 } 157 158 /** 159 * org.apache.harmony.luni.internal.net.www.http.getOutputStream() 160 */ 161 public void testGetOutputStream() throws Exception { 162 // Regression for HARMONY-482 163 MockServer httpServer = 164 new MockServer("ServerSocket for HttpURLConnectionTest"); 165 httpServer.start(); 166 synchronized(bound) { 167 if (!httpServer.started) { 168 bound.wait(5000); 169 } 170 } 171 HttpURLConnection c = (HttpURLConnection) 172 new URL("http://localhost:" + httpServer.port()).openConnection(); 173 c.setDoOutput(true); 174 //use new String("POST") instead of simple "POST" to obtain other 175 //object instances then those that are in HttpURLConnection classes 176 c.setRequestMethod(new String("POST")); 177 c.getOutputStream(); 178 httpServer.join(); 179 } 180 181 182 /** 183 * Test checks if the proxy specified in openConnection 184 * method will be used for connection to the server 185 */ 186 public void testUsingProxy() throws Exception { 187 // Regression for HARMONY-570 188 MockServer server = new MockServer("server"); 189 MockServer proxy = new MockServer("proxy"); 190 191 URL url = new URL("http://localhost:" + server.port()); 192 193 HttpURLConnection connection = (HttpURLConnection) url 194 .openConnection(new Proxy(Proxy.Type.HTTP, 195 new InetSocketAddress("localhost", 196 proxy.port()))); 197 connection.setConnectTimeout(2000); 198 connection.setReadTimeout(2000); 199 200 server.start(); 201 synchronized(bound) { 202 if (!server.started) bound.wait(5000); 203 } 204 proxy.start(); 205 synchronized(bound) { 206 if (!proxy.started) bound.wait(5000); 207 } 208 209 connection.connect(); 210 211 // wait while server and proxy run 212 server.join(); 213 proxy.join(); 214 215 assertTrue("Connection does not use proxy", connection.usingProxy()); 216 assertTrue("Proxy server was not used", proxy.accepted); 217 218 HttpURLConnection huc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY); 219 assertFalse(huc.usingProxy()); 220 } 221 222 /** 223 * Test checks if the proxy provided by proxy selector 224 * will be used for connection to the server 225 */ 226 public void testUsingProxySelector() throws Exception { 227 // Regression for HARMONY-570 228 MockServer server = new MockServer("server"); 229 MockServer proxy = new MockServer("proxy"); 230 231 URL url = new URL("http://localhost:" + server.port()); 232 233 // keep default proxy selector 234 ProxySelector defPS = ProxySelector.getDefault(); 235 // replace selector 236 ProxySelector.setDefault( 237 new TestProxySelector(server.port(), proxy.port())); 238 239 try { 240 HttpURLConnection connection = 241 (HttpURLConnection) url.openConnection(); 242 connection.setConnectTimeout(2000); 243 connection.setReadTimeout(2000); 244 245 server.start(); 246 synchronized(bound) { 247 if (!server.started) bound.wait(5000); 248 } 249 proxy.start(); 250 synchronized(bound) { 251 if (!proxy.started) bound.wait(5000); 252 } 253 connection.connect(); 254 255 // wait while server and proxy run 256 server.join(); 257 proxy.join(); 258 259 assertTrue("Connection does not use proxy", 260 connection.usingProxy()); 261 assertTrue("Proxy server was not used", proxy.accepted); 262 263 connection.disconnect(); 264 assertTrue("usingProxy broken after disconnect", 265 connection.usingProxy()); 266 } finally { 267 // restore default proxy selector 268 ProxySelector.setDefault(defPS); 269 } 270 } 271 // SideEffect: Suffers from side effect of other, currently unknown test 272 public void testProxyAuthorization() throws Exception { 273 // Set up test Authenticator 274 Authenticator.setDefault(new Authenticator() { 275 @Override 276 protected PasswordAuthentication getPasswordAuthentication() { 277 return new PasswordAuthentication( 278 "user", "password".toCharArray()); 279 } 280 }); 281 282 try { 283 MockProxyServer proxy = new MockProxyServer("ProxyServer"); 284 285 URL url = new URL("http://remotehost:55555/requested.data"); 286 HttpURLConnection connection = 287 (HttpURLConnection) url.openConnection( 288 new Proxy(Proxy.Type.HTTP, 289 new InetSocketAddress("localhost", proxy.port()))); 290 connection.setConnectTimeout(1000); 291 connection.setReadTimeout(1000); 292 293 proxy.start(); 294 295 connection.connect(); 296 assertEquals("unexpected response code", 297 200, connection.getResponseCode()); 298 proxy.join(); 299 assertTrue("Connection did not send proxy authorization request", 300 proxy.acceptedAuthorizedRequest); 301 } finally { 302 // remove previously set authenticator 303 Authenticator.setDefault(null); 304 } 305 } 306 307 } 308