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: 155418 $ $Date: 2005-02-26 08:01:52 -0500 (Sat, 26 Feb 2005) $
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(" ");
174 buffer.append(getEffectiveVersion());
175 String line = buffer.toString();
176 conn.printLine(line, getParams().getHttpElementCharset());
177 if (Wire.HEADER_WIRE.enabled()) {
178 Wire.HEADER_WIRE.output(line);
179 }
180 }
181
182 /***
183 * Returns <code>true</code> if the status code is anything other than
184 * SC_OK, <code>false</code> otherwise.
185 *
186 * @see HttpMethodBase#shouldCloseConnection(HttpConnection)
187 * @see HttpStatus#SC_OK
188 *
189 * @return <code>true</code> if the connection should be closed
190 */
191 protected boolean shouldCloseConnection(HttpConnection conn) {
192 if (getStatusCode() == HttpStatus.SC_OK) {
193 Header connectionHeader = null;
194 if (!conn.isTransparent()) {
195 connectionHeader = getResponseHeader("proxy-connection");
196 }
197 if (connectionHeader == null) {
198 connectionHeader = getResponseHeader("connection");
199 }
200 if (connectionHeader != null) {
201 if (connectionHeader.getValue().equalsIgnoreCase("close")) {
202 if (LOG.isWarnEnabled()) {
203 LOG.warn("Invalid header encountered '" + connectionHeader.toExternalForm()
204 + "' in response " + getStatusLine().toString());
205 }
206 }
207 }
208 return false;
209 } else {
210 return super.shouldCloseConnection(conn);
211 }
212 }
213
214 /*** Log object for this class. */
215 private static final Log LOG = LogFactory.getLog(ConnectMethod.class);
216
217 }