1 /*
2 * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/ConnectMethod.java,v 1.15 2003/05/22 18:26:33 olegk Exp $
3 * $Revision: 1.15 $
4 * $Date: 2003/05/22 18:26:33 $
5 *
6 * ====================================================================
7 *
8 * The Apache Software License, Version 1.1
9 *
10 * Copyright (c) 1999-2003 The Apache Software Foundation. All rights
11 * reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in
22 * the documentation and/or other materials provided with the
23 * distribution.
24 *
25 * 3. The end-user documentation included with the redistribution, if
26 * any, must include the following acknowlegement:
27 * "This product includes software developed by the
28 * Apache Software Foundation (http://www.apache.org/)."
29 * Alternately, this acknowlegement may appear in the software itself,
30 * if and wherever such third-party acknowlegements normally appear.
31 *
32 * 4. The names "The Jakarta Project", "Commons", and "Apache Software
33 * Foundation" must not be used to endorse or promote products derived
34 * from this software without prior written permission. For written
35 * permission, please contact apache@apache.org.
36 *
37 * 5. Products derived from this software may not be called "Apache"
38 * nor may "Apache" appear in their names without prior written
39 * permission of the Apache Group.
40 *
41 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 * ====================================================================
54 *
55 * This software consists of voluntary contributions made by many
56 * individuals on behalf of the Apache Software Foundation. For more
57 * information on the Apache Software Foundation, please see
58 * <http://www.apache.org/>.
59 *
60 * [Additional notices, if required by prior licensing conditions]
61 *
62 */
63
64 package org.apache.commons.httpclient;
65
66 import java.io.IOException;
67
68 import org.apache.commons.logging.Log;
69 import org.apache.commons.logging.LogFactory;
70
71 /***
72 * <p>Wraps another method to tunnel through a proxy.</p>
73 *
74 * @author Ortwin Glueck
75 * @author dIon Gillard
76 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
77 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
78 * @since 2.0
79 * @version $Revision: 1.15 $ $Date: 2003/05/22 18:26:33 $
80 */
81 public class ConnectMethod extends HttpMethodBase {
82 /*** the name of this method */
83 public static final String NAME = "CONNECT";
84
85 /***
86 * Create a connect method wrapping the existing method
87 *
88 * @param method the {@link HttpMethod method} to execute after connecting
89 * to the server
90 */
91 public ConnectMethod(HttpMethod method) {
92 LOG.trace("enter ConnectMethod(HttpMethod)");
93 this.method = method;
94 }
95
96 /***
97 * Provide the {@link #NAME name} of this method.
98 *
99 * @return the String "CONNECT"
100 */
101 public String getName() {
102 return NAME;
103 }
104
105
106 /***
107 * This method does nothing. <tt>CONNECT</tt> request is not supposed
108 * to contain <tt>Authorization</tt> request header.
109 *
110 * @param state current state of http requests
111 * @param conn the connection to use for I/O
112 *
113 * @throws IOException when errors occur reading or writing to/from the
114 * connection
115 * @throws HttpException when a recoverable error occurs
116 *
117 * @see HttpMethodBase#addAuthorizationRequestHeader(HttpState, HttpConnection)
118 */
119 protected void addAuthorizationRequestHeader(HttpState state, HttpConnection conn)
120 throws IOException, HttpException {
121 // Do nothing. Not applicable to CONNECT method
122 }
123
124 /***
125 * This method does nothing. <tt>CONNECT</tt> request is not supposed
126 * to contain <tt>Content-Length</tt> request header.
127 *
128 * @param state current state of http requests
129 * @param conn the connection to use for I/O
130 *
131 * @throws IOException when errors occur reading or writing to/from the
132 * connection
133 * @throws HttpException when a recoverable error occurs
134 *
135 * @see HttpMethodBase#addContentLengthRequestHeader(HttpState, HttpConnection)
136 */
137 protected void addContentLengthRequestHeader(HttpState state, HttpConnection conn)
138 throws IOException, HttpException {
139 // Do nothing. Not applicable to CONNECT method
140 }
141
142 /***
143 * This method does nothing. <tt>CONNECT</tt> request is not supposed
144 * to contain <tt>Cookie</tt> request header.
145 *
146 * @param state current state of http requests
147 * @param conn the connection to use for I/O
148 *
149 * @throws IOException when errors occur reading or writing to/from the
150 * connection
151 * @throws HttpException when a recoverable error occurs
152 *
153 * @see HttpMethodBase#addCookieRequestHeader(HttpState, HttpConnection)
154 */
155 protected void addCookieRequestHeader(HttpState state, HttpConnection conn)
156 throws IOException, HttpException {
157 // Do nothing. Not applicable to CONNECT method
158 }
159
160
161 /***
162 * Populates the request headers map to with additional {@link Header
163 * headers} to be submitted to the given {@link HttpConnection}.
164 *
165 * <p>
166 * This implementation adds <tt>User-Agent</tt>, <tt>Host</tt>,
167 * and <tt>Proxy-Authorization</tt> headers, when appropriate.
168 * </p>
169 *
170 * @param state the client state
171 * @param conn the {@link HttpConnection} the headers will eventually be
172 * written to
173 * @throws IOException when an error occurs writing the request
174 * @throws HttpException when a HTTP protocol error occurs
175 *
176 * @see #writeRequestHeaders
177 */
178 protected void addRequestHeaders(HttpState state, HttpConnection conn)
179 throws IOException, HttpException {
180 LOG.trace("enter ConnectMethod.addRequestHeaders(HttpState, "
181 + "HttpConnection)");
182 addUserAgentRequestHeader(state, conn);
183 addHostRequestHeader(state, conn);
184 addProxyAuthorizationRequestHeader(state, conn);
185 addProxyConnectionHeader(state, conn);
186 }
187
188 /***
189 * Execute this method by tunnelling and then executing the wrapped method.
190 *
191 * @param state the current http state
192 * @param conn the connection to write to
193 * @return the http status code from execution
194 * @throws HttpException when an error occurs writing the headers
195 * @throws IOException when an error occurs writing the headers
196 */
197 public int execute(HttpState state, HttpConnection conn)
198 throws IOException, HttpException {
199
200 LOG.trace("enter ConnectMethod.execute(HttpState, HttpConnection)");
201 int code = super.execute(state, conn);
202 LOG.debug("CONNECT status code " + code);
203 if ((code >= 200) && (code < 300)) {
204 conn.tunnelCreated();
205 code = method.execute(state, conn);
206 } else {
207 // What is to follow is an ugly hack.
208 // I REALLY hate having to resort to such
209 // an appalling trick
210 // TODO: Connect method must be redesigned.
211 // The only feasible solution is to split monolithic
212 // HttpMethod into HttpRequest/HttpResponse pair.
213 // That would allow to execute CONNECT method
214 // behind the scene and return CONNECT HttpResponse
215 // object in response to the original request that
216 // contains the correct status line, headers &
217 // response body.
218
219 LOG.debug("CONNECT failed, fake the response for the original method");
220 if (method instanceof HttpMethodBase) {
221 // Pass the status, headers and response stream to the wrapped
222 // method.
223 // To ensure that the connection is not released more than once
224 // this method is still responsible for releasing the connection.
225 // This will happen when the response body is consumed, or when
226 // the wrapped method closes the response connection in
227 // releaseConnection().
228 ((HttpMethodBase) method).fakeResponse(
229 getStatusLine(),
230 getResponseHeaderGroup(),
231 getResponseStream()
232 );
233 } else {
234 releaseConnection();
235 }
236 }
237 return code;
238 }
239
240 /***
241 * Special Connect request.
242 *
243 * @param state the current http state
244 * @param conn the connection to write to
245 * @throws IOException when an error occurs writing the request
246 * @throws HttpException when an error occurs writing the request
247 */
248 protected void writeRequestLine(HttpState state, HttpConnection conn)
249 throws IOException, HttpException {
250 int port = conn.getPort();
251 if (port == -1) {
252 port = conn.getProtocol().getDefaultPort();
253 }
254 StringBuffer buffer = new StringBuffer();
255 buffer.append(getName());
256 buffer.append(' ');
257 buffer.append(conn.getHost());
258 if (port > -1) {
259 buffer.append(':');
260 buffer.append(port);
261 }
262 buffer.append(" HTTP/1.1");
263 String line = buffer.toString();
264 conn.printLine(line);
265 if (Wire.enabled()) {
266 Wire.output(line);
267 }
268 }
269
270 /***
271 * Returns <code>true</code> if the status code is anything other than
272 * SC_OK, <code>false</code> otherwise.
273 *
274 * @see HttpMethodBase#shouldCloseConnection(HttpConnection)
275 * @see HttpStatus#SC_OK
276 *
277 * @return <code>true</code> if the connection should be closed
278 */
279 protected boolean shouldCloseConnection(HttpConnection conn) {
280 return (getStatusCode() != HttpStatus.SC_OK);
281 }
282
283 /*** Log object for this class. */
284 private static final Log LOG = LogFactory.getLog(ConnectMethod.class);
285
286 /*** The wrapped method */
287 private HttpMethod method;
288
289 }
This page was automatically generated by Maven