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 &lt;[EMAIL PROTECTED]&gt;
    */
   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]>

Reply via email to