1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.apache.commons.httpclient;
31
32 import java.io.IOException;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37 /***
38 * Establishes a tunneled HTTP connection via the CONNECT method.
39 *
40 * @author Ortwin Gl???ck
41 * @author dIon Gillard
42 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
43 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
44 * @since 2.0
45 * @version $Revision: 1.28 $ $Date: 2004/05/13 04:03:25 $
46 */
47 public class ConnectMethod extends HttpMethodBase {
48
49 /*** the name of this method */
50 public static final String NAME = "CONNECT";
51
52 /***
53 * Create a connect method.
54 *
55 * @since 3.0
56 */
57 public ConnectMethod() {
58 LOG.trace("enter ConnectMethod()");
59 }
60
61 /***
62 * @deprecated the wrapped method is no longer used
63 *
64 * Create a connect method wrapping the existing method
65 *
66 * @param method the {@link HttpMethod method} to execute after connecting
67 * to the server
68 */
69 public ConnectMethod(HttpMethod method) {
70 LOG.trace("enter ConnectMethod(HttpMethod)");
71 }
72
73 /***
74 * Provide the {@link #NAME name} of this method.
75 *
76 * @return the String "CONNECT"
77 */
78 public String getName() {
79 return NAME;
80 }
81
82 /***
83 * This method does nothing. <tt>CONNECT</tt> request is not supposed
84 * to contain <tt>Cookie</tt> request header.
85 *
86 * @param state current state of http requests
87 * @param conn the connection to use for I/O
88 *
89 * @throws IOException when errors occur reading or writing to/from the
90 * connection
91 * @throws HttpException when a recoverable error occurs
92 *
93 * @see HttpMethodBase#addCookieRequestHeader(HttpState, HttpConnection)
94 */
95 protected void addCookieRequestHeader(HttpState state, HttpConnection conn)
96 throws IOException, HttpException {
97
98 }
99
100
101 /***
102 * Populates the request headers map to with additional {@link Header
103 * headers} to be submitted to the given {@link HttpConnection}.
104 *
105 * <p>
106 * This implementation adds <tt>User-Agent</tt>, <tt>Host</tt>,
107 * and <tt>Proxy-Authorization</tt> headers, when appropriate.
108 * </p>
109 *
110 * @param state the client state
111 * @param conn the {@link HttpConnection} the headers will eventually be
112 * written to
113 * @throws IOException when an error occurs writing the request
114 * @throws HttpException when a HTTP protocol error occurs
115 *
116 * @see #writeRequestHeaders
117 */
118 protected void addRequestHeaders(HttpState state, HttpConnection conn)
119 throws IOException, HttpException {
120 LOG.trace("enter ConnectMethod.addRequestHeaders(HttpState, "
121 + "HttpConnection)");
122 addUserAgentRequestHeader(state, conn);
123 addHostRequestHeader(state, conn);
124 addProxyConnectionHeader(state, conn);
125 }
126
127 /***
128 * Execute this method and create a tunneled HttpConnection. If the method
129 * is successful (i.e. the status is a 2xx) tunnelCreated() will be called
130 * on the connection.
131 *
132 * @param state the current http state
133 * @param conn the connection to write to
134 * @return the http status code from execution
135 * @throws HttpException when an error occurs writing the headers
136 * @throws IOException when an error occurs writing the headers
137 *
138 * @see HttpConnection#tunnelCreated()
139 */
140 public int execute(HttpState state, HttpConnection conn)
141 throws IOException, HttpException {
142
143 LOG.trace("enter ConnectMethod.execute(HttpState, HttpConnection)");
144 int code = super.execute(state, conn);
145 if (LOG.isDebugEnabled()) {
146 LOG.debug("CONNECT status code " + code);
147 }
148 return code;
149 }
150
151 /***
152 * Special Connect request.
153 *
154 * @param state the current http state
155 * @param conn the connection to write to
156 * @throws IOException when an error occurs writing the request
157 * @throws HttpException when an error occurs writing the request
158 */
159 protected void writeRequestLine(HttpState state, HttpConnection conn)
160 throws IOException, HttpException {
161 int port = conn.getPort();
162 if (port == -1) {
163 port = conn.getProtocol().getDefaultPort();
164 }
165 StringBuffer buffer = new StringBuffer();
166 buffer.append(getName());
167 buffer.append(' ');
168 buffer.append(conn.getHost());
169 if (port > -1) {
170 buffer.append(':');
171 buffer.append(port);
172 }
173 buffer.append(" HTTP/1.1");
174 String line = buffer.toString();
175 conn.printLine(line, getParams().getHttpElementCharset());
176 if (Wire.enabled()) {
177 Wire.output(line);
178 }
179 }
180
181 /***
182 * Returns <code>true</code> if the status code is anything other than
183 * SC_OK, <code>false</code> otherwise.
184 *
185 * @see HttpMethodBase#shouldCloseConnection(HttpConnection)
186 * @see HttpStatus#SC_OK
187 *
188 * @return <code>true</code> if the connection should be closed
189 */
190 protected boolean shouldCloseConnection(HttpConnection conn) {
191 if (getStatusCode() == HttpStatus.SC_OK) {
192 Header connectionHeader = null;
193 if (!conn.isTransparent()) {
194 connectionHeader = getResponseHeader("proxy-connection");
195 }
196 if (connectionHeader == null) {
197 connectionHeader = getResponseHeader("connection");
198 }
199 if (connectionHeader != null) {
200 if (connectionHeader.getValue().equalsIgnoreCase("close")) {
201 if (LOG.isWarnEnabled()) {
202 LOG.warn("Invalid header encountered '" + connectionHeader.toExternalForm()
203 + "' in response " + getStatusLine().toString());
204 }
205 }
206 }
207 return false;
208 } else {
209 return super.shouldCloseConnection(conn);
210 }
211 }
212
213 /*** Log object for this class. */
214 private static final Log LOG = LogFactory.getLog(ConnectMethod.class);
215
216 }