Home | History | Annotate | Download | only in http
      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