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