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