You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ri...@apache.org on 2008/01/08 18:55:41 UTC
svn commit: r610084 - in /geronimo/sandbox/AsyncHttpClient: ./
src/main/java/org/apache/ahc/ src/main/java/org/apache/ahc/codec/
src/main/java/org/apache/ahc/proxy/ src/test/java/org/apache/ahc/
Author: rickmcguire
Date: Tue Jan 8 09:55:22 2008
New Revision: 610084
URL: http://svn.apache.org/viewvc?rev=610084&view=rev
Log:
GERONIMO-3706 support for proxy
GERONIMO-3735 upgrade mina to 1.1.5
Added:
geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/
geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyConfiguration.java (with props)
geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyFilter.java (with props)
geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/ProxyTest.java (with props)
Modified:
geronimo/sandbox/AsyncHttpClient/pom.xml
geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/AsyncHttpClient.java
geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpRequestEncoder.java
geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpRequestMessage.java
Modified: geronimo/sandbox/AsyncHttpClient/pom.xml
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/pom.xml?rev=610084&r1=610083&r2=610084&view=diff
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/pom.xml (original)
+++ geronimo/sandbox/AsyncHttpClient/pom.xml Tue Jan 8 09:55:22 2008
@@ -38,12 +38,12 @@
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
- <version>1.1.2</version>
+ <version>1.1.5</version>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-filter-ssl</artifactId>
- <version>1.1.2</version>
+ <version>1.1.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@@ -107,6 +107,10 @@
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>pertest</forkMode>
+ <excludes>
+ <exclude>**/ProxyTest.java</exclude>
+ <exclude>**/AbstractTest.java</exclude>
+ </excludes>
</configuration>
</plugin>
<plugin>
Modified: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/AsyncHttpClient.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/AsyncHttpClient.java?rev=610084&r1=610083&r2=610084&view=diff
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/AsyncHttpClient.java (original)
+++ geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/AsyncHttpClient.java Tue Jan 8 09:55:22 2008
@@ -20,6 +20,9 @@
package org.apache.ahc;
import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
+import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
@@ -33,6 +36,7 @@
import org.apache.ahc.codec.HttpRequestMessage;
import org.apache.ahc.codec.ResponseFuture;
import org.apache.ahc.codec.SessionCache;
+import org.apache.ahc.proxy.ProxyFilter;
import org.apache.ahc.ssl.TrustManagerFactoryImpl;
import org.apache.ahc.util.AsyncHttpClientException;
import org.apache.mina.common.ConnectFuture;
@@ -144,6 +148,11 @@
/** flag to make this as having been disposed of */
private boolean destroyed = false;
+ public static final String SSL_FILTER = "SSL";
+ public static final String PROTOCOL_FILTER = "protocolFilter";
+ public static final String PROXY_FILTER = "proxyFilter";
+ public static final String EVENT_THREAD_POOL_FILTER = "eventThreadPoolFilter";
+
/**
* Returns if it reuses established connections for more requests.
*
@@ -445,11 +454,13 @@
// *IF* connection reuse is enabled, we should see if we have a cached
// connection first; if not, always open a new one
ConnectFuture future = null;
- if (reuseConnection) {
- future = getCachedConnection(message);
- } else {
- // add the Connection close header explicitly
- message.setHeader(HttpDecoder.CONNECTION, HttpDecoder.CLOSE);
+ if (!message.isProxyEnabled()) {
+ if (reuseConnection) {
+ future = getCachedConnection(message);
+ } else {
+ // add the Connection close header explicitly
+ message.setHeader(HttpDecoder.CONNECTION, HttpDecoder.CLOSE);
+ }
}
// if no cached connection is found or keep-alive is disabled, force a
@@ -458,7 +469,11 @@
future = openConnection(message);
}
ResponseFuture response = message.getResponseFuture();
- future.addListener(new FutureListener(message, response, connectionRetries));
+ FutureListener listener =
+ message.isProxyEnabled() ?
+ new ProxyFutureListener(message, response) :
+ new FutureListener(message, response);
+ future.addListener(listener);
return response;
}
@@ -472,13 +487,17 @@
* attempt. This should be one less than the count
* used for the previous attempt.
*/
- private void retryConnection(HttpRequestMessage message, ResponseFuture response, int retries) {
+ private void retryConnection(HttpRequestMessage message, ResponseFuture response, FutureListener listener) {
ConnectFuture future = openConnection(message);
- future.addListener(new FutureListener(message, response, retries));
+ future.addListener(listener);
}
private ConnectFuture openConnection(HttpRequestMessage message) {
- return connector.connect(new InetSocketAddress(message.getHost(), message.getPort()), handler);
+ InetSocketAddress remote =
+ message.isProxyEnabled() ?
+ message.getProxyConfiguration().getProxyAddress(message.getUrl()) :
+ new InetSocketAddress(message.getHost(), message.getPort());
+ return connector.connect(remote, handler);
}
private ConnectFuture getCachedConnection(HttpRequestMessage message) {
@@ -543,17 +562,13 @@
* connection occurs, it is also responsible for sending the request.
*/
class FutureListener implements IoFutureListener {
- static final String SSL_FILTER = "SSL";
- static final String PROTOCOL_FILTER = "protocolFilter";
- static final String EVENT_THREAD_POOL_FILTER = "eventThreadPoolFilter";
-
/** The request. */
final HttpRequestMessage request;
/** The response future. */
final ResponseFuture response;
/** The count of additional retries for the connection */
- int retries = 0;
+ volatile int retries = getConnectionRetries();
/**
* Instantiates a new future listener for a connection.
@@ -561,10 +576,9 @@
* @param request the <code>HttpRequestMessage</code> request that is to be sent.
* @param response the response future object.
*/
- public FutureListener(HttpRequestMessage request, ResponseFuture response, int retries) {
+ public FutureListener(HttpRequestMessage request, ResponseFuture response) {
this.request = request;
this.response = response;
- this.retries = retries;
}
/**
@@ -583,38 +597,18 @@
addSSLFilter(sess);
// add the protocol filter (if it's not there already like in a
// reused session)
- if (!sess.getFilterChain().contains(PROTOCOL_FILTER)) {
- sess.getFilterChain().addLast(PROTOCOL_FILTER, new ProtocolCodecFilter(
- new HttpProtocolCodecFactory()));
- }
+ addProtocolCodecFilter(sess);
// (optional) add the executor filter for the event thread pool
// (if it's not there already like in a reused session)
- if (eventThreadPool != null &&
- !sess.getFilterChain().contains(EVENT_THREAD_POOL_FILTER)) {
- sess.getFilterChain().addLast(EVENT_THREAD_POOL_FILTER,
- new ExecutorFilter(eventThreadPool));
- }
+ addEventThreadPoolFilter(sess);
- sess.setAttribute(HttpIoHandler.CURRENT_REQUEST, request);
-
- sess.setAttachment(AsyncHttpClient.this);
-
- //Set the socket parameters on successfully obtaining the session
- SocketSessionConfig config = (SocketSessionConfig) sess.getConfig();
- config.setKeepAlive(keepAlive);
- config.setOobInline(oobInline);
- config.setReceiveBufferSize(receiveBufferSize);
- config.setReuseAddress(reuseAddress);
- config.setSendBufferSize(sendBufferSize);
- config.setSoLinger(soLinger);
- config.setTcpNoDelay(tcpNoDelay);
- config.setTrafficClass(trafficClass);
+ configureSession(sess);
sess.write(request);
} else {
- if (retries > 0) {
+ if (retries-- > 0) {
// go retry this connection
- retryConnection(request, response, --retries);
+ retryConnection(request, response, this);
}
else {
try {
@@ -628,6 +622,38 @@
}
}
+ protected void configureSession(IoSession sess) {
+ sess.setAttribute(HttpIoHandler.CURRENT_REQUEST, request);
+
+ sess.setAttachment(AsyncHttpClient.this);
+
+ //Set the socket parameters on successfully obtaining the session
+ SocketSessionConfig config = (SocketSessionConfig) sess.getConfig();
+ config.setKeepAlive(keepAlive);
+ config.setOobInline(oobInline);
+ config.setReceiveBufferSize(receiveBufferSize);
+ config.setReuseAddress(reuseAddress);
+ config.setSendBufferSize(sendBufferSize);
+ config.setSoLinger(soLinger);
+ config.setTcpNoDelay(tcpNoDelay);
+ config.setTrafficClass(trafficClass);
+ }
+
+ protected void addEventThreadPoolFilter(IoSession sess) {
+ if (eventThreadPool != null &&
+ !sess.getFilterChain().contains(EVENT_THREAD_POOL_FILTER)) {
+ sess.getFilterChain().addLast(EVENT_THREAD_POOL_FILTER,
+ new ExecutorFilter(eventThreadPool));
+ }
+ }
+
+ protected void addProtocolCodecFilter(IoSession sess) {
+ if (!sess.getFilterChain().contains(PROTOCOL_FILTER)) {
+ sess.getFilterChain().addLast(PROTOCOL_FILTER, new ProtocolCodecFilter(
+ new HttpProtocolCodecFactory()));
+ }
+ }
+
private void addSSLFilter(IoSession sess) {
String scheme = request.getUrl().getProtocol();
@@ -637,14 +663,7 @@
// session
if (!sess.getFilterChain().contains(SSL_FILTER)) {
try {
- SSLContext context = request.getSSLContext();
- if (context == null) {
- // if the caller did not provide an SSL context
- // create a default SSL context
- context = createDefaultSSLContext();
- }
- SSLFilter sslFilter = new SSLFilter(context);
- sslFilter.setUseClientMode(true);
+ SSLFilter sslFilter = createSSLFilter();
sess.getFilterChain().addLast(SSL_FILTER, sslFilter);
} catch (GeneralSecurityException e) {
try {
@@ -657,6 +676,18 @@
}
}
+ protected SSLFilter createSSLFilter() throws GeneralSecurityException {
+ SSLContext context = request.getSSLContext();
+ if (context == null) {
+ // if the caller did not provide an SSL context
+ // create a default SSL context
+ context = createDefaultSSLContext();
+ }
+ SSLFilter sslFilter = new SSLFilter(context);
+ sslFilter.setUseClientMode(true);
+ return sslFilter;
+ }
+
/**
* Creates a default SSL context in case it was not provided by the
* caller.
@@ -670,5 +701,70 @@
return context;
}
+ }
+
+ class ProxyFutureListener extends FutureListener {
+ public ProxyFutureListener(HttpRequestMessage request,
+ ResponseFuture response) {
+ super(request, response);
+ }
+
+ @Override
+ public void operationComplete(IoFuture future) {
+ ConnectFuture connectFuture = (ConnectFuture)future;
+ if (connectFuture.isConnected()) {
+ IoSession session = future.getSession();
+ // add the protocol filter (if it's not there already like in a
+ // reused session)
+ addProtocolCodecFilter(session);
+ addProxyFilter(session);
+ // (optional) add the executor filter for the event thread pool
+ // (if it's not there already like in a reused session)
+ addEventThreadPoolFilter(session);
+
+ configureSession(session);
+
+ // write the connect request if the protocol is https
+ String protocol = request.getUrl().getProtocol();
+ if (protocol.toLowerCase().equals("https")) {
+ session.write(createConnectRequest());
+ } else {
+ session.write(request);
+ }
+ } else {
+ super.operationComplete(future);
+ }
+ }
+
+ private HttpRequestMessage createConnectRequest() {
+ try {
+ HttpRequestMessage req = new HttpRequestMessage(new URL("http", request.getHost(), request.getPort(), ""), null);
+ req.setRequestMethod(HttpRequestMessage.REQUEST_CONNECT);
+ return req;
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ } catch (ProtocolException e) {
+ e.printStackTrace();
+ }
+ // this can't happen
+ return null;
+ }
+
+ private void addProxyFilter(IoSession session) {
+ if (!session.getFilterChain().contains(PROXY_FILTER)) {
+ String scheme = request.getUrl().getProtocol();
+ ProxyFilter proxyFilter = null;
+ if (scheme.toLowerCase().equals("https")) {
+ try {
+ proxyFilter = new ProxyFilter(createSSLFilter());
+ } catch (GeneralSecurityException e) {
+ e.printStackTrace(); // this normally cannot happen
+ }
+ } else {
+ proxyFilter = new ProxyFilter();
+ }
+ session.getFilterChain().addLast(PROXY_FILTER, proxyFilter);
+ }
+ }
}
}
Modified: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpRequestEncoder.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpRequestEncoder.java?rev=610084&r1=610083&r2=610084&view=diff
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpRequestEncoder.java (original)
+++ geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpRequestEncoder.java Tue Jan 8 09:55:22 2008
@@ -106,16 +106,26 @@
CharsetEncoder encoder = Charset.forName(HttpMessage.HTTP_ELEMENT_CHARSET).newEncoder();
buf.putString(msg.getRequestMethod(), encoder);
buf.putString(" ", encoder);
- buf.putString(msg.getUrl().getFile(), encoder);
- //If its a GET, append the attributes
- if (msg.getRequestMethod().equals(HttpRequestMessage.REQUEST_GET) && attrCount > 0) {
- //If there is not already a ? in the query, append one, otherwise append a &
- if (!msg.getUrl().getFile().contains("?")) {
- buf.putString("?", encoder);
+ if (msg.getRequestMethod().equals(HttpRequestMessage.REQUEST_CONNECT)) {
+ buf.putString(msg.getHost(), encoder);
+ buf.putString(":", encoder);
+ buf.putString(msg.getPort() + "", encoder);
+ } else {
+ if (msg.isProxyEnabled() && !msg.getProtocol().toLowerCase().equals("https")) {
+ buf.putString(msg.getUrl().toString(), encoder);
} else {
- buf.putString("&", encoder);
+ buf.putString(msg.getUrl().getFile(), encoder);
+ }
+ //If its a GET, append the attributes
+ if (msg.getRequestMethod().equals(HttpRequestMessage.REQUEST_GET) && attrCount > 0) {
+ //If there is not already a ? in the query, append one, otherwise append a &
+ if (!msg.getUrl().getFile().contains("?")) {
+ buf.putString("?", encoder);
+ } else {
+ buf.putString("&", encoder);
+ }
+ buf.putString(urlAttrs, encoder);
}
- buf.putString(urlAttrs, encoder);
}
buf.putString(" HTTP/1.1", encoder);
buf.put(CRLF);
Modified: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpRequestMessage.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpRequestMessage.java?rev=610084&r1=610083&r2=610084&view=diff
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpRequestMessage.java (original)
+++ geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpRequestMessage.java Tue Jan 8 09:55:22 2008
@@ -32,6 +32,7 @@
import org.apache.ahc.auth.AuthScope;
import org.apache.ahc.auth.AuthState;
import org.apache.ahc.auth.Credentials;
+import org.apache.ahc.proxy.ProxyConfiguration;
/**
* The Class HttpRequestMessage. This is an object representation of an HTTP request.
@@ -82,6 +83,8 @@
* The Constant REQUEST_TRACE.
*/
public static final String REQUEST_TRACE = "TRACE";
+
+ public static final String REQUEST_CONNECT = "CONNECT";
/**
* The request method.
@@ -153,6 +156,8 @@
* SSL context for https
*/
private SSLContext sslContext;
+
+ private ProxyConfiguration proxyConfig;
/**
* Instantiates a new http request message.
@@ -249,7 +254,8 @@
|| requestMethod.equals(REQUEST_OPTIONS)
|| requestMethod.equals(REQUEST_PUT)
|| requestMethod.equals(REQUEST_DELETE)
- || requestMethod.equals(REQUEST_TRACE)) {
+ || requestMethod.equals(REQUEST_TRACE)
+ || requestMethod.equals(REQUEST_CONNECT)) {
this.requestMethod = requestMethod;
return;
}
@@ -538,5 +544,17 @@
*/
public void setSSLContext(SSLContext sslContext) {
this.sslContext = sslContext;
+ }
+
+ public ProxyConfiguration getProxyConfiguration() {
+ return proxyConfig;
+ }
+
+ public void setProxyConfiguration(ProxyConfiguration config) {
+ proxyConfig = config;
+ }
+
+ public boolean isProxyEnabled() {
+ return proxyConfig != null && !proxyConfig.isExcluded(getUrl());
}
}
Added: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyConfiguration.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyConfiguration.java?rev=610084&view=auto
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyConfiguration.java (added)
+++ geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyConfiguration.java Tue Jan 8 09:55:22 2008
@@ -0,0 +1,180 @@
+package org.apache.ahc.proxy;
+
+import java.net.InetSocketAddress;
+import java.net.InetAddress;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.apache.ahc.auth.AuthScheme;
+
+public class ProxyConfiguration {
+ private final String httpProxyHost;
+ private final int httpProxyPort;
+ private final String httpsProxyHost;
+ private final int httpsProxyPort;
+ private String exclusionList = null;
+ private String proxyUser = null;
+ private String proxyPassword = null;
+ private AuthScheme scheme = null;
+ private List<String> wildCardExclusions = new ArrayList<String>();
+ private Map<String,String> directExclusions = new HashMap<String,String>();
+
+ /**
+ * Construct a ProxyConfiguration instance.
+ *
+ * @param proxyHost The host to be used for both http and https connections.
+ * @param proxyPort The port to be used for both http and https connections.
+ */
+ public ProxyConfiguration(String proxyHost, int proxyPort) {
+ this.httpProxyHost = proxyHost;
+ this.httpProxyPort = proxyPort;
+ this.httpsProxyHost = proxyHost;
+ this.httpsProxyPort = proxyPort;
+ }
+
+ /**
+ * Construct a proxy configuration that uses separate
+ * http and https proxy targets.
+ *
+ * @param httpProxyHost
+ * The host to be used for http requests.
+ * @param httpProxyPort
+ * The port to be used for http requests.
+ * @param httpsProxyHost
+ * The host to use for https requests.
+ * @param httpsProxyPort
+ */
+ public ProxyConfiguration(String httpProxyHost, int httpProxyPort, String httpsProxyHost, int httpsProxyPort) {
+ this.httpProxyHost = httpProxyHost;
+ this.httpProxyPort = httpProxyPort;
+ this.httpsProxyHost = httpsProxyHost;
+ this.httpsProxyPort = httpsProxyPort;
+ }
+
+
+ /**
+ * Get the target connection for a proxied request.
+ * The target will depend on whether this is an http
+ * or an https request.
+ *
+ * @param target The target URL
+ *
+ * @return An InetSocketAddress for the appropriate proxy target.
+ */
+ public InetSocketAddress getProxyAddress(URL target)
+ {
+ if (target.getProtocol().equalsIgnoreCase("https")) {
+ return new InetSocketAddress(getHttpsProxyHost(), getHttpsProxyPort());
+ }
+ else {
+ return new InetSocketAddress(getHttpProxyHost(), getHttpProxyPort());
+ }
+ }
+
+ public String getHttpProxyHost() {
+ return httpProxyHost;
+ }
+
+ public int getHttpProxyPort() {
+ return httpProxyPort;
+ }
+
+ public String getHttpsProxyHost() {
+ return httpsProxyHost;
+ }
+
+ public int getHttpsProxyPort() {
+ return httpsProxyPort;
+ }
+
+ public String getExclusionList() {
+ return exclusionList;
+ }
+
+ /**
+ * Set the exclusion list for the proxy configuration.
+ * The exclusion list is a set of explicit hosts and/or
+ * wildcard domains ("*.apache.org") separated by ";".
+ *
+ * @param exclusionList
+ */
+ public void setExclusionList(String exclusionList) {
+ this.exclusionList = exclusionList;
+ // we clear these out regardless
+ wildCardExclusions.clear();
+ directExclusions.clear();
+
+ if (exclusionList != null) {
+ // now divide the exclusion list into the explict and wildcard lists
+ StringTokenizer tokenizer = new StringTokenizer(exclusionList, ";");
+ while (tokenizer.hasMoreTokens()) {
+ String domain = tokenizer.nextToken();
+ // wild card versions we just create a matching list that we run through
+ if (domain.startsWith("*.")) {
+ wildCardExclusions.add(domain.substring(1));
+ }
+ else {
+ // the direct exlusions are names we can look up via a map.
+ directExclusions.put(domain, domain);
+ }
+ }
+ }
+ }
+
+ public String getProxyUser() {
+ return proxyUser;
+ }
+
+ public void setProxyUser(String proxyUser) {
+ this.proxyUser = proxyUser;
+ }
+
+ public String getProxyPassword() {
+ return proxyPassword;
+ }
+
+ public void setProxyPassword(String proxyPassword) {
+ this.proxyPassword = proxyPassword;
+ }
+
+ public AuthScheme getAuthScheme() {
+ return scheme;
+ }
+
+ public void setAuthScheme(AuthScheme scheme) {
+ this.scheme = scheme;
+ }
+
+ /**
+ * Tests if the host in a target URL is specified in
+ * the proxy configuration exclusion list.
+ *
+ * @param target The target URL of the connection.
+ *
+ * @return true if the host is included in the configuration
+ * exclusion list. false indicates the connection
+ * needs to go through the proxy server.
+ */
+ public boolean isExcluded(URL target) {
+ String host = target.getHost();
+
+ // if the host is explicitly listed, this is easy
+ if (directExclusions.get(host) != null) {
+ return true;
+ }
+ // the wildcard elements are stored as ".apache.org", so
+ // a simple endsWith() test will gives a match on something
+ // like "people.apache.org".
+ for (String domain : wildCardExclusions) {
+ if (host.endsWith(domain)) {
+ return true;
+ }
+ }
+ // not found in any host
+ return false;
+ }
+}
Propchange: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyConfiguration.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyConfiguration.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyConfiguration.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyFilter.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyFilter.java?rev=610084&view=auto
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyFilter.java (added)
+++ geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyFilter.java Tue Jan 8 09:55:22 2008
@@ -0,0 +1,81 @@
+package org.apache.ahc.proxy;
+
+import org.apache.ahc.AsyncHttpClient;
+import org.apache.ahc.auth.UsernamePasswordCredentials;
+import org.apache.ahc.codec.HttpIoHandler;
+import org.apache.ahc.codec.HttpRequestMessage;
+import org.apache.ahc.codec.HttpResponseMessage;
+import org.apache.mina.common.IoFilterAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.SSLFilter;
+
+public class ProxyFilter extends IoFilterAdapter {
+ public static final String PROXY_AUTHORIZATION_HEADER = "Proxy-Authorization";
+
+ private volatile boolean connectHandshakeComplete;
+ private final SSLFilter sslFilter;
+
+ public ProxyFilter() {
+ this(null);
+ }
+
+ public ProxyFilter(SSLFilter sslFilter) {
+ this.sslFilter = sslFilter;
+ }
+
+ @Override
+ public void messageSent(NextFilter nextFilter, IoSession session,
+ Object message) throws Exception {
+ HttpRequestMessage request = (HttpRequestMessage)message;
+ ProxyConfiguration proxyConfig = request.getProxyConfiguration();
+ if (proxyConfig != null &&
+ proxyConfig.getProxyUser() != null &&
+ proxyConfig.getProxyPassword() != null &&
+ proxyConfig.getAuthScheme() != null) { // can proxy config ever be null?
+ // add the proxy authorization header
+ UsernamePasswordCredentials cred =
+ new UsernamePasswordCredentials(proxyConfig.getProxyUser(),
+ proxyConfig.getProxyPassword());
+ String authHeader = proxyConfig.getAuthScheme().authenticate(cred, request);
+ request.setHeader(PROXY_AUTHORIZATION_HEADER, authHeader);
+ }
+ // always forward
+ super.messageSent(nextFilter, session, message);
+ }
+
+ private HttpRequestMessage getRequest(IoSession session) {
+ HttpRequestMessage request =
+ (HttpRequestMessage)session.getAttribute(HttpIoHandler.CURRENT_REQUEST);
+ return request;
+ }
+
+ @Override
+ public void messageReceived(NextFilter nextFilter, IoSession session,
+ Object message) throws Exception {
+ if (needConnectHandshake()) {
+ // we need to complete the connect handshake
+ handleConnectResponse(session, message);
+ } else {
+ super.messageReceived(nextFilter, session, message);
+ }
+ }
+
+ private boolean needConnectHandshake() {
+ return (sslFilter != null && !connectHandshakeComplete);
+ }
+
+ private void handleConnectResponse(IoSession session, Object message) {
+ HttpResponseMessage response = (HttpResponseMessage)message;
+ int status = response.getStatusCode();
+ if (status == 200) {
+ // layer the SSL socket by inserting the SSL filter
+ session.getFilterChain().addBefore(AsyncHttpClient.PROTOCOL_FILTER, "SSL", sslFilter);
+ connectHandshakeComplete = true; // handshake is done
+ HttpRequestMessage request = getRequest(session);
+ // write the original request intended for the remote target
+ session.write(request);
+ } else {
+ session.close();
+ }
+ }
+}
Propchange: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyFilter.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyFilter.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/proxy/ProxyFilter.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/ProxyTest.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/ProxyTest.java?rev=610084&view=auto
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/ProxyTest.java (added)
+++ geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/ProxyTest.java Tue Jan 8 09:55:22 2008
@@ -0,0 +1,117 @@
+package org.apache.ahc;
+
+import java.net.URL;
+import java.util.concurrent.Future;
+
+import org.apache.ahc.codec.HttpRequestMessage;
+import org.apache.ahc.codec.HttpResponseMessage;
+import org.apache.ahc.proxy.ProxyConfiguration;
+
+public class ProxyTest extends AbstractTest {
+ public void testHttpProxy() throws Exception {
+ AsyncHttpClient ahc = new AsyncHttpClient();
+
+ HttpRequestMessage request =
+ new HttpRequestMessage(new URL("http://localhost:8282/"), null);
+ ProxyConfiguration config = new ProxyConfiguration("localhost", 8888);
+ request.setProxyConfiguration(config);
+
+ Future<HttpResponseMessage> future = ahc.sendRequest(request);
+
+ HttpResponseMessage response = future.get();
+ assertEquals("\nHello World!", response.getStringContent());
+ }
+
+
+ public void testHttpProxyIP() throws Exception {
+ AsyncHttpClient ahc = new AsyncHttpClient();
+
+ HttpRequestMessage request =
+ new HttpRequestMessage(new URL("http://127.0.0.1:8282/"), null);
+ ProxyConfiguration config = new ProxyConfiguration("localhost", 8888);
+ request.setProxyConfiguration(config);
+
+ Future<HttpResponseMessage> future = ahc.sendRequest(request);
+
+ HttpResponseMessage response = future.get();
+ assertEquals("\nHello World!", response.getStringContent());
+ }
+
+ public void testHttpsProxySame() throws Exception {
+ AsyncHttpClient ahc = new AsyncHttpClient();
+
+ HttpRequestMessage request =
+ new HttpRequestMessage(new URL("https://localhost:8383/"), null);
+ ProxyConfiguration config = new ProxyConfiguration("localhost", 8888);
+ request.setProxyConfiguration(config);
+
+ Future<HttpResponseMessage> future = ahc.sendRequest(request);
+
+ HttpResponseMessage response = future.get();
+ assertEquals("\nHello World!", response.getStringContent());
+ }
+
+
+ public void testHttpsProxyDifferent() throws Exception {
+ AsyncHttpClient ahc = new AsyncHttpClient();
+
+ HttpRequestMessage request =
+ new HttpRequestMessage(new URL("https://localhost:8383/"), null);
+ ProxyConfiguration config = new ProxyConfiguration("people.apache.org", 8889, "localhost", 8888);
+ request.setProxyConfiguration(config);
+
+ Future<HttpResponseMessage> future = ahc.sendRequest(request);
+
+ HttpResponseMessage response = future.get();
+ assertEquals("\nHello World!", response.getStringContent());
+ }
+
+ public void testHttpExclusion() throws Exception {
+ AsyncHttpClient ahc = new AsyncHttpClient();
+
+ HttpRequestMessage request =
+ new HttpRequestMessage(new URL("http://localhost:8282/"), null);
+ // NOTE: The proxy server config is invalid, so this will fail if the
+ // exclusion doesn't work.
+ ProxyConfiguration config = new ProxyConfiguration("localhost", 8889);
+ config.setExclusionList("localhost");
+ request.setProxyConfiguration(config);
+
+ Future<HttpResponseMessage> future = ahc.sendRequest(request);
+
+ HttpResponseMessage response = future.get();
+ assertEquals("\nHello World!", response.getStringContent());
+ }
+
+ public void testHttpExclusionIP() throws Exception {
+ AsyncHttpClient ahc = new AsyncHttpClient();
+
+ HttpRequestMessage request =
+ new HttpRequestMessage(new URL("http://127.0.0.1:8282/"), null);
+ // NOTE: The proxy server config is invalid, so this will fail if the
+ // exclusion doesn't work.
+ ProxyConfiguration config = new ProxyConfiguration("localhost", 8889);
+ config.setExclusionList("127.0.0.1;*.apache.org");
+ request.setProxyConfiguration(config);
+
+ Future<HttpResponseMessage> future = ahc.sendRequest(request);
+
+ HttpResponseMessage response = future.get();
+ assertEquals("\nHello World!", response.getStringContent());
+ }
+
+ public void testHttpsExclusion() throws Exception {
+ AsyncHttpClient ahc = new AsyncHttpClient();
+
+ HttpRequestMessage request =
+ new HttpRequestMessage(new URL("https://localhost:8383/"), null);
+ ProxyConfiguration config = new ProxyConfiguration("localhost", 8889);
+ config.setExclusionList("localhost;*.apache.org");
+ request.setProxyConfiguration(config);
+
+ Future<HttpResponseMessage> future = ahc.sendRequest(request);
+
+ HttpResponseMessage response = future.get();
+ assertEquals("\nHello World!", response.getStringContent());
+ }
+}
Propchange: geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/ProxyTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/ProxyTest.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/ProxyTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain