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 package org.apache.commons.httpclient;
28
29 import java.io.IOException;
30
31 import junit.framework.*;
32 import org.apache.commons.httpclient.methods.*;
33 import org.apache.commons.httpclient.params.HttpMethodParams;
34 import org.apache.commons.httpclient.server.HttpRequestHandler;
35 import org.apache.commons.httpclient.server.ResponseWriter;
36 import org.apache.commons.httpclient.server.SimpleHttpServerConnection;
37 import org.apache.commons.httpclient.server.SimpleRequest;
38
39 /***
40 * Tests handling of non-compliant responses.
41 *
42 * @author Oleg Kalnichevski
43 * @author Jeff Dever
44 */
45 public class TestNoncompliant extends HttpClientTestBase {
46
47 public TestNoncompliant(String s) throws IOException {
48 super(s);
49 }
50
51 public static Test suite() {
52 TestSuite suite = new TestSuite(TestNoncompliant.class);
53 return suite;
54 }
55
56 /***
57 * Tests if client is able to recover gracefully when HTTP server or
58 * proxy fails to send 100 status code when expected. The client should
59 * resume sending the request body after a defined timeout without having
60 * received "continue" code.
61 */
62 public void testNoncompliantPostMethodString() throws Exception {
63 this.server.setRequestHandler(new HttpRequestHandler() {
64 public boolean processRequest(SimpleHttpServerConnection conn,
65 SimpleRequest request) throws IOException {
66 ResponseWriter out = conn.getWriter();
67 out.println("HTTP/1.1 200 OK");
68 out.println("Connection: close");
69 out.println("Content-Length: 0");
70 out.println();
71 out.flush();
72 return true;
73 }
74 });
75
76 PostMethod method = new PostMethod("/");
77 method.getParams().setBooleanParameter(
78 HttpMethodParams.USE_EXPECT_CONTINUE, true);
79 method.setRequestEntity(new StringRequestEntity(
80 "This is data to be sent in the body of an HTTP POST."));
81 client.executeMethod(method);
82 assertEquals(200, method.getStatusCode());
83 }
84
85 /***
86 * Tests that a response status line containing \r and \n is handled.
87 */
88 public void testNoncompliantStatusLine() {
89 this.server.setRequestHandler(new HttpRequestHandler() {
90 public boolean processRequest(SimpleHttpServerConnection conn,
91 SimpleRequest request) throws IOException {
92 ResponseWriter out = conn.getWriter();
93 out.println("HTTP/1.1 444 This status message contains\n"
94 + " a newline and a\r"
95 + " carrage return but that should be OK.");
96 out.println("Connection: close");
97 out.println("Content-Length: 0");
98 out.println();
99 out.flush();
100 return true;
101 }
102 });
103 GetMethod method = new GetMethod("/");
104 try {
105 client.executeMethod(method);
106 } catch (Exception e) {
107 e.printStackTrace();
108 fail("Unexpected exception: " + e.toString());
109 }
110 assertEquals(444, method.getStatusCode());
111 }
112
113 /***
114 * Test if a response to HEAD method from non-compliant server that contains
115 * an unexpected body content can be correctly redirected
116 */
117 public void testNoncompliantHeadWithResponseBody() throws Exception {
118 final String body = "Test body";
119 this.server.setRequestHandler(new HttpRequestHandler() {
120 public boolean processRequest(SimpleHttpServerConnection conn,
121 SimpleRequest request) throws IOException {
122 ResponseWriter out = conn.getWriter();
123 out.println("HTTP/1.1 200 OK");
124 out.println("Connection: close");
125 out.println("Content-Length: " + body.length());
126 out.println();
127 out.print(body);
128 out.flush();
129 return true;
130 }
131 });
132 HeadMethod method = new HeadMethod("/");
133 method.getParams().setIntParameter(
134 HttpMethodParams.HEAD_BODY_CHECK_TIMEOUT, 50);
135 client.executeMethod(method);
136 assertEquals(200, method.getStatusCode());
137 method.releaseConnection();
138 }
139
140 /***
141 * Test if a response to HEAD method from non-compliant server causes an
142 * HttpException to be thrown
143 */
144 public void testNoncompliantHeadStrictMode() throws Exception {
145 final String body = "Test body";
146 this.server.setRequestHandler(new HttpRequestHandler() {
147 public boolean processRequest(SimpleHttpServerConnection conn,
148 SimpleRequest request) throws IOException {
149 ResponseWriter out = conn.getWriter();
150 out.println("HTTP/1.1 200 OK");
151 out.println("Connection: close");
152 out.println("Content-Length: " + body.length());
153 out.println();
154 out.print(body);
155 out.flush();
156 return true;
157 }
158 });
159 client.getParams().setBooleanParameter(
160 HttpMethodParams.REJECT_HEAD_BODY, true);
161 HeadMethod method = new NoncompliantHeadMethod("/");
162 method.getParams().setIntParameter(
163 HttpMethodParams.HEAD_BODY_CHECK_TIMEOUT, 50);
164 try {
165 client.executeMethod(method);
166 fail("HttpException should have been thrown");
167 } catch (HttpException e) {
168
169 }
170 method.releaseConnection();
171 }
172
173 /***
174 * Tests if client is able to handle gracefully malformed responses
175 * that may not include response body.
176 */
177 public void testMalformed304Response() throws Exception {
178 this.server.setRequestHandler(new HttpRequestHandler() {
179 public boolean processRequest(SimpleHttpServerConnection conn,
180 SimpleRequest request) throws IOException {
181 conn.setSocketTimeout(20000);
182 ResponseWriter out = conn.getWriter();
183 out.println("HTTP/1.1 304 OK");
184 out.println("Connection: keep-alive");
185 out.println("Content-Length: 100");
186 out.println();
187 out.flush();
188 conn.setKeepAlive(true);
189 return true;
190 }
191 });
192
193 GetMethod method = new GetMethod("/");
194 method.getParams().setSoTimeout(1000);
195 client.executeMethod(method);
196 assertEquals(HttpStatus.SC_NOT_MODIFIED, method.getStatusCode());
197 method.getResponseBody();
198 }
199
200 public void testMalformed204Response() throws Exception {
201 this.server.setRequestHandler(new HttpRequestHandler() {
202 public boolean processRequest(SimpleHttpServerConnection conn,
203 SimpleRequest request) throws IOException {
204 conn.setSocketTimeout(20000);
205 ResponseWriter out = conn.getWriter();
206 out.println("HTTP/1.1 204 OK");
207 out.println("Connection: close");
208 out.println("Content-Length: 100");
209 out.println();
210 out.flush();
211 conn.setKeepAlive(true);
212 return true;
213 }
214 });
215
216 GetMethod method = new GetMethod("/");
217 method.getParams().setSoTimeout(1000);
218 client.executeMethod(method);
219 assertEquals(HttpStatus.SC_NO_CONTENT, method.getStatusCode());
220 method.getResponseBody();
221 }
222
223 }