I am developing a Java webservice application (with JAX-WS) that has to use two different proxies to establish separated connections to internet and an intranet. As solution I tried to write my own java.net.ProxySelector that returns a java.net.Proxy instance (of type HTTP) for internet or intranet.
In a little test application I try to download webpage via URL.openConnection(), and before I replaced the default ProxySelector with my own. But it results in an exception:
java.net.SocketException: Unknown proxy type : HTTP at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:370) at java.net.Socket.connect(Socket.java:519) at java.net.Socket.connect(Socket.java:469) at sun.net.NetworkClient.doConnect(NetworkClient.java:163) at sun.net.www.http.HttpClient.openServer(HttpClient.java:394) at 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) at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:844) at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:792) at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:703) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1026) at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:373) at norman.test.ProxyTest.conntectToRmViaProxy(ProxyTest.java:42) at norman.test.ProxyTest.main(ProxyTest.java:65)
2 Question: "Is there a alternative, to define different proxies for each connection?"
This is my 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);
}
}
This is the test class:
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");
}
}
Using multiple proxies to serve different Web services can strengthen your company's internal network security even further. To use multiple proxies, though, you must enable the correct settings in your Web browser.
To bypass a range of IP addresses or a specific domain name, specify the addresses in the proxy exception list: In Internet Explorer, on the Tools menu, select Internet Options. On the Connections tab, select LAN Settings. Select Advanced, and type the appropriate information in the Exceptions area.
You can configure multiple proxy servers with multiple network interfaces using a load balancer in a multihomed environment.
Select the Start button, then select Settings > Network & Internet > VPN. Select the VPN connection, then select Advanced options. Under VPN proxy settings, select the type of proxy setup you want to use, then enter the proxy server information for that VPN connection.
Ok, I have found the problem.
The HttpURLConnection did the OwnProxySelector.select() twice if the requested URL does not contain a port.
At first, HttpURLConnection invoked the select() with an URI, with the Scheme of "http" but no port. The select() checks whether the host address and port are euqal to intranetAddress or extranetAddress. This didn't match, because the port was not given. So the select return a Proxy for a direct connection.
At the second HttpURLConnection invoked the select() with an URI, with the Scheme of "socket" and port 80. So, because the select() checks host address and port, but not the scheme, it returned a HTTP proxy.
Now here is my corrected version of OwnProxySelector. It checks the scheme and sets the default port for HTTP or HTTPS if the port is not given by the URI. Also it asks the Java standard ProxySelector, if no HTTP or HTTPS scheme is given.
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("https")){
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);
}
}
But it is curious to me, that the HttpURLConnection did a second invoke of select(), when it got a direct connection Proxy from the first invoke.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With