Hello,
I created a patch, which allows HTTPUtils follow redirects, with simple
check that this occurs no more than 5 times. Since it uses recurrent call,
I had to add additional parameter to the function post (interfaces do not
changed, old function exists).
Also I removed StringBuffer creation, while parsing headers, creating
header/value directly from byte[].
I did small testing with IIS & one java app server.
Please review
Pavel
Index: HTTPUtils.java
===================================================================
RCS file: /home/cvspublic/xml-soap/java/src/org/apache/soap/util/net/HTTPUtils.java,v
retrieving revision 1.32
diff -u -r1.32 HTTPUtils.java
--- HTTPUtils.java 4 Oct 2002 19:50:19 -0000 1.32
+++ HTTPUtils.java 14 Oct 2002 13:25:54 -0000
@@ -203,7 +203,7 @@
msg.append(": ").append(e.toString());
throw new SOAPException(Constants.FAULT_CODE_CLIENT, msg.toString(), e);
}
-
+
if (s != null && tcpNoDelay != null)
s.setTcpNoDelay(tcpNoDelay.booleanValue());
@@ -317,9 +317,9 @@
int outputBufferSize,
Boolean tcpNoDelay)
throws IOException, SOAPException {
-
+
return post(url, request, timeout, httpProxyHost, httpProxyPort,
- outputBufferSize, tcpNoDelay, null, null);
+ outputBufferSize, tcpNoDelay, null, null, 0);
}
/**
@@ -354,8 +354,47 @@
Boolean tcpNoDelay,
StringBuffer requestCopy,
StringBuffer responseCopy)
- throws IOException, SOAPException {
+ throws IOException, SOAPException {
+ return post(url, request, timeout, httpProxyHost, httpProxyPort,
+ outputBufferSize, tcpNoDelay, null, null, 0);
+ }
+ /**
+ * POST something to the given URL. The headers are put in as
+ * HTTP headers, the content length is calculated and the content
+ * byte array is sent as the POST content.
+ *
+ * This method allows the caller to provide buffers in which to capture
+ * request and response data. This is useful when debugging SSL, as
+ * wire dumps are not very useful in that case. However, it is important
+ * to note that the bytes send or received are optimistically handled
+ * with the default encoding, much as TcpTunnelGui treats everything
+ * as iso-8859-1.
+ *
+ * @param url the url to post to
+ * @param request the message
+ * @param timeout the amount of time, in ms, to block on reading data
+ * @param httpProxyHost the HTTP proxy host or null if no proxy
+ * @param httpProxyPort the HTTP proxy port, if the proxy host is not null
+ * @param outputBufferSize the size of the output buffer on the HTTP stream
+ * @param tcpNoDelay the tcpNoDelay setting for the socket
+ * @param requestCopy the buffer for capturing copy of the request or null
+ * if capture is not required.
+ * @param responseCopy the buffer for capturing copy of the response or null
+ * if capture is not required.
+ * @param numRedirects the current number of redirects - to prevent cycles
+ * @return the response message
+ */
+ private static TransportMessage post(URL url, TransportMessage request,
+ int timeout,
+ String httpProxyHost, int httpProxyPort,
+ int outputBufferSize,
+ Boolean tcpNoDelay,
+ StringBuffer requestCopy,
+ StringBuffer responseCopy,
+ int numRedirects)
+
+ throws IOException, SOAPException {
OutputStream outStream = null;
InputStream inStream = null;
BufferedReader in = null;
@@ -425,17 +464,14 @@
bOutStream.write(
headerbuf.toString().getBytes(Constants.HEADERVAL_DEFAULT_CHARSET));
request.writeTo(bOutStream);
-
+
/* If required, capture a copy of the request. */
if (requestCopy != null) {
requestCopy.append(headerbuf)
.append(new String(request.getBytes())); /* Note: could get junk
depending on actual encoding */
}
-
- //bOutStream.write('\r'); bOutStream.write('\n');
- //bOutStream.write('\r'); bOutStream.write('\n');
+
bOutStream.flush();
- outStream.flush();
BufferedInputStream bInStream = new BufferedInputStream(inStream);
/* Read the response status line. */
@@ -477,24 +513,26 @@
Hashtable respHeaders = new Hashtable();
int respContentLength = -1;
String respContentType = null;
- StringBuffer namebuf = new StringBuffer(64);
- StringBuffer valuebuf = new StringBuffer(64);
+
+ int nameStart = 0;
+ int nameEnd = 0;
+ int valStart = 0;
boolean parsingName = true;
int offset;
+
for (offset = 0; offset < bytes.length; offset++) {
if (bytes[offset] == '\n') {
- if (namebuf.length() == 0)
+ if (nameStart >= nameEnd)
break;
- String name = namebuf.toString();
+ String name = new String(bytes, nameStart, nameEnd-nameStart+1);
// Remove trailing ; to prevent ContextType from throwing exception
- int valueLen = valuebuf.length();
+ int valueLen = offset - valStart -1;
- if (valueLen > 0 && valuebuf.charAt(valueLen - 1) == ';') {
- valuebuf.deleteCharAt(valueLen - 1);
- }
+ if (valueLen > 0 && bytes[offset-1] == ';')
+ valueLen--;
- String value = valuebuf.toString();
+ String value = new String(bytes, valStart, valueLen);
if (name.equalsIgnoreCase(Constants.HEADER_CONTENT_LENGTH))
respContentLength = Integer.parseInt(value);
else if (name.equalsIgnoreCase(Constants.HEADER_CONTENT_TYPE))
@@ -510,35 +548,50 @@
}
}
}
- namebuf = new StringBuffer(64);
- valuebuf = new StringBuffer(64);
parsingName = true;
+ nameStart = offset+1;
}
else if (bytes[offset] != '\r') {
if (parsingName) {
if (bytes[offset] == ':') {
parsingName = false;
+ nameEnd = offset - 1;
if ((offset != bytes.length-1) &&
bytes[offset+1] == ' ')
offset++;
+ valStart = offset+1;
}
- else
- namebuf.append((char)bytes[offset]);
}
- else
- valuebuf.append((char)bytes[offset]);
}
- }
+ } // End of for
+
InputStream is = ds.getInputStream();
is.skip(offset + 1);
if (respContentLength < 0)
respContentLength = ds.getSize() - offset - 1;
+ /* Handle redirect here */
+ if (statusCode >= HttpURLConnection.HTTP_MULT_CHOICE &&
+ statusCode <= HttpURLConnection.HTTP_USE_PROXY &&
+ statusCode != HttpURLConnection.HTTP_NOT_MODIFIED && (++numRedirects)<5 ) {
+ String newLocation = getHeaderValue(respHeaders, "Location");
+ if (newLocation != null) {
+ URL newURL = new URL(url, newLocation);
+ /* Close current streams */
+ bOutStream.close();
+ bInStream.close();
+ s.close();
+ // Post to new location
+ return post(newURL, request, timeout, httpProxyHost, httpProxyPort,
+ outputBufferSize, tcpNoDelay, null, responseCopy, numRedirects);
+ }
+ }
+
/* If required, capture a copy of the response. */
if (responseCopy != null) {
responseCopy.append(line).append("\r\n").append(new String(bytes)); /* May
get junk due to actual encoding */
}
-
+
// TODO: process differently depending on statusCode and respContentLength
// (TransportMessage does not even get statusCode)
// e.g. statusCode 401 is Unauthorized
@@ -562,9 +615,7 @@
/* All done here! */
bOutStream.close();
- outStream.close();
bInStream.close();
- inStream.close();
s.close();
return response;
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>