-
-
Notifications
You must be signed in to change notification settings - Fork 727
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
597 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
140 changes: 140 additions & 0 deletions
140
jodd-http/src/main/java/jodd/http/net/HTTPProxySocketFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
// Copyright (c) 2003-2013, Jodd Team (jodd.org). All Rights Reserved. | ||
|
||
package jodd.http.net; | ||
|
||
import jodd.http.HttpException; | ||
import jodd.util.Base64; | ||
|
||
import javax.net.SocketFactory; | ||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.StringReader; | ||
import java.net.HttpURLConnection; | ||
import java.net.InetAddress; | ||
import java.net.Socket; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
/** | ||
* Socket factory for HTTP proxy. | ||
*/ | ||
public class HTTPProxySocketFactory extends SocketFactory { | ||
|
||
private final ProxyInfo proxy; | ||
|
||
public HTTPProxySocketFactory(ProxyInfo proxy) { | ||
this.proxy = proxy; | ||
} | ||
|
||
public Socket createSocket(String host, int port) throws IOException { | ||
return createHttpProxySocket(host, port); | ||
} | ||
|
||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { | ||
return createHttpProxySocket(host, port); | ||
} | ||
|
||
public Socket createSocket(InetAddress host, int port) throws IOException { | ||
return createHttpProxySocket(host.getHostAddress(), port); | ||
} | ||
|
||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { | ||
return createHttpProxySocket(address.getHostAddress(), port); | ||
} | ||
|
||
private Socket createHttpProxySocket(String host, int port) throws IOException { | ||
Socket socket = null; | ||
String proxyAddress = proxy.getProxyAddress(); | ||
int proxyPort = proxy.getProxyPort(); | ||
|
||
try { | ||
|
||
socket = new Socket(proxyAddress, proxyPort); | ||
String hostport = "CONNECT " + host + ":" + port; | ||
String proxyLine; | ||
String username = proxy.getProxyUsername(); | ||
|
||
if (username == null) { | ||
proxyLine = ""; | ||
} else { | ||
String password = proxy.getProxyPassword(); | ||
proxyLine = | ||
"\r\nProxy-Authorization: Basic " | ||
+ Base64.encodeToString((username + ":" + password)); | ||
} | ||
socket.getOutputStream().write( | ||
(hostport + " HTTP/1.1\r\nHost: " | ||
+ hostport + proxyLine + "\r\n\r\n").getBytes("UTF-8")); | ||
|
||
InputStream in = socket.getInputStream(); | ||
StringBuilder recv = new StringBuilder(100); | ||
int nlchars = 0; | ||
|
||
while (true) { | ||
char c = (char) in.read(); | ||
recv.append(c); | ||
if (recv.length() > 1024) { | ||
throw new HttpException(ProxyInfo.ProxyType.HTTP, "Received header longer then 1024 chars"); | ||
} | ||
if (c == -1) { | ||
throw new HttpException(ProxyInfo.ProxyType.HTTP, "Invalid response"); | ||
} | ||
if ((nlchars == 0 || nlchars == 2) && c == '\r') { | ||
nlchars++; | ||
} else if ((nlchars == 1 || nlchars == 3) && c == '\n') { | ||
nlchars++; | ||
} else { | ||
nlchars = 0; | ||
} | ||
if (nlchars == 4) { | ||
break; | ||
} | ||
} | ||
|
||
String recvStr = recv.toString(); | ||
|
||
BufferedReader br = new BufferedReader(new StringReader(recvStr)); | ||
String response = br.readLine(); | ||
|
||
if (response == null) { | ||
throw new HttpException(ProxyInfo.ProxyType.HTTP, "Empty proxy response"); | ||
} | ||
|
||
Matcher m = RESPONSE_PATTERN.matcher(response); | ||
if (!m.matches()) { | ||
throw new HttpException(ProxyInfo.ProxyType.HTTP, "Unexpected proxy response"); | ||
} | ||
|
||
int code = Integer.parseInt(m.group(1)); | ||
|
||
if (code != HttpURLConnection.HTTP_OK) { | ||
throw new HttpException(ProxyInfo.ProxyType.HTTP, "Invalid code"); | ||
} | ||
|
||
return socket; | ||
} catch (RuntimeException rtex) { | ||
closeSocket(socket); | ||
throw rtex; | ||
} catch (Exception ex) { | ||
closeSocket(socket); | ||
throw new HttpException(ProxyInfo.ProxyType.HTTP, ex.toString(), ex); | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Closes socket silently. | ||
*/ | ||
private void closeSocket(Socket socket) { | ||
try { | ||
if (socket != null) { | ||
socket.close(); | ||
} | ||
} catch (Exception ignore) { | ||
} | ||
} | ||
|
||
private static final Pattern RESPONSE_PATTERN = | ||
Pattern.compile("HTTP/\\S+\\s(\\d+)\\s(.*)\\s*"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// Copyright (c) 2003-2013, Jodd Team (jodd.org). All Rights Reserved. | ||
|
||
package jodd.http.net; | ||
|
||
import javax.net.SocketFactory; | ||
|
||
/** | ||
* Proxy information. | ||
*/ | ||
public class ProxyInfo { | ||
|
||
/** | ||
* Proxy types. | ||
*/ | ||
public static enum ProxyType { | ||
NONE, HTTP, SOCKS4, SOCKS5 | ||
} | ||
|
||
private String proxyAddress; | ||
private int proxyPort; | ||
private String proxyUsername; | ||
private String proxyPassword; | ||
private ProxyType proxyType; | ||
|
||
public ProxyInfo(ProxyType proxyType, String proxyHost, int proxyPort, String proxyUser, String proxyPassword) { | ||
this.proxyType = proxyType; | ||
this.proxyAddress = proxyHost; | ||
this.proxyPort = proxyPort; | ||
this.proxyUsername = proxyUser; | ||
this.proxyPassword = proxyPassword; | ||
} | ||
|
||
// ---------------------------------------------------------------- factory | ||
|
||
/** | ||
* Creates directProxy. | ||
*/ | ||
public static ProxyInfo directProxy() { | ||
return new ProxyInfo(ProxyType.NONE, null, 0, null, null); | ||
} | ||
|
||
/** | ||
* Creates SOCKS4 proxy. | ||
*/ | ||
public static ProxyInfo socks4Proxy(String proxyAddress, int proxyPort, String proxyUser) { | ||
return new ProxyInfo(ProxyType.SOCKS4, proxyAddress, proxyPort, proxyUser, null); | ||
} | ||
|
||
/** | ||
* Creates SOCKS5 proxy. | ||
*/ | ||
public static ProxyInfo socks5Proxy(String proxyAddress, int proxyPort, String proxyUser, String proxyPassword) { | ||
return new ProxyInfo(ProxyType.SOCKS5, proxyAddress, proxyPort, proxyUser, proxyPassword); | ||
} | ||
|
||
/** | ||
* Creates HTTP proxy. | ||
*/ | ||
public static ProxyInfo httpProxy(String proxyAddress, int proxyPort, String proxyUser, String proxyPassword) { | ||
return new ProxyInfo(ProxyType.HTTP, proxyAddress, proxyPort, proxyUser, proxyPassword); | ||
} | ||
|
||
// ---------------------------------------------------------------- getter | ||
|
||
/** | ||
* Returns proxy type. | ||
*/ | ||
public ProxyType getProxyType() { | ||
return proxyType; | ||
} | ||
|
||
/** | ||
* Returns proxy address. | ||
*/ | ||
public String getProxyAddress() { | ||
return proxyAddress; | ||
} | ||
|
||
/** | ||
* Returns proxy port. | ||
*/ | ||
public int getProxyPort() { | ||
return proxyPort; | ||
} | ||
|
||
/** | ||
* Returns proxy user name or <code>null</code> if | ||
* no authentication required. | ||
*/ | ||
public String getProxyUsername() { | ||
return proxyUsername; | ||
} | ||
|
||
/** | ||
* Returns proxy password or <code>null</code>. | ||
*/ | ||
public String getProxyPassword() { | ||
return proxyPassword; | ||
} | ||
|
||
/** | ||
* Returns socket factory based on socket | ||
*/ | ||
public SocketFactory getSocketFactory() { | ||
switch (proxyType) { | ||
case NONE: | ||
return SocketFactory.getDefault(); | ||
case HTTP: | ||
return new HTTPProxySocketFactory(this); | ||
case SOCKS4: | ||
return new Socks4ProxySocketFactory(this); | ||
case SOCKS5: | ||
return new Socks5ProxySocketFactory(this); | ||
} | ||
return null; | ||
} | ||
} |
72 changes: 0 additions & 72 deletions
72
jodd-http/src/main/java/jodd/http/net/ProxySocketFactory.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.