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.methods;
31
32 import java.io.IOException;
33 import org.apache.commons.httpclient.HttpConnection;
34 import org.apache.commons.httpclient.HttpException;
35 import org.apache.commons.httpclient.HttpMethodBase;
36 import org.apache.commons.httpclient.HttpState;
37 import org.apache.commons.httpclient.HttpVersion;
38 import org.apache.commons.httpclient.params.HttpMethodParams;
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41
42 /***
43 * <p>
44 * This abstract class serves as a foundation for all HTTP methods
45 * that support 'Expect: 100-continue' handshake.
46 * </p>
47 *
48 * <p>
49 * The purpose of the 100 (Continue) status (refer to section 10.1.1
50 * of the RFC 2616 for more details) is to allow a client that is
51 * sending a request message with a request body to determine if the
52 * origin server is willing to accept the request (based on the request
53 * headers) before the client sends the request body. In some cases,
54 * it might either be inappropriate or highly inefficient for the
55 * client to send the body if the server will reject the message
56 * without looking at the body.
57 * </p>
58 *
59 * <p>
60 * 'Expect: 100-continue' handshake should be used with caution,
61 * as it may cause problems with HTTP servers and proxies that
62 * do not support HTTP/1.1 protocol.
63 * </p>
64 *
65 * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
66 *
67 * @since 2.0beta1
68 */
69
70 public abstract class ExpectContinueMethod extends HttpMethodBase {
71
72 /*** LOG object for this class. */
73 private static final Log LOG = LogFactory.getLog(ExpectContinueMethod.class);
74
75 /***
76 * No-arg constructor.
77 *
78 * @since 2.0
79 */
80 public ExpectContinueMethod() {
81 super();
82 }
83
84 /***
85 * Constructor specifying a URI.
86 *
87 * @param uri either an absolute or relative URI
88 *
89 * @since 2.0
90 */
91 public ExpectContinueMethod(String uri) {
92 super(uri);
93 }
94
95 /***
96 * <p>
97 * Returns <tt>true</tt> if the 'Expect: 100-Continue' handshake
98 * is activated. The purpose of the 'Expect: 100-Continue'
99 * handshake to allow a client that is sending a request message
100 * with a request body to determine if the origin server is
101 * willing to accept the request (based on the request headers)
102 * before the client sends the request body.
103 * </p>
104 *
105 * @return <tt>true</tt> if 'Expect: 100-Continue' handshake is to
106 * be used, <tt>false</tt> otherwise.
107 *
108 * @since 2.0beta1
109 *
110 * @deprecated Use {@link HttpMethodParams}
111 *
112 * @see #getParams()
113 * @see HttpMethodParams
114 * @see HttpMethodParams#USE_EXPECT_CONTINUE
115 */
116 public boolean getUseExpectHeader() {
117 return getParams().getBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, false);
118 }
119
120 /***
121 * <p>
122 * Activates 'Expect: 100-Continue' handshake. The purpose of
123 * the 'Expect: 100-Continue' handshake to allow a client that is
124 * sending a request message with a request body to determine if
125 * the origin server is willing to accept the request (based on
126 * the request headers) before the client sends the request body.
127 * </p>
128 *
129 * <p>
130 * The use of the 'Expect: 100-continue' handshake can result in
131 * noticable peformance improvement for entity enclosing requests
132 * (such as POST and PUT) that require the target server's
133 * authentication.
134 * </p>
135 *
136 * <p>
137 * 'Expect: 100-continue' handshake should be used with
138 * caution, as it may cause problems with HTTP servers and
139 * proxies that do not support HTTP/1.1 protocol.
140 * </p>
141 *
142 * @param value boolean value
143 *
144 * @since 2.0beta1
145 *
146 * @deprecated Use {@link HttpMethodParams}
147 *
148 * @see #getParams()
149 * @see HttpMethodParams
150 * @see HttpMethodParams#USE_EXPECT_CONTINUE
151 */
152 public void setUseExpectHeader(boolean value) {
153 getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, value);
154 }
155
156 /***
157 * Returns <tt>true</tt> if there is a request body to be sent.
158 * 'Expect: 100-continue' handshake may not be used if request
159 * body is not present
160 *
161 * @return boolean
162 *
163 * @since 2.0beta1
164 */
165 protected abstract boolean hasRequestContent();
166
167 /***
168 * Sets the <tt>Expect</tt> header if it has not already been set,
169 * in addition to the "standard" set of headers.
170 *
171 * @param state the {@link HttpState state} information associated with this method
172 * @param conn the {@link HttpConnection connection} used to execute
173 * this HTTP method
174 *
175 * @throws IOException if an I/O (transport) error occurs. Some transport exceptions
176 * can be recovered from.
177 * @throws HttpException if a protocol exception occurs. Usually protocol exceptions
178 * cannot be recovered from.
179 */
180 protected void addRequestHeaders(HttpState state, HttpConnection conn)
181 throws IOException, HttpException {
182 LOG.trace("enter ExpectContinueMethod.addRequestHeaders(HttpState, HttpConnection)");
183
184 super.addRequestHeaders(state, conn);
185
186 boolean headerPresent = (getRequestHeader("Expect") != null);
187
188
189
190
191 if (getParams().isParameterTrue(HttpMethodParams.USE_EXPECT_CONTINUE)
192 && getEffectiveVersion().greaterEquals(HttpVersion.HTTP_1_1)
193 && hasRequestContent())
194 {
195 if (!headerPresent) {
196 setRequestHeader("Expect", "100-continue");
197 }
198 } else {
199 if (headerPresent) {
200 removeRequestHeader("Expect");
201 }
202 }
203 }
204 }