2010-02-01 14 views
5

Estoy desarrollando una aplicación de servicio web Java (con JAX-WS) que tiene que usar dos proxies diferentes para establecer conexiones separadas a internet y una intranet. Como solución intenté escribir mi propio java.net.ProxySelector que devuelve una instancia java.net.Proxy (de tipo HTTP) para Internet o Intranet.Conexión con diferentes Proxies a direcciones específicas

En una pequeña aplicación de prueba intento descargar la página web a través de URL.openConnection(), y antes de reemplazar el ProxySelector predeterminado por el mío. Pero el resultado es una excepción:

java.net.SocketException: Desconocido tipo de proxy: HTTP en java.net.SocksSocketImpl.connect (SocksSocketImpl.java:370) en java.net.Socket.connect (Socket.java:519) en java.net.Socket.connect (Socket.java:469) en sun.net.NetworkClient.doConnect (NetworkClient.java:163) en sun.net.www.http.HttpClient. openServer (HttpClient.java:394) en sun.net.www.http.HttpClient.openServer (HttpClient.java:529) at sun.net.www.http.HttpClient. (HttpClient.java:233) at sun .net.www.http.HttpClient.New (HttpClient.java:306) en sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient (HttpURLConnection.java:844) en sun.net.www.protocol.http.HttpURLConnection.plainConnect (HttpURLConnection.java:792) en sun.net. www.protocol.http.HttpURLConnection.connect (HttpURLConnection.java:703) en sun.net.www.protocol.http.HttpURLConnection.getInputStream (HttpURLConnection.java:1026) en java.net.HttpURLConnection.getResponseCode (HttpURLConnection. java: 373) en norman.test.ProxyTest.conntectToRmViaProxy (ProxyTest.java:42) en norman.test.ProxyTest.main (ProxyTest.java:65)

  1. pregunta: " ¿Por qué intenta la aplicación establecer una conexión a través de SOCKS, si mi ProxySelector solo devuelve un proxy HTTP? "

2 Pregunta: "¿Existe una alternativa, definir diferentes proxies para cada conexión?"

Esta es mi ProxySelector:

public class OwnProxySelector extends ProxySelector { 
private Proxy intranetProxy; 
private Proxy extranetProxy; 
private Proxy directConnection = Proxy.NO_PROXY; 
private URI intranetAddress; 
private URI extranetAddress; 

/* (non-Javadoc) 
* @see java.net.ProxySelector#connectFailed(java.net.URI, java.net.SocketAddress, java.io.IOException) 
*/ 
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { 
    // Nothing to do 
} 

/* (non-Javadoc) 
* @see java.net.ProxySelector#select(java.net.URI) 
*/ 
public List select(URI uri) { 
    ArrayList<Proxy> result = new ArrayList<Proxy>(); 

    if(intranetAddress.getHost().equals(uri.getHost()) && intranetAddress.getPort()==uri.getPort()){ 
     result.add(intranetProxy); 
     System.out.println("Adding intranet Proxy!"); 
    } 
    else if(extranetAddress.getHost().equals(uri.getHost()) && extranetAddress.getPort()==uri.getPort()){ 
     result.add(extranetProxy); 
     System.out.println("Adding extranet Proxy!"); 
    } 
    else{ 
     result.add(directConnection); 
     System.out.println("Adding direct connection!"); 
    } 

    return result; 
} 

public void setIntranetProxy(String proxyAddress, int proxyPort){ 
    if(proxyAddress==null || proxyAddress.isEmpty()){ 
     intranetProxy = Proxy.NO_PROXY; 
    } 
    else{ 
     SocketAddress address = new InetSocketAddress(proxyAddress, proxyPort); 
     intranetProxy = new Proxy(Proxy.Type.HTTP, address); 
    } 
} 

public void setExtranetProxy(String proxyAddress, int proxyPort){ 
    if(proxyAddress==null || proxyAddress.isEmpty()){ 
     extranetProxy = Proxy.NO_PROXY; 
    } 
    else{ 
     SocketAddress address = new InetSocketAddress(proxyAddress, proxyPort); 
     extranetProxy = new Proxy(Proxy.Type.HTTP, address); 
    } 
} 

public void clearIntranetProxy(){ 
    intranetProxy = Proxy.NO_PROXY; 
} 

public void clearExtranetProxy(){ 
    extranetProxy = Proxy.NO_PROXY; 
} 

public void setIntranetAddress(String address) throws URISyntaxException{ 
    intranetAddress = new URI(address); 
} 

public void setExtranetAddress(String address) throws URISyntaxException{ 
    extranetAddress = new URI(address); 
} 
} 

Ésta es la clase de prueba:

public class ProxyTest { 
OwnProxySelector ownSelector = new OwnProxySelector(); 

public ProxyTest(){ 
    ownSelector.setIntranetProxy("intranet.proxy", 8123); 
    try { 
     ownSelector.setIntranetAddress("http://intranet:80"); 
    } catch (URISyntaxException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    ownSelector.setExtranetProxy("", 0); 
    try { 
     ownSelector.setExtranetAddress("http://www.example.com:80"); 
    } catch (URISyntaxException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 


    ProxySelector.setDefault(ownSelector); 
} 

public void conntectToRmViaProxy(boolean internal, String connectAddress){ 
    try { 
     URL url = new URL(connectAddress); 

     HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 

     conn.setRequestMethod("GET"); 
      if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) { 
      System.out.println(conn.getResponseMessage()); 
      } 
      else{ 
       BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); 
       int tmp = reader.read(); 
       while(tmp != -1){ 
        System.out.print((char)tmp); 
        tmp = reader.read(); 
       } 
      } 

    } catch (MalformedURLException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

public static void main(String[] args){ 
    ProxyTest proxyText = new ProxyTest(); 
    proxyText.conntectToRmViaProxy(true, "http://intranet:80"); 
} 
} 
+0

¿Realmente nadie tiene una pista sobre esto? –

Respuesta

5

Ok, he encontrado el problema.

La HttpURLConnection hizo el OwnProxySelector.select() dos veces si la URL solicitada no contiene un puerto.

Al principio, HttpURLConnection invoca el select() con un URI, con el esquema de "http" pero sin puerto. El select() comprueba si la dirección del host y el puerto son euqal para intranetAddress o extranetAddress. Esto no coincidió, porque el puerto no fue dado. Entonces el select devuelve un Proxy para una conexión directa.

En el segundo HttpURLConnection invoca el select() con un URI, con el esquema de "socket" y el puerto 80. Por lo tanto, debido a que select() comprueba la dirección del host y el puerto, pero no el esquema, devuelve un HTTP apoderado.

Ahora aquí está mi versión corregida de OwnProxySelector. Comprueba el esquema y establece el puerto predeterminado para HTTP o HTTPS si el URI no proporciona el puerto. También pregunta al ProxySelector estándar de Java, si no se proporciona ningún esquema HTTP o HTTPS.

public class OwnProxySelector extends ProxySelector { 
private ProxySelector defaultProxySelector; 
private Proxy intranetProxy; 
private Proxy extranetProxy; 
private Proxy directConnection = Proxy.NO_PROXY; 
private URI intranetAddress; 
private URI extranetAddress; 


public OwnProxySelector(ProxySelector defaultProxySelector){ 
    this.defaultProxySelector = defaultProxySelector; 
} 

/* (non-Javadoc) 
* @see java.net.ProxySelector#connectFailed(java.net.URI, java.net.SocketAddress, java.io.IOException) 
*/ 
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { 
    // Nothing to do 
} 

/* (non-Javadoc) 
* @see java.net.ProxySelector#select(java.net.URI) 
*/ 
public List select(URI uri) { 
    ArrayList<Proxy> result = new ArrayList<Proxy>(); 

    if(uri.getScheme().equalsIgnoreCase("http") || uri.getScheme().equalsIgnoreCase("https")){ 
     int uriPort = uri.getPort(); 

     // set default http and https ports if port is not given in URI 
     if(uriPort<1){ 
      if(uri.getScheme().equalsIgnoreCase("http")){ 
       uriPort = 80; 
      } 
      else if(uri.getScheme().equalsIgnoreCase("http")){ 
       uriPort = 443; 
      } 
     } 

     if(intranetAddress.getHost().equals(uri.getHost()) && intranetAddress.getPort()==uriPort){ 
      result.add(intranetProxy); 
      System.out.println("Adding intranet Proxy!"); 
     } 
     else if(extranetAddress.getHost().equals(uri.getHost()) && extranetAddress.getPort()==uriPort){ 
      result.add(extranetProxy); 
      System.out.println("Adding extranet Proxy!"); 
     } 
    } 

    if(result.isEmpty()){ 
     List<Proxy> defaultResult = defaultProxySelector.select(uri); 
     if(defaultResult!=null && !defaultResult.isEmpty()){ 
      result.addAll(defaultResult); 
      System.out.println("Adding Proxis from default selector."); 
     } 
     else{ 
      result.add(directConnection); 
      System.out.println("Adding direct connection, because requested URI does not match any Proxy"); 
     } 
    } 

    return result; 
} 

public void setIntranetProxy(String proxyAddress, int proxyPort){ 
    if(proxyAddress==null || proxyAddress.isEmpty()){ 
     intranetProxy = Proxy.NO_PROXY; 
    } 
    else{ 
     SocketAddress address = new InetSocketAddress(proxyAddress, proxyPort); 
     intranetProxy = new Proxy(Proxy.Type.HTTP, address); 
    } 
} 

public void setExtranetProxy(String proxyAddress, int proxyPort){ 
    if(proxyAddress==null || proxyAddress.isEmpty()){ 
     extranetProxy = Proxy.NO_PROXY; 
    } 
    else{ 
     SocketAddress address = new InetSocketAddress(proxyAddress, proxyPort); 
     extranetProxy = new Proxy(Proxy.Type.HTTP, address); 
    } 
} 

public void clearIntranetProxy(){ 
    intranetProxy = Proxy.NO_PROXY; 
} 

public void clearExtranetProxy(){ 
    extranetProxy = Proxy.NO_PROXY; 
} 

public void setIntranetAddress(String address) throws URISyntaxException{ 
    intranetAddress = new URI(address); 
} 

public void setExtranetAddress(String address) throws URISyntaxException{ 
    extranetAddress = new URI(address); 
} 

}

Pero es curioso para mí, que la HttpURLConnection hizo una segunda invocación de select(), cuando se hizo una conexión directa Proxy de la primera invocación.

Cuestiones relacionadas