Cra*_*Doc 5 java proxy http socks
我正在开发一个Java Web服务应用程序(使用JAX-WS),它必须使用两个不同的代理来建立与Internet和Intranet的分离连接.作为解决方案,我尝试编写自己的java.net.ProxySelector,它返回一个用于Internet或Intranet 的java.net.Proxy实例(HTTP类型).
在一个小测试应用程序中,我尝试通过URL.openConnection()下载网页,然后我用我自己的替换默认的ProxySelector.但它导致了一个例外:
java.net.SocketException:未知代理类型:java.net.SocksSocketImpl.connect上的HTTP(SocksSocketImpl.java:370),java.net.Socket.connect(Socket.java:519),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)位于nor.net.test的java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:373)的sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1026). Norman.t的ProxyTest.conntectToRmViaProxy(ProxyTest.java:42)est.ProxyTest.main(ProxyTest.java:65)
2问题:"是否有替代方案,为每个连接定义不同的代理?"
这是我的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);
}
}
Run Code Online (Sandbox Code Playgroud)
这是测试类:
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");
}
}
Run Code Online (Sandbox Code Playgroud)
好的,我发现了问题.
如果请求的URL不包含端口,HttpURLConnection将执行两次OwnProxySelector.select().
首先,HttpURLConnection使用URI调用select(),Scheme为"http"但没有端口.select()检查主机地址和端口是否与intranetAddress或extranetAddress相同.这不匹配,因为没有给出端口.因此,select为直接连接返回一个Proxy.
在第二个HttpURLConnection调用带有URI的select(),方案为"socket"和端口80.因此,因为select()检查主机地址和端口,而不是方案,它返回了一个HTTP代理.
现在这是我更正的OwnProxySelector版本.它检查方案并设置HTTP或HTTPS的默认端口(如果URI未给出端口).如果没有给出HTTP或HTTPS方案,它也会询问Java标准ProxySelector.
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);
}
Run Code Online (Sandbox Code Playgroud)
}
但是我很好奇,当它从第一次调用获得直接连接代理时,HttpURLConnection执行了select()的第二次调用.
归档时间: |
|
查看次数: |
10882 次 |
最近记录: |