snichol 2002/10/15 20:58:11
Modified: java/docs changes.html
java/src/org/apache/soap/util/net HTTPUtils.java
Log:
Submitted by Pavel Ausianik ([EMAIL PROTECTED]):
Add client support for HTTP redirects.
Revision Changes Path
1.49 +1 -0 xml-soap/java/docs/changes.html
Index: changes.html
===================================================================
RCS file: /home/cvs/xml-soap/java/docs/changes.html,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -r1.48 -r1.49
--- changes.html 11 Oct 2002 18:41:41 -0000 1.48
+++ changes.html 16 Oct 2002 03:58:11 -0000 1.49
@@ -93,6 +93,7 @@
<li>Support messaging in the Stateless EJB and CORBA provieders. Throw an
exception for messaging calls in the Stateful EJB and Entity EJB providers
rather than throwing a NPE.</li>
+ <li>Add client support for HTTP redirects.</li>
</ul>
</li>
</ul>
1.33 +80 -28 xml-soap/java/src/org/apache/soap/util/net/HTTPUtils.java
Index: HTTPUtils.java
===================================================================
RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/util/net/HTTPUtils.java,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- HTTPUtils.java 4 Oct 2002 19:50:19 -0000 1.32
+++ HTTPUtils.java 16 Oct 2002 03:58:11 -0000 1.33
@@ -85,6 +85,7 @@
* @author Arek Wnukowski ([EMAIL PROTECTED])
* @author Doug Davis ([EMAIL PROTECTED]) (code lifted from Axis)
* @author Davanum Srinivas ([EMAIL PROTECTED]) (code lifted from Axis)
+ * @author Pavel Ausianik <[EMAIL PROTECTED]>
*/
public class HTTPUtils {
private static final String HTTP_VERSION = "1.0";
@@ -203,7 +204,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 +318,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 +355,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 +465,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 +514,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 +549,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 +616,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]>