ProxySelector cambia el esquema de URL de https: // a socket: //

Necesito acceder a Facebook, pero todas las comunicaciones salientes están bloqueadas en nuestro servidor, así que tengo que usar proxy.

Inicializo proxies con:

ProxySelector.setDefault(new ConfigurableProxySelector(mapping)); 

El tipo de proxy es HTTP, el servidor proxy y el puerto están funcionando (confirmado por una prueba simple de wget).

Estoy tratando de hacer esto:

 HttpClient httpClient = new HttpClient(); HttpMethod method = new GetMethod("https://graph.facebook.com:443"); int status = httpClient.executeMethod(method); 

Ahora, en mi clase ConfigurableProxySelector tengo un método de selección en el que tengo un punto de interrupción:

 public List select(URI uri) { ... } 

Por lo tanto, al usar HttpClient hago una solicitud, que debe ser un proxy y el código se detiene en el punto de interrupción en el método select () en ConfigurableProxySelector.

Pero lo que es extraño es que uri.scheme = “socket” y .toString () dan “socket: //graph.facebook.com: 443” en lugar de “https://graph.facebook.com:443”.

Debido a que ProxySelector tiene mapeo para “https: //” y no para “socket: //”, no lo encuentra y termina con “Conexión rechazada”. Lo que es extraño es que el método select () se llama 4 veces antes de que la ejecución finalice con “Conexión rechazada”.

Cualquier ayuda sería apreciada.

Apache HTTP Client 3.1 no respetará de forma nativa los Proxies HTTP devueltos por el ProxySelector predeterminado o las implementaciones de usuario.

Resumen rápido de ProxySelector

ProxySelector es una clase de servicio que selecciona y devuelve un proxy adecuado para una URL determinada según su esquema. Por ejemplo, una solicitud de http://somehost intentará proporcionar un proxy HTTP si está definido. El ProxySelector predeterminado se puede configurar en tiempo de ejecución utilizando las Propiedades del sistema, como http.proxyHost y http.proxyPort .

HTTPUrlConnection

Una instancia de HTTPUrlConnection comparará con el ProxySelector predeterminado varias veces: primero, para seleccionar http o https , y luego cuando construya el socket tcp sin procesar, usando el esquema de socket . Se puede usar un proxy SOCKS para representar un socket tcp sin procesar, pero no se encuentra a menudo en entornos corporativos, por lo que un socket tcp en bruto generalmente no recibirá proxy.

Cliente HTTP 3.1

HC 3.1, por otro lado, nunca verificará el ProxySelector predeterminado para los esquemas http / https . Sin embargo, en un punto posterior verificará el esquema de socket cuando finalmente compile el socket sin procesar: esta es la solicitud que está viendo. Esto significa que las Propiedades del sistema http.proxyHost y http.proxyPort son ineficaces. Obviamente, esto no es ideal para la mayoría de las personas que solo tienen un proxy HTTP / HTTPS.

Para solucionar esto, tiene dos opciones: definir un proxy en cada conexión HC 3.1 o implementar su propio HC 3.1 HTTPConnectionManager.

HTTPConnectionManager

El HTTPConnectionManager es responsable de crear conexiones para el cliente HC 3.1.

El HC 3.1 HTTPConnectionManager predeterminado se puede ampliar para que busque un proxy adecuado de un ProxySelector (predeterminado o personalizado) al generar la solicitud de la misma manera que HTTPUrlConnection:

 public class MyHTTPConnectionManager extends SimpleHttpConnectionManager { @Override public HttpConnection getConnectionWithTimeout( HostConfiguration hostConfiguration, long timeout) { HttpConnection hc = super.getConnectionWithTimeout(hostConfiguration, timeout); try { URI uri = new URI( hostConfiguration.getHostURL()); List hostProxies = ProxySelector.getDefault().select(uri); Proxy Proxy = hostProxies.get(0); InetSocketAddress sa = (InetSocketAddress) Proxy.address(); hc.setProxyHost(sa.getHostName()); hc.setProxyPort(sa.getPort()); } catch (URISyntaxException e) { return hc; } return hc; } } 

Luego, cuando cree un cliente HC 3.1, use su nuevo administrador de conexión:

 HttpClient client = new HttpClient(new MyHTTPConnectionManager() ); 

No es el ProxySelector el que cambia el esquema, sino el SocketFactory que abre un Socket. Si SocketFactory es nulo, se creará un socket SOCKS de forma predeterminada que solo permite proxies SOCKS. No sé nada sobre Sockets y no puedo decirle si hay una manera de hacerlo funcionar con proxies HTTP.

Pero usar otro enfoque puede ayudar, ya que Apache HttpClient parece tener su propia manera de configurar proxies.

 client.getHostConfiguration().setProxy(proxyHost, proxyPort); if (proxyUser != null) { client.getState().setProxyCredentials(new AuthScope(proxyHost, proxyPort), new UsernamePasswordCredentials(proxyUser, proxyPassword)); }