You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2011/10/06 22:16:59 UTC
svn commit: r1179817 - in /httpcomponents/httpclient/trunk/httpclient/src:
examples/org/apache/http/examples/client/ProxyTunnelDemo.java
main/java/org/apache/http/impl/client/ProxyClient.java
Author: olegk
Date: Thu Oct 6 20:16:59 2011
New Revision: 1179817
URL: http://svn.apache.org/viewvc?rev=1179817&view=rev
Log:
HTTPCLIENT-1132: ProxyClient implementation
Added:
httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/ProxyTunnelDemo.java (with props)
httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/ProxyClient.java (with props)
Added: httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/ProxyTunnelDemo.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/ProxyTunnelDemo.java?rev=1179817&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/ProxyTunnelDemo.java (added)
+++ httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/ProxyTunnelDemo.java Thu Oct 6 20:16:59 2011
@@ -0,0 +1,74 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.examples.client;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.net.Socket;
+
+import org.apache.http.HttpHost;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.impl.client.ProxyClient;
+import org.apache.http.protocol.HTTP;
+
+/**
+ * Example code for using {@link ProxyClient} in order to establish a tunnel through an HTTP proxy.
+ */
+public class ProxyTunnelDemo {
+
+ public final static void main(String[] args) throws Exception {
+
+ ProxyClient proxyClient = new ProxyClient();
+ HttpHost target = new HttpHost("www.yahoo.com", 80);
+ HttpHost proxy = new HttpHost("localhost", 8888);
+ UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("user", "pwd");
+ Socket socket = proxyClient.tunnel(proxy, target, credentials);
+ try {
+ Writer out = new OutputStreamWriter(socket.getOutputStream(),
+ HTTP.DEFAULT_CONTENT_CHARSET);
+ out.write("GET / HTTP/1.1\r\n");
+ out.write("Host: " + target.toHostString() + "\r\n");
+ out.write("Agent: whatever\r\n");
+ out.write("Connection: close\r\n");
+ out.write("\r\n");
+ out.flush();
+ BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(),
+ HTTP.DEFAULT_CONTENT_CHARSET));
+ String line = null;
+ while ((line = in.readLine()) != null) {
+ System.out.println(line);
+ }
+ } finally {
+ socket.close();
+ }
+ }
+
+}
+
Propchange: httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/ProxyTunnelDemo.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/ProxyTunnelDemo.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: httpcomponents/httpclient/trunk/httpclient/src/examples/org/apache/http/examples/client/ProxyTunnelDemo.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/ProxyClient.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/ProxyClient.java?rev=1179817&view=auto
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/ProxyClient.java (added)
+++ httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/ProxyClient.java Thu Oct 6 20:16:59 2011
@@ -0,0 +1,245 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.impl.client;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import javax.net.ssl.SSLSession;
+
+import org.apache.http.ConnectionReuseStrategy;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpException;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.HttpResponse;
+import org.apache.http.ProtocolVersion;
+import org.apache.http.auth.AuthSchemeRegistry;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.AuthState;
+import org.apache.http.auth.Credentials;
+import org.apache.http.client.params.AuthPolicy;
+import org.apache.http.client.params.HttpClientParams;
+import org.apache.http.client.protocol.ClientContext;
+import org.apache.http.client.protocol.RequestClientConnControl;
+import org.apache.http.client.protocol.RequestProxyAuthentication;
+import org.apache.http.conn.HttpRoutedConnection;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.entity.BufferedHttpEntity;
+import org.apache.http.impl.DefaultConnectionReuseStrategy;
+import org.apache.http.impl.DefaultHttpClientConnection;
+import org.apache.http.impl.auth.BasicSchemeFactory;
+import org.apache.http.impl.auth.DigestSchemeFactory;
+import org.apache.http.impl.auth.NTLMSchemeFactory;
+import org.apache.http.impl.auth.NegotiateSchemeFactory;
+import org.apache.http.message.BasicHttpRequest;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.HttpParams;
+import org.apache.http.params.HttpProtocolParams;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.ExecutionContext;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpProcessor;
+import org.apache.http.protocol.HttpRequestExecutor;
+import org.apache.http.protocol.ImmutableHttpProcessor;
+import org.apache.http.protocol.RequestContent;
+import org.apache.http.protocol.RequestTargetHost;
+import org.apache.http.protocol.RequestUserAgent;
+import org.apache.http.util.EntityUtils;
+
+public class ProxyClient {
+
+ private final HttpProcessor httpProcessor;
+ private final HttpRequestExecutor requestExec;
+ private final ProxyAuthenticationStrategy proxyAuthStrategy;
+ private final HttpAuthenticator authenticator;
+ private final AuthState proxyAuthState;
+ private final AuthSchemeRegistry authSchemeRegistry;
+ private final ConnectionReuseStrategy reuseStrategy;
+ private final HttpParams params;
+
+ public ProxyClient(final HttpParams params) {
+ super();
+ if (params == null) {
+ throw new IllegalArgumentException("HTTP parameters may not be null");
+ }
+ this.httpProcessor = new ImmutableHttpProcessor(new HttpRequestInterceptor[] {
+ new RequestContent(),
+ new RequestTargetHost(),
+ new RequestClientConnControl(),
+ new RequestUserAgent(),
+ new RequestProxyAuthentication()
+ } );
+ this.requestExec = new HttpRequestExecutor();
+ this.proxyAuthStrategy = new ProxyAuthenticationStrategy();
+ this.authenticator = new HttpAuthenticator();
+ this.proxyAuthState = new AuthState();
+ this.authSchemeRegistry = new AuthSchemeRegistry();
+ this.authSchemeRegistry.register(AuthPolicy.BASIC, new BasicSchemeFactory());
+ this.authSchemeRegistry.register(AuthPolicy.DIGEST, new DigestSchemeFactory());
+ this.authSchemeRegistry.register(AuthPolicy.NTLM, new NTLMSchemeFactory());
+ this.authSchemeRegistry.register(AuthPolicy.SPNEGO, new NegotiateSchemeFactory());
+ this.reuseStrategy = new DefaultConnectionReuseStrategy();
+ this.params = params;
+ }
+
+ public ProxyClient() {
+ this(new BasicHttpParams());
+ }
+
+ public HttpParams getParams() {
+ return this.params;
+ }
+
+ public AuthSchemeRegistry getAuthSchemeRegistry() {
+ return this.authSchemeRegistry;
+ }
+
+ public Socket tunnel(
+ final HttpHost proxy,
+ final HttpHost target,
+ final Credentials credentials) throws IOException, HttpException {
+ ProxyConnection conn = new ProxyConnection(new HttpRoute(proxy));
+ HttpContext context = new BasicHttpContext();
+ HttpResponse response = null;
+
+ for (;;) {
+ if (!conn.isOpen()) {
+ Socket socket = new Socket(proxy.getHostName(), proxy.getPort());
+ conn.bind(socket, this.params);
+ }
+ String host = target.getHostName();
+ int port = target.getPort();
+ if (port < 0) {
+ port = 80;
+ }
+
+ StringBuilder buffer = new StringBuilder(host.length() + 6);
+ buffer.append(host);
+ buffer.append(':');
+ buffer.append(Integer.toString(port));
+
+ String authority = buffer.toString();
+ ProtocolVersion ver = HttpProtocolParams.getVersion(this.params);
+ HttpRequest connect = new BasicHttpRequest("CONNECT", authority, ver);
+ connect.setParams(this.params);
+
+ BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
+ credsProvider.setCredentials(new AuthScope(proxy), credentials);
+
+ // Populate the execution context
+ context.setAttribute(ExecutionContext.HTTP_TARGET_HOST, target);
+ context.setAttribute(ExecutionContext.HTTP_PROXY_HOST, proxy);
+ context.setAttribute(ExecutionContext.HTTP_CONNECTION, conn);
+ context.setAttribute(ExecutionContext.HTTP_REQUEST, connect);
+ context.setAttribute(ClientContext.PROXY_AUTH_STATE, this.proxyAuthState);
+ context.setAttribute(ClientContext.CREDS_PROVIDER, credsProvider);
+ context.setAttribute(ClientContext.AUTHSCHEME_REGISTRY, this.authSchemeRegistry);
+
+ this.requestExec.preProcess(connect, this.httpProcessor, context);
+
+ response = this.requestExec.execute(connect, conn, context);
+
+ response.setParams(this.params);
+ this.requestExec.postProcess(response, this.httpProcessor, context);
+
+ int status = response.getStatusLine().getStatusCode();
+ if (status < 200) {
+ throw new HttpException("Unexpected response to CONNECT request: " +
+ response.getStatusLine());
+ }
+
+ if (HttpClientParams.isAuthenticating(this.params)) {
+ if (this.authenticator.isAuthenticationRequested(response,
+ this.proxyAuthStrategy, this.proxyAuthState, context)) {
+ if (this.authenticator.authenticate(proxy, response,
+ this.proxyAuthStrategy, this.proxyAuthState, context)) {
+ // Retry request
+ if (this.reuseStrategy.keepAlive(response, context)) {
+ // Consume response content
+ HttpEntity entity = response.getEntity();
+ EntityUtils.consume(entity);
+ } else {
+ conn.close();
+ }
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ int status = response.getStatusLine().getStatusCode();
+
+ if (status > 299) {
+
+ // Buffer response content
+ HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ response.setEntity(new BufferedHttpEntity(entity));
+ }
+
+ conn.close();
+ throw new TunnelRefusedException("CONNECT refused by proxy: " +
+ response.getStatusLine(), response);
+ }
+ return conn.getSocket();
+ }
+
+ static class ProxyConnection extends DefaultHttpClientConnection implements HttpRoutedConnection {
+
+ private final HttpRoute route;
+
+ ProxyConnection(final HttpRoute route) {
+ super();
+ this.route = route;
+ }
+
+ public HttpRoute getRoute() {
+ return this.route;
+ }
+
+ public boolean isSecure() {
+ return false;
+ }
+
+ public SSLSession getSSLSession() {
+ return null;
+ }
+
+ @Override
+ public Socket getSocket() {
+ return super.getSocket();
+ }
+
+ }
+
+}
Propchange: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/ProxyClient.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/ProxyClient.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/ProxyClient.java
------------------------------------------------------------------------------
svn:mime-type = text/plain