View Javadoc

1   /*
2    * $HeadURL: https://svn.apache.org/repos/asf/httpcomponents/oac.hc3x/trunk/src/java/org/apache/commons/httpclient/methods/ExpectContinueMethod.java $
3    * $Revision$
4    * $Date$
5    *
6    * ====================================================================
7    *
8    *  Licensed to the Apache Software Foundation (ASF) under one or more
9    *  contributor license agreements.  See the NOTICE file distributed with
10   *  this work for additional information regarding copyright ownership.
11   *  The ASF licenses this file to You under the Apache License, Version 2.0
12   *  (the "License"); you may not use this file except in compliance with
13   *  the License.  You may obtain a copy of the License at
14   *
15   *      http://www.apache.org/licenses/LICENSE-2.0
16   *
17   *  Unless required by applicable law or agreed to in writing, software
18   *  distributed under the License is distributed on an "AS IS" BASIS,
19   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   *  See the License for the specific language governing permissions and
21   *  limitations under the License.
22   * ====================================================================
23   *
24   * This software consists of voluntary contributions made by many
25   * individuals on behalf of the Apache Software Foundation.  For more
26   * information on the Apache Software Foundation, please see
27   * <http://www.apache.org/>.
28   *
29   */
30  
31  package org.apache.commons.httpclient.methods;
32  
33  import java.io.IOException;
34  import org.apache.commons.httpclient.HttpConnection;
35  import org.apache.commons.httpclient.HttpException;
36  import org.apache.commons.httpclient.HttpMethodBase;
37  import org.apache.commons.httpclient.HttpState;
38  import org.apache.commons.httpclient.HttpVersion;
39  import org.apache.commons.httpclient.params.HttpMethodParams;
40  import org.apache.commons.logging.Log;
41  import org.apache.commons.logging.LogFactory;
42  
43  /***
44   * <p>
45   * This abstract class serves as a foundation for all HTTP methods 
46   * that support 'Expect: 100-continue' handshake.
47   * </p>
48   * 
49   * <p>
50   * The purpose of the 100 (Continue) status (refer to section 10.1.1 
51   * of the RFC 2616 for more details) is to allow a client that is 
52   * sending a request message with a request body to determine if the 
53   * origin server is willing to accept the request (based on the request 
54   * headers) before the client sends the request body. In some cases,
55   * it might either be inappropriate or highly inefficient for the 
56   * client to send the body if the server will reject the message 
57   * without looking at the body.
58   * </p>
59   * 
60   * <p>
61   * 'Expect: 100-continue' handshake should be used with caution,
62   * as it may cause problems with HTTP servers and proxies that
63   * do not support HTTP/1.1 protocol.
64   * </p>
65   * 
66   * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
67   *
68   * @since 2.0beta1
69   */
70  
71  public abstract class ExpectContinueMethod extends HttpMethodBase {
72      
73      /*** LOG object for this class. */
74      private static final Log LOG = LogFactory.getLog(ExpectContinueMethod.class);
75  
76      /***
77       * No-arg constructor.
78       *
79       * @since 2.0
80       */
81      public ExpectContinueMethod() {
82          super();
83      }
84  
85      /***
86       * Constructor specifying a URI.
87       *
88       * @param uri either an absolute or relative URI
89       *
90       * @since 2.0
91       */
92      public ExpectContinueMethod(String uri) {
93          super(uri);
94      }
95  
96      /***
97       * <p>
98       * Returns <tt>true</tt> if the 'Expect: 100-Continue' handshake
99       * is activated. The purpose of the 'Expect: 100-Continue' 
100      * handshake to allow a client that is sending a request message 
101      * with a request body to determine if the origin server is 
102      * willing to accept the request (based on the request headers) 
103      * before the client sends the request body.
104      * </p>
105      * 
106      * @return <tt>true</tt> if 'Expect: 100-Continue' handshake is to
107      * be used, <tt>false</tt> otherwise.
108      * 
109      * @since 2.0beta1
110      * 
111      * @deprecated Use {@link HttpMethodParams}
112      * 
113      * @see #getParams()
114      * @see HttpMethodParams
115      * @see HttpMethodParams#USE_EXPECT_CONTINUE
116      */
117     public boolean getUseExpectHeader() {
118         return getParams().getBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, false);
119     }
120 
121     /***
122      * <p>
123      * Activates 'Expect: 100-Continue' handshake. The purpose of 
124      * the 'Expect: 100-Continue' handshake to allow a client that is 
125      * sending a request message with a request body to determine if 
126      * the origin server is willing to accept the request (based on 
127      * the request headers) before the client sends the request body.
128      * </p>
129      * 
130      * <p>
131      * The use of the 'Expect: 100-continue' handshake can result in 
132      * noticable peformance improvement for entity enclosing requests
133      * (such as POST and PUT) that require the target server's 
134      * authentication.
135      * </p>
136      * 
137      * <p>
138      * 'Expect: 100-continue' handshake should be used with 
139      * caution, as it may cause problems with HTTP servers and 
140      * proxies that do not support HTTP/1.1 protocol.
141      * </p>
142      * 
143      * @param value boolean value
144      * 
145      * @since 2.0beta1
146      * 
147      * @deprecated Use {@link HttpMethodParams}
148      * 
149      * @see #getParams()
150      * @see HttpMethodParams
151      * @see HttpMethodParams#USE_EXPECT_CONTINUE
152      */
153     public void setUseExpectHeader(boolean value) {
154         getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, value);
155     }
156 
157     /***
158      * Returns <tt>true</tt> if there is a request body to be sent.
159      * 'Expect: 100-continue' handshake may not be used if request
160      * body is not present
161      * 
162      * @return boolean
163      * 
164      * @since 2.0beta1
165      */
166     protected abstract boolean hasRequestContent();
167 
168     /***
169      * Sets the <tt>Expect</tt> header if it has not already been set, 
170      * in addition to the "standard" set of headers.
171      *
172      * @param state the {@link HttpState state} information associated with this method
173      * @param conn the {@link HttpConnection connection} used to execute
174      *        this HTTP method
175      *
176      * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
177      *                     can be recovered from.
178      * @throws HttpException  if a protocol exception occurs. Usually protocol exceptions 
179      *                    cannot be recovered from.
180      */
181     protected void addRequestHeaders(HttpState state, HttpConnection conn)
182     throws IOException, HttpException {
183         LOG.trace("enter ExpectContinueMethod.addRequestHeaders(HttpState, HttpConnection)");
184         
185         super.addRequestHeaders(state, conn);
186         // If the request is being retried, the header may already be present
187         boolean headerPresent = (getRequestHeader("Expect") != null);
188         // See if the expect header should be sent
189         // = HTTP/1.1 or higher
190         // = request body present
191 
192         if (getParams().isParameterTrue(HttpMethodParams.USE_EXPECT_CONTINUE) 
193         && getEffectiveVersion().greaterEquals(HttpVersion.HTTP_1_1) 
194         && hasRequestContent())
195         {
196             if (!headerPresent) {
197                 setRequestHeader("Expect", "100-continue");
198             }
199         } else {
200             if (headerPresent) {
201                 removeRequestHeader("Expect");
202             }
203         }
204     }
205 }