1   /*
2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/test/org/apache/commons/httpclient/server/ProxyRequestHandler.java,v 1.11 2004/12/11 22:35:26 olegk Exp $
3    * $Revision: 169849 $
4    * $Date: 2005-05-12 13:05:07 -0400 (Thu, 12 May 2005) $
5    *
6    * ====================================================================
7    *
8    *  Copyright 1999-2004 The Apache Software Foundation
9    *
10   *  Licensed under the Apache License, Version 2.0 (the "License");
11   *  you may not use this file except in compliance with the License.
12   *  You may obtain a copy of the License at
13   *
14   *      http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing, software
17   *  distributed under the License is distributed on an "AS IS" BASIS,
18   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   *  See the License for the specific language governing permissions and
20   *  limitations under the License.
21   * ====================================================================
22   *
23   * This software consists of voluntary contributions made by many
24   * individuals on behalf of the Apache Software Foundation.  For more
25   * information on the Apache Software Foundation, please see
26   * <http://www.apache.org/>.
27   *
28   */
29  
30  package org.apache.commons.httpclient.server;
31  
32  import java.io.IOException;
33  import java.net.UnknownHostException;
34  
35  import org.apache.commons.httpclient.Header;
36  import org.apache.commons.httpclient.HttpException;
37  import org.apache.commons.httpclient.HttpStatus;
38  import org.apache.commons.httpclient.HttpVersion;
39  import org.apache.commons.httpclient.URI;
40  import org.apache.commons.httpclient.URIException;
41  import org.apache.commons.logging.Log;
42  import org.apache.commons.logging.LogFactory;
43  
44  /***
45   * @author Ortwin Glueck
46   * @author Oleg Kalnichevski
47   */
48  public class ProxyRequestHandler implements HttpRequestHandler {
49  
50      private static final Log LOG = LogFactory.getLog(ProxyRequestHandler.class);
51  
52      private SimpleConnManager connmanager = null;
53      
54      public ProxyRequestHandler(final SimpleConnManager connmanager) {
55          super();
56          if (connmanager == null) {
57              throw new IllegalArgumentException("Connection manager may not be null");
58          }
59          this.connmanager = connmanager;
60      }
61      
62  	/***
63  	 * @see org.apache.commons.httpclient.server.HttpRequestHandler#processRequest(org.apache.commons.httpclient.server.SimpleHttpServerConnection)
64  	 */
65  	public boolean processRequest(
66          final SimpleHttpServerConnection conn,
67          final SimpleRequest request) throws IOException
68      {
69          httpProxy(conn, request);
70          return true;
71  	}
72  
73  	private void httpProxy(
74          final SimpleHttpServerConnection conn,
75          final SimpleRequest request) throws IOException {
76  
77          RequestLine oldreqline = request.getRequestLine();
78          URI uri = null;
79          SimpleHost host = null;
80          try {
81              uri = new URI(oldreqline.getUri(), true);
82              host = new SimpleHost(uri.getHost(), uri.getPort());
83          } catch (URIException ex) {
84              SimpleResponse response = ErrorResponse.getResponse(HttpStatus.SC_BAD_REQUEST);
85              conn.writeResponse(response);
86              return;
87          }
88          SimpleHttpServerConnection proxyconn = null;
89          try {
90              proxyconn = this.connmanager.openConnection(host);
91          } catch (UnknownHostException e) {
92              SimpleResponse response = ErrorResponse.getResponse(HttpStatus.SC_NOT_FOUND);
93              conn.writeResponse(response);
94              return;
95          }
96          try {
97              proxyconn.setSocketTimeout(0);
98              // Rewrite target url
99              RequestLine newreqline = new RequestLine(
100                     oldreqline.getMethod(), 
101                     uri.getEscapedPath(), 
102                     oldreqline.getHttpVersion()); 
103             request.setRequestLine(newreqline);
104             // Remove proxy-auth headers if present
105             request.removeHeaders("Proxy-Authorization");
106             // Manage connection persistence
107             Header connheader = request.getFirstHeader("Proxy-Connection");
108             if (connheader != null) {
109                 if (connheader.getValue().equalsIgnoreCase("close")) {
110                     request.setHeader(new Header("Connection", "close"));
111                 }
112             }
113             request.removeHeaders("Proxy-Connection");
114             
115             proxyconn.writeRequest(request);
116             
117             SimpleResponse response = proxyconn.readResponse();
118             if (response == null) {
119                 return;
120             }
121             response.setHeader(new Header("Via", "1.1 test (Test-Proxy)"));
122             connheader = response.getFirstHeader("Connection");
123             if (connheader != null) {
124                 String s = connheader.getValue(); 
125                 if (s.equalsIgnoreCase("close")) {
126                     response.setHeader(new Header("Proxy-Connection", "close"));
127                     conn.setKeepAlive(false);
128                     proxyconn.setKeepAlive(false);
129                     response.removeHeaders("Connection");
130                 }
131                 if (s.equalsIgnoreCase("keep-alive")) {
132                     response.setHeader(new Header("Proxy-Connection", "keep-alive"));
133                     conn.setKeepAlive(true);
134                     proxyconn.setKeepAlive(true);
135                     response.removeHeaders("Connection");
136                 }
137             } else {
138                 // Use protocol default connection policy
139                 if (response.getHttpVersion().greaterEquals(HttpVersion.HTTP_1_1)) {
140                     conn.setKeepAlive(true);
141                     proxyconn.setKeepAlive(true);
142                 } else {
143                     conn.setKeepAlive(false);
144                     proxyconn.setKeepAlive(false);
145                 }
146             }
147             if ("HEAD".equalsIgnoreCase(request.getRequestLine().getMethod())) {
148                 // this is a head request, we don't want to send the actualy content
149                 response.setBody(null);
150             }
151             conn.writeResponse(response);
152 
153         } catch (HttpException e) {
154             SimpleResponse response = ErrorResponse.getResponse(HttpStatus.SC_BAD_REQUEST);
155             conn.writeResponse(response);
156             proxyconn.setKeepAlive(false);
157         } catch (IOException e) {
158             LOG.warn(e.getMessage());
159             proxyconn.setKeepAlive(false);
160         } finally {
161             this.connmanager.releaseConnection(host, proxyconn);
162         }
163 	}
164     
165 }