Skip to content

Commit

Permalink
Added various http proxies
Browse files Browse the repository at this point in the history
  • Loading branch information
igr committed Dec 23, 2013
1 parent 3f5d000 commit 7874d00
Show file tree
Hide file tree
Showing 7 changed files with 597 additions and 76 deletions.
8 changes: 8 additions & 0 deletions jodd-http/src/main/java/jodd/http/HttpException.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,15 @@ public HttpException(String message) {
super(message);
}

public HttpException(Object networkObject, String message) {
super(networkObject.toString() + ": " + message);
}

public HttpException(String message, Throwable t) {
super(message, t);
}

public HttpException(Object networkObject, String message, Throwable t) {
super(networkObject.toString() + ": " + message, t);
}
}
140 changes: 140 additions & 0 deletions jodd-http/src/main/java/jodd/http/net/HTTPProxySocketFactory.java
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*");
}
117 changes: 117 additions & 0 deletions jodd-http/src/main/java/jodd/http/net/ProxyInfo.java
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 jodd-http/src/main/java/jodd/http/net/ProxySocketFactory.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@
import java.net.Socket;

/**
* Socket-based {@link jodd.http.HttpConnectionProvider transport provider}.
* Socket factory for HTTP proxy.
*/
public class SocketHttpConnectionProvider implements HttpConnectionProvider {

protected SocketFactory socketFactory = SocketFactory.getDefault();
protected ProxyInfo proxy = ProxyInfo.directProxy();

/**
* Defines proxy to use for created sockets.
*/
public void useProxy(String proxyHost, int proxyPort) {
socketFactory = new ProxySocketFactory(proxyHost, proxyPort);
public void useProxy(ProxyInfo proxyInfo) {
proxy = proxyInfo;
}

/**
Expand All @@ -42,6 +42,8 @@ public HttpConnection createHttpConnection(HttpRequest httpRequest) throws IOExc

socket = sslSocket;
} else {
SocketFactory socketFactory = proxy.getSocketFactory();

socket = createSocket(socketFactory, httpRequest.host(), httpRequest.port());
}

Expand Down
Loading

0 comments on commit 7874d00

Please sign in to comment.