You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@locus.apache.org on 2000/07/03 06:45:41 UTC

cvs commit: jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http HttpRequestStream.java LocalStrings.properties

remm        00/07/02 21:45:40

  Modified:    proposals/catalina/src/share/org/apache/tomcat/connector/http
                        HttpRequestStream.java LocalStrings.properties
  Log:
  - Added support for chunked request entity bodies. The connector
    now support almost all the HTTP/1.1 fancy features. The only one
    missing is the trailing headers, but there is no way for a servlet to
    access them anyway.
  
  Revision  Changes    Path
  1.2       +211 -5    jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/HttpRequestStream.java
  
  Index: HttpRequestStream.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/HttpRequestStream.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- HttpRequestStream.java	2000/05/22 04:57:25	1.1
  +++ HttpRequestStream.java	2000/07/03 04:45:37	1.2
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/HttpRequestStream.java,v 1.1 2000/05/22 04:57:25 remm Exp $
  - * $Revision: 1.1 $
  - * $Date: 2000/05/22 04:57:25 $
  + * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/HttpRequestStream.java,v 1.2 2000/07/03 04:45:37 remm Exp $
  + * $Revision: 1.2 $
  + * $Date: 2000/07/03 04:45:37 $
    *
    * ====================================================================
    * 
  @@ -64,6 +64,7 @@
   
   package org.apache.tomcat.connector.http;
   
  +import java.io.IOException;
   import org.apache.tomcat.Request;
   import org.apache.tomcat.connector.RequestStream;
   
  @@ -83,11 +84,216 @@
        *
        * @param request The associated request
        */
  -    public HttpRequestStream(Request request) {
  +    public HttpRequestStream(HttpRequestImpl request) {
   
   	super(request);
  -
  +        String transferEncoding = request.getHeader("Transfer-Encoding");
  +        
  +        if ((transferEncoding != null) 
  +            && (transferEncoding.indexOf("chunked") != -1)) {
  +            chunk = true;
  +        }
  +        
       }
  +    
  +    
  +    // ----------------------------------------------------- Instance Variables
  +    
  +    
  +    /**
  +     * Use chunking ?
  +     */
  +    protected boolean chunk = false;
  +    
  +    
  +    /**
  +     * True if the final chunk was found.
  +     */
  +    protected boolean endChunk = false;
  +    
  +    
  +    /**
  +     * Chunk buffer.
  +     */
  +    protected byte[] chunkBuffer = null;
  +    
  +    
  +    /**
  +     * Chunk length.
  +     */
  +    protected int chunkLength = 0;
  +    
  +    
  +    /**
  +     * Chunk buffer position.
  +     */
  +    protected int chunkPos = 0;
  +    
  +    
  +    // --------------------------------------------------------- Public Methods
  +    
  +    
  +    /**
  +     * Close this input stream.  No physical level I-O is performed, but
  +     * any further attempt to read from this stream will throw an IOException.
  +     * If a content length has been set but not all of the bytes have yet been
  +     * consumed, the remaining bytes will be swallowed.
  +     */
  +    public void close()
  +        throws IOException {
  +        
  +	if (closed)
  +	    throw new IOException(sm.getString("requestStream.close.closed"));
  +        
  +        if (chunk) {
  +            
  +            while (!endChunk) {
  +                int b = read();
  +                if (b < 0)
  +                    break;
  +            }
  +            
  +        } else {
  +            
  +            if (length > 0) {
  +                while (count < length) {
  +                    int b = read();
  +                    if (b < 0)
  +                        break;
  +                }
  +            }
  +            
  +        }
  +        
  +	closed = true;
  +        
  +    }
  +    
  +    
  +    /**
  +     * Read and return a single byte from this input stream, or -1 if end of
  +     * file has been encountered.
  +     *
  +     * @exception IOException if an input/output error occurs
  +     */
  +    public int read()
  +        throws IOException {
  +        
  +        // Has this stream been closed?
  +        if (closed)
  +            throw new IOException(sm.getString("requestStream.read.closed"));
  +        
  +        if (endChunk)
  +            return (-1);
  +        
  +        if (chunk) {
  +            
  +            if ((chunkBuffer == null)
  +                || (chunkPos == chunkLength)) {
  +                
  +                chunkPos = 0;
  +                
  +                try {
  +                    chunkLength = Integer.parseInt(readLine(), 16);
  +                } catch (NumberFormatException e) {
  +                    // Critical error, unable to parse the chunk length
  +                    chunkLength = 0;
  +                    chunk = false;
  +                    close();
  +                    return -1;
  +                }
  +                
  +                if (chunkLength == 0) {
  +                    
  +                    // TODO : Parse the trailing headers, if any
  +                    readLine();
  +                    endChunk = true;
  +                    return (-1);
  +                    // TODO : Should the stream be automatically closed ?
  +                    
  +                } else {
  +                    
  +                    if ((chunkBuffer == null)
  +                        || (chunkLength > chunkBuffer.length))
  +                        chunkBuffer = new byte[chunkLength];
  +                    
  +                    // Now read the whole chunk into the buffer
  +                    
  +                    int nbRead = 0;
  +                    int currentRead = 0;
  +                    
  +                    while (nbRead < chunkLength) {
  +                        currentRead = 
  +                            stream.read(chunkBuffer, nbRead, 
  +                                        chunkLength - nbRead);
  +                        if (currentRead == -1)
  +                            throw new IOException
  +                                (sm.getString("requestStream.read.error"));
  +                        nbRead += currentRead;
  +                    }
  +                    
  +                    // Skipping the CRLF
  +                    stream.read();
  +                    stream.read();
  +                    
  +                }
  +                
  +            }
  +            
  +            return (chunkBuffer[chunkPos++]);
  +            
  +        } else {
  +            
  +            // Have we read the specified content length already?
  +            if ((length >= 0) && (count >= length))
  +                return (-1);	// End of file indicator
  +            
  +            // Read and count the next byte, then return it
  +            int b = stream.read();
  +            if (b >= 0)
  +                count++;
  +            return (b);
  +            
  +        }
  +        
  +    }
  +
  +
  +    // -------------------------------------------------------- Private Methods
  +    
   
  +    /**
  +     * Reads the input stream, one line at a time. Reads bytes into an array, 
  +     * until it reads a certain number of bytes or reaches a newline character,
  +     * which it reads into the array as well.
  +     * 
  +     * @param input Input stream on which the bytes are read
  +     * @return The line that was read, or <code>null</code> if end-of-file
  +     *  was encountered
  +     * @exception IOException	if an input or output exception has occurred
  +     */
  +    private String readLine() 
  +        throws IOException {
  +        
  +	StringBuffer sb = new StringBuffer();
  +	while (true) {
  +	    int ch = stream.read();
  +	    if (ch < 0) {
  +		if (sb.length() == 0) {
  +		    return (null);
  +		} else {
  +		    break;
  +		}
  +	    } else if (ch == '\r') {
  +		continue;
  +	    } else if (ch == '\n') {
  +		break;
  +	    }
  +	    sb.append((char) ch);
  +	}
  +	return (sb.toString());
  +        
  +    }
  +    
       
   }
  
  
  
  1.8       +3 -0      jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/LocalStrings.properties
  
  Index: LocalStrings.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/connector/http/LocalStrings.properties,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- LocalStrings.properties	2000/07/02 18:07:03	1.7
  +++ LocalStrings.properties	2000/07/03 04:45:37	1.8
  @@ -20,3 +20,6 @@
   httpProcessor.start=HTTP processor has already been started
   httpProcessor.starting=Starting background thread
   httpProcessor.stopping=Stopping background thread
  +requestStream.close.closed=Request stream has already been closed
  +requestStream.read.closed=Unable to read from a closed stream
  +requestStream.read.error=Unexpected end of stream
  \ No newline at end of file