Lines 39-45
Link Here
|
39 |
*/ |
39 |
*/ |
40 |
public abstract class SimpleHttpClient { |
40 |
public abstract class SimpleHttpClient { |
41 |
public static final String TEMP_DIR = |
41 |
public static final String TEMP_DIR = |
42 |
System.getProperty("java.io.tmpdir"); |
42 |
System.getProperty("java.io.tmpdir"); |
43 |
|
43 |
|
44 |
public static final String CRLF = "\r\n"; |
44 |
public static final String CRLF = "\r\n"; |
45 |
|
45 |
|
Lines 48-61
Link Here
|
48 |
public static final String REDIRECT_302 = "HTTP/1.1 302"; |
48 |
public static final String REDIRECT_302 = "HTTP/1.1 302"; |
49 |
public static final String FAIL_400 = "HTTP/1.1 400"; |
49 |
public static final String FAIL_400 = "HTTP/1.1 400"; |
50 |
public static final String FAIL_404 = "HTTP/1.1 404"; |
50 |
public static final String FAIL_404 = "HTTP/1.1 404"; |
|
|
51 |
public static final String TIMEOUT_408 = "HTTP/1.1 408"; |
51 |
public static final String FAIL_413 = "HTTP/1.1 413"; |
52 |
public static final String FAIL_413 = "HTTP/1.1 413"; |
52 |
public static final String FAIL_50X = "HTTP/1.1 50"; |
53 |
public static final String FAIL_50X = "HTTP/1.1 50"; |
53 |
public static final String FAIL_500 = "HTTP/1.1 500"; |
54 |
public static final String FAIL_500 = "HTTP/1.1 500"; |
54 |
public static final String FAIL_501 = "HTTP/1.1 501"; |
55 |
public static final String FAIL_501 = "HTTP/1.1 501"; |
55 |
|
56 |
|
|
|
57 |
private static final String CONTENT_LENGTH_HEADER_PREFIX = |
58 |
"Content-Length: "; |
59 |
|
60 |
protected static final String SESSION_COOKIE_NAME = "JSESSIONID"; |
61 |
protected static final String SESSION_PARAMETER_NAME = |
62 |
SESSION_COOKIE_NAME.toLowerCase(); |
63 |
|
64 |
private static final String COOKIE_HEADER_PREFIX = "Set-Cookie: "; |
56 |
private static final String SESSION_COOKIE_HEADER_PREFIX = |
65 |
private static final String SESSION_COOKIE_HEADER_PREFIX = |
57 |
"Set-Cookie: JSESSIONID="; |
66 |
COOKIE_HEADER_PREFIX + SESSION_COOKIE_NAME + "="; |
58 |
|
67 |
|
|
|
68 |
private static final String REDIRECT_HEADER_PREFIX = "Location: "; |
69 |
protected static final String SESSION_PATH_PARAMETER_PREFIX = |
70 |
SESSION_PARAMETER_NAME + "="; |
71 |
protected static final String SESSION_PATH_PARAMETER_TAILS = CRLF + ";?"; |
72 |
|
73 |
private static final String ELEMENT_HEAD = "<"; |
74 |
private static final String ELEMENT_TAIL = ">"; |
75 |
private static final String RESOURCE_TAG = "a"; |
76 |
private static final String LOGIN_TAG = "form"; |
77 |
|
59 |
private Socket socket; |
78 |
private Socket socket; |
60 |
private Writer writer; |
79 |
private Writer writer; |
61 |
private BufferedReader reader; |
80 |
private BufferedReader reader; |
Lines 63-75
Link Here
|
63 |
|
82 |
|
64 |
private String[] request; |
83 |
private String[] request; |
65 |
private boolean useContinue = false; |
84 |
private boolean useContinue = false; |
|
|
85 |
private boolean useCookies = true; |
66 |
private int requestPause = 1000; |
86 |
private int requestPause = 1000; |
67 |
|
87 |
|
68 |
private String responseLine; |
88 |
private String responseLine; |
69 |
private List<String> responseHeaders = new ArrayList<>(); |
89 |
private List<String> responseHeaders = new ArrayList<>(); |
70 |
private String responseBody; |
90 |
private String sessionId; |
71 |
private boolean useContentLength; |
91 |
private boolean useContentLength; |
|
|
92 |
private int contentLength; |
93 |
private String redirectUri; |
72 |
|
94 |
|
|
|
95 |
private String responseBody; |
96 |
private List<String> bodyUriElments = new ArrayList<>(); |
97 |
|
73 |
protected void setPort(int thePort) { |
98 |
protected void setPort(int thePort) { |
74 |
port = thePort; |
99 |
port = thePort; |
75 |
} |
100 |
} |
Lines 86-91
Link Here
|
86 |
return useContinue; |
111 |
return useContinue; |
87 |
} |
112 |
} |
88 |
|
113 |
|
|
|
114 |
public void setUseCookies(boolean theUseCookiesFlag) { |
115 |
useCookies = theUseCookiesFlag; |
116 |
} |
117 |
|
118 |
public boolean getUseCookies() { |
119 |
return useCookies; |
120 |
} |
121 |
|
89 |
public void setRequestPause(int theRequestPause) { |
122 |
public void setRequestPause(int theRequestPause) { |
90 |
requestPause = theRequestPause; |
123 |
requestPause = theRequestPause; |
91 |
} |
124 |
} |
Lines 106-123
Link Here
|
106 |
useContentLength = b; |
139 |
useContentLength = b; |
107 |
} |
140 |
} |
108 |
|
141 |
|
|
|
142 |
public void setSessionId(String theSessionId) { |
143 |
sessionId = theSessionId; |
144 |
} |
145 |
|
109 |
public String getSessionId() { |
146 |
public String getSessionId() { |
110 |
for (String header : responseHeaders) { |
147 |
return sessionId; |
111 |
if (header.startsWith(SESSION_COOKIE_HEADER_PREFIX)) { |
|
|
112 |
header = header.substring(SESSION_COOKIE_HEADER_PREFIX.length()); |
113 |
header = header.substring(0, header.indexOf(';')); |
114 |
return header; |
115 |
} |
116 |
} |
117 |
return null; |
118 |
} |
148 |
} |
119 |
|
149 |
|
120 |
public void connect(int connectTimeout, int soTimeout) throws UnknownHostException, IOException { |
150 |
public String getRedirectUri() { |
|
|
151 |
return redirectUri; |
152 |
} |
153 |
|
154 |
public void connect(int connectTimeout, int soTimeout) |
155 |
throws UnknownHostException, IOException { |
121 |
final String encoding = "ISO-8859-1"; |
156 |
final String encoding = "ISO-8859-1"; |
122 |
SocketAddress addr = new InetSocketAddress("localhost", port); |
157 |
SocketAddress addr = new InetSocketAddress("localhost", port); |
123 |
socket = new Socket(); |
158 |
socket = new Socket(); |
Lines 137-146
Link Here
|
137 |
processRequest(true); |
172 |
processRequest(true); |
138 |
} |
173 |
} |
139 |
|
174 |
|
140 |
public void processRequest(boolean readBody) throws IOException, InterruptedException { |
175 |
public void processRequest(boolean wantBody) |
|
|
176 |
throws IOException, InterruptedException { |
141 |
sendRequest(); |
177 |
sendRequest(); |
142 |
|
178 |
|
143 |
readResponse(readBody); |
179 |
readResponse(wantBody); |
144 |
|
180 |
|
145 |
} |
181 |
} |
146 |
|
182 |
|
Lines 158-170
Link Here
|
158 |
} |
194 |
} |
159 |
} |
195 |
} |
160 |
|
196 |
|
161 |
public void readResponse(boolean readBody) throws IOException { |
197 |
public void readResponse(boolean wantBody) throws IOException { |
162 |
// Reset fields use to hold response |
198 |
// clear any residual data before starting on this response |
163 |
responseLine = null; |
|
|
164 |
responseHeaders.clear(); |
199 |
responseHeaders.clear(); |
165 |
responseBody = null; |
200 |
responseBody = null; |
|
|
201 |
bodyUriElments.clear(); |
166 |
|
202 |
|
167 |
// Read the response |
203 |
// Read the response status line |
168 |
responseLine = readLine(); |
204 |
responseLine = readLine(); |
169 |
|
205 |
|
170 |
// Is a 100 continue response expected? |
206 |
// Is a 100 continue response expected? |
Lines 179-213
Link Here
|
179 |
} |
215 |
} |
180 |
} |
216 |
} |
181 |
|
217 |
|
182 |
// Put the headers into the map |
218 |
// Put the headers into a map, and process interesting ones |
|
|
219 |
processHeaders(); |
220 |
|
221 |
// Read the body, if requested and if one exists |
222 |
processBody(wantBody); |
223 |
|
224 |
if (isResponse408()) { |
225 |
// the session has timed out |
226 |
sessionId = null; |
227 |
} |
228 |
} |
229 |
|
230 |
/* |
231 |
* Accumulate the response headers into a map, and extract |
232 |
* interesting details at the same time |
233 |
*/ |
234 |
private void processHeaders() throws IOException { |
235 |
// Reset response fields |
236 |
redirectUri = null; |
237 |
contentLength = -1; |
238 |
|
183 |
String line = readLine(); |
239 |
String line = readLine(); |
184 |
int cl = -1; |
240 |
while ((line != null) && (line.length() > 0)) { |
185 |
while (line!=null && line.length() > 0) { |
|
|
186 |
responseHeaders.add(line); |
241 |
responseHeaders.add(line); |
|
|
242 |
if (line.startsWith(CONTENT_LENGTH_HEADER_PREFIX)) { |
243 |
contentLength = Integer.parseInt(line.substring(16)); |
244 |
} |
245 |
else if (line.startsWith(COOKIE_HEADER_PREFIX)) { |
246 |
if (useCookies) { |
247 |
String temp = line.substring( |
248 |
SESSION_COOKIE_HEADER_PREFIX.length()); |
249 |
temp = temp.substring(0, temp.indexOf(';')); |
250 |
setSessionId(temp); |
251 |
} |
252 |
} |
253 |
else if (line.startsWith(REDIRECT_HEADER_PREFIX)) { |
254 |
redirectUri = line.substring(REDIRECT_HEADER_PREFIX.length()); |
255 |
} |
187 |
line = readLine(); |
256 |
line = readLine(); |
188 |
if (line != null && line.startsWith("Content-Length: ")) { |
|
|
189 |
cl = Integer.parseInt(line.substring(16)); |
190 |
} |
191 |
} |
257 |
} |
|
|
258 |
} |
192 |
|
259 |
|
193 |
// Read the body, if any |
260 |
/* |
|
|
261 |
* Read the body of the server response. Save its contents and |
262 |
* search it for uri-elements only if requested |
263 |
*/ |
264 |
private void processBody(boolean wantBody) throws IOException { |
265 |
// Read the body, if one exists |
194 |
StringBuilder builder = new StringBuilder(); |
266 |
StringBuilder builder = new StringBuilder(); |
195 |
if (readBody) { |
267 |
if (wantBody) { |
196 |
if (cl > -1 && useContentLength) { |
268 |
if (useContentLength && (contentLength > -1)) { |
197 |
char[] body = new char[cl]; |
269 |
char[] body = new char[contentLength]; |
198 |
reader.read(body); |
270 |
reader.read(body); |
199 |
builder.append(body); |
271 |
builder.append(body); |
200 |
} else { |
272 |
} |
201 |
line = readLine(); |
273 |
else { |
202 |
while (line != null) { |
274 |
// not using content length, so just read it line by line |
|
|
275 |
String line = null; |
276 |
while ((line = readLine()) != null) { |
203 |
builder.append(line); |
277 |
builder.append(line); |
204 |
line = readLine(); |
|
|
205 |
} |
278 |
} |
206 |
} |
279 |
} |
207 |
} |
280 |
} |
208 |
responseBody = builder.toString(); |
281 |
responseBody = builder.toString(); |
|
|
282 |
extractUriElements(responseBody); |
209 |
} |
283 |
} |
210 |
|
284 |
|
|
|
285 |
/* |
286 |
* Scan an html body for useful html uri elements. If any are found, |
287 |
* then accumulate them. Test classes might not use them, but they |
288 |
* are collected anyway. |
289 |
*/ |
290 |
private void extractUriElements(String body) { |
291 |
if (body.length() > 0) { |
292 |
int ix = 0; |
293 |
while ((ix = extractUriElement(body, ix, RESOURCE_TAG)) > 0){} |
294 |
ix = 0; |
295 |
while ((ix = extractUriElement(body, ix, LOGIN_TAG)) > 0){} |
296 |
} |
297 |
} |
298 |
|
299 |
/* |
300 |
* Scan an html body for a given html uri element, starting from the |
301 |
* given index into the source string. If any are found, simply |
302 |
* accumulate them as literal strings, including angle brackets. |
303 |
* note: nested elements will not be collected. |
304 |
* |
305 |
* @param body HTTP body of the response |
306 |
* @param startIx offset into the body to resume the scan (for iteration) |
307 |
* @param elementName to scan for (only one at a time) |
308 |
* @returns the index into the body to continue the scan (for iteration) |
309 |
*/ |
310 |
private int extractUriElement(String body, int startIx, String elementName) { |
311 |
String detector = ELEMENT_HEAD + elementName + " "; |
312 |
int iStart = body.indexOf(detector, startIx); |
313 |
if (iStart > -1) { |
314 |
int iEnd = body.indexOf(ELEMENT_TAIL, iStart); |
315 |
if (iEnd < 0) { |
316 |
throw new IllegalArgumentException( |
317 |
"Response body check failure.\n" |
318 |
+ "element [" + detector + "] is not terminated with [" |
319 |
+ ELEMENT_TAIL + "]\nActual: [" + body + "]"); |
320 |
} |
321 |
String element = body.substring(iStart, iEnd); |
322 |
bodyUriElments.add(element); |
323 |
iStart += element.length(); |
324 |
} |
325 |
return iStart; |
326 |
} |
327 |
|
211 |
public String readLine() throws IOException { |
328 |
public String readLine() throws IOException { |
212 |
return reader.readLine(); |
329 |
return reader.readLine(); |
213 |
} |
330 |
} |
Lines 253-258
Link Here
|
253 |
return getResponseLine().startsWith(FAIL_404); |
370 |
return getResponseLine().startsWith(FAIL_404); |
254 |
} |
371 |
} |
255 |
|
372 |
|
|
|
373 |
public boolean isResponse408() { |
374 |
return getResponseLine().startsWith(TIMEOUT_408); |
375 |
} |
376 |
|
256 |
public boolean isResponse413() { |
377 |
public boolean isResponse413() { |
257 |
return getResponseLine().startsWith(FAIL_413); |
378 |
return getResponseLine().startsWith(FAIL_413); |
258 |
} |
379 |
} |