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 package org.apache.commons.httpclient;
30
31 import java.io.IOException;
32 import java.io.InputStream;
33
34 import junit.framework.Test;
35 import junit.framework.TestCase;
36 import junit.framework.TestSuite;
37
38 import org.apache.commons.httpclient.methods.GetMethod;
39 import org.apache.commons.httpclient.server.HttpRequestHandler;
40 import org.apache.commons.httpclient.server.RequestLine;
41 import org.apache.commons.httpclient.server.ResponseWriter;
42 import org.apache.commons.httpclient.server.SimpleHttpServer;
43 import org.apache.commons.httpclient.server.SimpleHttpServerConnection;
44 import org.apache.commons.httpclient.server.SimpleRequest;
45
46 /***
47 * Tests HttpClient's behaviour when receiving more response data than expected.
48 * <p>
49 * A very simple HTTP Server will be setup on a free port during testing, which
50 * returns an incorrect response Content-Length, sending surplus response data,
51 * which may contain malicious/fake response headers.
52 * </p>
53 *
54 * @author Christian Kohlschuetter
55 * @version $Id: TestBadContentLength.java 480424 2006-11-29 05:56:49Z bayard $
56 */
57 public class TestBadContentLength extends TestCase {
58 private HttpClient client = null;
59 private SimpleHttpServer server = null;
60
61
62 public TestBadContentLength(String testName) {
63 super(testName);
64 }
65
66
67 public static void main(String args[]) {
68 String[] testCaseName = { TestBadContentLength.class.getName()};
69 junit.textui.TestRunner.main(testCaseName);
70 }
71
72
73
74 public static Test suite() {
75 return new TestSuite(TestBadContentLength.class);
76 }
77
78
79
80 public void setUp() throws IOException {
81 client = new HttpClient();
82 server = new SimpleHttpServer();
83 server.setTestname(getName());
84 server.setRequestHandler(new MyHttpRequestHandler());
85 }
86
87 public void tearDown() throws IOException {
88 client = null;
89
90 server.destroy();
91 }
92
93 /***
94 * HttpClient connects to the test server and performs two subsequent
95 * requests to the same URI in <u>lenient</u> mode.
96 *
97 * Expected behavior:
98 * For both requests, status code 200 and a response body of "12345"
99 * should be returned.
100 *
101 * @throws IOException
102 */
103 public void test1Lenient() throws IOException {
104 client.getParams().makeLenient();
105
106 GetMethod m =
107 new GetMethod("http://localhost:" + server.getLocalPort() + "/");
108
109 client.executeMethod(m);
110 assertEquals(200, m.getStatusCode());
111 assertEquals("12345", m.getResponseBodyAsString());
112
113 m = new GetMethod("http://localhost:" + server.getLocalPort() + "/");
114
115 client.executeMethod(m);
116 assertEquals(200, m.getStatusCode());
117 assertEquals("12345", m.getResponseBodyAsString());
118 m.releaseConnection();
119 }
120
121 /***
122 * HttpClient connects to the test server and performs two subsequent
123 * requests to the same URI in <u>strict</u> mode.
124 * <p>
125 * The first response body will be read with getResponseBodyAsString(),
126 * which returns null if an error occured.
127 * </p>
128 * <p>
129 * The second response body will be read using an InputStream, which
130 * throws an IOException if something went wrong.
131 * </p>
132 * Expected behavior:
133 * For both requests, status code 200 should be returned.<br />
134 * For request 1, a <code>null</code> response body should be returned.<br />
135 * For request 2, a {@link ProtocolException} is expected.
136 *
137 * @throws IOException
138 */
139 public void test1Strict() throws IOException {
140 client.getParams().makeStrict();
141
142 GetMethod m =
143 new GetMethod("http://localhost:" + server.getLocalPort() + "/");
144
145 client.executeMethod(m);
146 assertEquals(200, m.getStatusCode());
147 assertEquals("12345", m.getResponseBodyAsString());
148
149 m = new GetMethod("http://localhost:" + server.getLocalPort() + "/");
150
151 client.executeMethod(m);
152 assertEquals(200, m.getStatusCode());
153
154 InputStream in = m.getResponseBodyAsStream();
155 while (in.read() != -1) {
156 }
157
158 m.releaseConnection();
159 }
160
161 public void enableThisTestForDebuggingOnly()
162 throws InterruptedException {
163 while (server.isRunning()) {
164 Thread.sleep(100);
165 }
166 }
167
168 private class MyHttpRequestHandler implements HttpRequestHandler {
169 private int requestNo = 0;
170
171 public boolean processRequest(
172 final SimpleHttpServerConnection conn,
173 final SimpleRequest request) throws IOException
174 {
175 RequestLine requestLine = request.getRequestLine();
176 ResponseWriter out = conn.getWriter();
177 if ("GET".equals(requestLine.getMethod())
178 && "/".equals(requestLine.getUri())) {
179
180 requestNo++;
181
182 out.println("HTTP/1.1 200 OK");
183 out.println("Content-Type: text/html");
184 out.println("Content-Length: 5");
185 out.println("Connection: keep-alive");
186 out.println();
187 out.println("12345");
188
189
190 out.println("AND SOME MORE\r\nGARBAGE!");
191 out.println("HTTP/1.0 404 Not Found");
192 out.println("Content-Type: text/plain");
193 out.println("");
194 out.println("THIS-IS-A-FAKE-RESPONSE!");
195
196 out.flush();
197
198 if (requestNo < 2) {
199 conn.setKeepAlive(true);
200 }
201 }
202 return true;
203 }
204 }
205
206 }