changeset 980:bd26bd9320e2

simplify HttpParser
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 16 Oct 2016 21:01:26 -0600
parents c8cd3e96db5f
children f46de416e219
files src/org/eclipse/jetty/http/HttpParser.java src/org/eclipse/jetty/server/AbstractHttpConnection.java src/org/eclipse/jetty/server/HttpInput.java
diffstat 3 files changed, 74 insertions(+), 220 deletions(-) [+]
line wrap: on
line diff
--- a/src/org/eclipse/jetty/http/HttpParser.java	Sun Oct 16 18:01:39 2016 -0600
+++ b/src/org/eclipse/jetty/http/HttpParser.java	Sun Oct 16 21:01:26 2016 -0600
@@ -37,28 +37,28 @@
 	private static final Logger LOG = LoggerFactory.getLogger(HttpParser.class);
 
 	// States
-	public static final int STATE_START=-14;
-	public static final int STATE_FIELD0=-13;
-	public static final int STATE_SPACE1=-12;
-	public static final int STATE_STATUS=-11;
-	public static final int STATE_URI=-10;
-	public static final int STATE_SPACE2=-9;
-	public static final int STATE_END0=-8;
-	public static final int STATE_END1=-7;
-	public static final int STATE_FIELD2=-6;
-	public static final int STATE_HEADER=-5;
-	public static final int STATE_HEADER_NAME=-4;
-	public static final int STATE_HEADER_IN_NAME=-3;
-	public static final int STATE_HEADER_VALUE=-2;
-	public static final int STATE_HEADER_IN_VALUE=-1;
-	public static final int STATE_END=0;
-	public static final int STATE_EOF_CONTENT=1;
-	public static final int STATE_CONTENT=2;
-	public static final int STATE_CHUNKED_CONTENT=3;
-	public static final int STATE_CHUNK_SIZE=4;
-	public static final int STATE_CHUNK_PARAMS=5;
-	public static final int STATE_CHUNK=6;
-	public static final int STATE_SEEKING_EOF=7;
+	private static final int STATE_START=-14;
+	private static final int STATE_FIELD0=-13;
+	private static final int STATE_SPACE1=-12;
+	private static final int STATE_STATUS=-11;
+	private static final int STATE_URI=-10;
+	private static final int STATE_SPACE2=-9;
+	private static final int STATE_END0=-8;
+	private static final int STATE_END1=-7;
+	private static final int STATE_FIELD2=-6;
+	private static final int STATE_HEADER=-5;
+	private static final int STATE_HEADER_NAME=-4;
+	private static final int STATE_HEADER_IN_NAME=-3;
+	private static final int STATE_HEADER_VALUE=-2;
+	private static final int STATE_HEADER_IN_VALUE=-1;
+	private static final int STATE_END=0;
+	private static final int STATE_EOF_CONTENT=1;
+	private static final int STATE_CONTENT=2;
+	private static final int STATE_CHUNKED_CONTENT=3;
+	private static final int STATE_CHUNK_SIZE=4;
+	private static final int STATE_CHUNK_PARAMS=5;
+	private static final int STATE_CHUNK=6;
+	private static final int STATE_SEEKING_EOF=7;
 
 	private final EventHandler _handler;
 	private final Buffers _buffers; // source of buffers
@@ -71,12 +71,10 @@
 	private final View.CaseInsensitive _tok1; // Saved token: header value, request URI or response code
 	private String _multiLineValue;
 	private int _responseStatus; // If >0 then we are parsing a response
-	private boolean _forceContentBuffer;
 	private boolean _persistent;
 
-	/* ------------------------------------------------------------------------------- */
-	protected final View  _contentView=new View(); // View of the content in the buffer for {@link Input}
-	protected int _state=STATE_START;
+	protected final View  _contentView = new View(); // View of the content in the buffer for {@link Input}
+	protected int _state = STATE_START;
 	protected byte _eol;
 	protected int _length;
 	protected long _contentLength;
@@ -85,45 +83,20 @@
 	protected int _chunkPosition;
 	private boolean _headResponse;
 
-	/* ------------------------------------------------------------------------------- */
-	/**
-	 * Constructor.
-	 */
-	public HttpParser(Buffer buffer, EventHandler handler)
+	public HttpParser(Buffers buffers, EndPoint endp, EventHandler handler)
 	{
-		_endp=null;
-		_buffers=null;
-		_header=buffer;
-		_buffer=buffer;
-		_handler=handler;
-
-		_tok0=new View.CaseInsensitive(_header);
-		_tok1=new View.CaseInsensitive(_header);
+		_buffers = buffers;
+		_endp = endp;
+		_handler = handler;
+		_tok0 = new View.CaseInsensitive();
+		_tok1 = new View.CaseInsensitive();
 	}
 
-	/* ------------------------------------------------------------------------------- */
-	/**
-	 * Constructor.
-	 * @param buffers the buffers to use
-	 * @param endp the endpoint
-	 * @param handler the even handler
-	 */
-	public HttpParser(Buffers buffers, EndPoint endp, EventHandler handler)
-	{
-		_buffers=buffers;
-		_endp=endp;
-		_handler=handler;
-		_tok0=new View.CaseInsensitive();
-		_tok1=new View.CaseInsensitive();
-	}
-
-	/* ------------------------------------------------------------------------------- */
 	public long getContentLength()
 	{
 		return _contentLength;
 	}
 
-	/* ------------------------------------------------------------ */
 	public long getContentRead()
 	{
 		return _contentPosition;
@@ -135,66 +108,29 @@
 	 */
 	public void setHeadResponse(boolean head)
 	{
-		_headResponse=head;
-	}
-
-	/* ------------------------------------------------------------------------------- */
-	public int getState()
-	{
-		return _state;
+		_headResponse = head;
 	}
 
-	/* ------------------------------------------------------------------------------- */
-	public boolean inContentState()
-	{
-		return _state > 0;
-	}
-
-	/* ------------------------------------------------------------------------------- */
-	public boolean inHeaderState()
-	{
-		return _state < 0;
-	}
-
-	/* ------------------------------------------------------------------------------- */
 	public boolean isChunking()
 	{
 		return _contentLength==HttpTokens.CHUNKED_CONTENT;
 	}
 
-	/* ------------------------------------------------------------ */
 	public boolean isIdle()
 	{
-		return isState(STATE_START);
-	}
-
-	/* ------------------------------------------------------------ */
-	public boolean isComplete()
-	{
-		return isState(STATE_END);
+		return _state==STATE_START;
 	}
 
-	/* ------------------------------------------------------------ */
-	public boolean isMoreInBuffer()
-	throws IOException
+	public boolean isComplete()
 	{
-		return ( _header!=null && _header.hasContent() ||
-			 _body!=null && _body.hasContent());
+		return _state==STATE_END;
 	}
 
-	/* ------------------------------------------------------------------------------- */
-	public boolean isState(int state)
-	{
-		return _state == state;
-	}
-
-	/* ------------------------------------------------------------------------------- */
 	public boolean isPersistent()
 	{
 		return _persistent;
 	}
 
-	/* ------------------------------------------------------------------------------- */
 	public void setPersistent(boolean persistent)
 	{
 		_persistent = persistent;
@@ -204,25 +140,6 @@
 
 	/* ------------------------------------------------------------------------------- */
 	/**
-	 * Parse until {@link #STATE_END END} state.
-	 * If the parser is already in the END state, then it is {@link #reset reset} and re-parsed.
-	 * @throws IllegalStateException If the buffers have already been partially parsed.
-	 */
-	public void parse() throws IOException
-	{
-		if (_state==STATE_END)
-			reset();
-		if (_state!=STATE_START)
-			throw new IllegalStateException("!START");
-
-		// continue parsing
-		while (_state != STATE_END)
-			if (parseNext()<0)
-				return;
-	}
-
-	/* ------------------------------------------------------------------------------- */
-	/**
 	 * Parse until END state.
 	 * This method will parse any remaining content in the current buffer as long as there is
 	 * no unconsumed content. It does not care about the {@link #getState current state} of the parser.
@@ -247,7 +164,7 @@
 	 * Parse until next Event.
 	 * @return an indication of progress <0 EOF, 0 no progress, >0 progress.
 	 */
-	public int parseNext() throws IOException
+	private int parseNext() throws IOException
 	{
 		try
 		{
@@ -418,7 +335,6 @@
 						}
 						else if (ch < HttpTokens.SPACE && ch>=0)
 						{
-							_handler.startResponse(HttpMethods.CACHE.lookup(_tok0), _responseStatus, null);
 							_eol=ch;
 							_state=STATE_HEADER;
 							_tok0.setPutIndex(_tok0.getIndex());
@@ -460,7 +376,6 @@
 						{
 							if (_responseStatus>0)
 							{
-								_handler.startResponse(HttpMethods.CACHE.lookup(_tok0), _responseStatus, null);
 								_eol=ch;
 								_state=STATE_HEADER;
 								_tok0.setPutIndex(_tok0.getIndex());
@@ -485,7 +400,8 @@
 						{
 							Buffer version;
 							if (_responseStatus>0)
-								_handler.startResponse(version=HttpVersions.CACHE.lookup(_tok0), _responseStatus,_buffer.sliceFromMark());
+//								_handler.startResponse(version=HttpVersions.CACHE.lookup(_tok0), _responseStatus,_buffer.sliceFromMark());
+								version = HttpVersions.CACHE.lookup(_tok0);
 							else
 								_handler.startRequest(HttpMethods.CACHE.lookup(_tok0), _tok1, version=HttpVersions.CACHE.lookup(_buffer.sliceFromMark()));
 							_eol=ch;
@@ -1000,7 +916,7 @@
 	/** fill the buffers from the endpoint
 	 *
 	 */
-	protected int fill() throws IOException
+	private int fill() throws IOException
 	{
 		// Do we have a buffer?
 		if (_buffer==null)
@@ -1014,46 +930,39 @@
 		}
 
 		// Shall we switch to a body buffer?
-		if (_buffer==_header && _state>STATE_END && _header.length()==0 && (_forceContentBuffer || (_contentLength-_contentPosition)>_header.capacity()) && (_body!=null||_buffers!=null))
+		if (_buffer==_header && _state>STATE_END && _header.length()==0 && ((_contentLength-_contentPosition)>_header.capacity()) && (_body!=null||_buffers!=null))
 		{
 			if (_body==null)
 				_body=_buffers.getBuffer();
 			_buffer=_body;
 		}
 
-		// Do we have somewhere to fill from?
-		if (_endp != null )
+		// Shall we compact the body?
+		if (_buffer==_body || _state>STATE_END)
 		{
-			// Shall we compact the body?
-			if (_buffer==_body || _state>STATE_END)
-			{
-				_buffer.compact();
-			}
-
-			// Are we full?
-			if (_buffer.space() == 0)
-			{
-				LOG.warn("HttpParser Full for {} ",_endp);
-				_buffer.clear();
-				throw new HttpException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413, "Request Entity Too Large: "+(_buffer==_body?"body":"head"));
-			}
-
-			try
-			{
-				int filled = _endp.fill(_buffer);
-				return filled;
-			}
-			catch(IOException e)
-			{
-				LOG.debug("",e);
-				throw (e instanceof EofException) ? e:new EofException(e);
-			}
+			_buffer.compact();
 		}
 
-		return -1;
+		// Are we full?
+		if (_buffer.space() == 0)
+		{
+			LOG.warn("HttpParser Full for {} ",_endp);
+			_buffer.clear();
+			throw new HttpException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413, "Request Entity Too Large: "+(_buffer==_body?"body":"head"));
+		}
+
+		try
+		{
+			int filled = _endp.fill(_buffer);
+			return filled;
+		}
+		catch(IOException e)
+		{
+			LOG.debug("",e);
+			throw (e instanceof EofException) ? e:new EofException(e);
+		}
 	}
 
-	/* ------------------------------------------------------------------------------- */
 	public void reset()
 	{
 		// reset state
@@ -1100,7 +1009,6 @@
 	}
 
 
-	/* ------------------------------------------------------------------------------- */
 	public void returnBuffers()
 	{
 		if (_body!=null && !_body.hasContent() && _body.markIndex()==-1 && _buffers!=null)
@@ -1121,20 +1029,6 @@
 		}
 	}
 
-	/* ------------------------------------------------------------------------------- */
-	public void setState(int state)
-	{
-		this._state=state;
-		_contentLength=HttpTokens.UNKNOWN_CONTENT;
-	}
-
-	/* ------------------------------------------------------------------------------- */
-	public String toString(Buffer buf)
-	{
-		return "state=" + _state + " length=" + _length + " buf=" + buf.hashCode();
-	}
-
-	/* ------------------------------------------------------------------------------- */
 	@Override
 	public String toString()
 	{
@@ -1145,40 +1039,23 @@
 				_contentLength);
 	}
 
-	/* ------------------------------------------------------------ */
 	public Buffer getHeaderBuffer()
 	{
 		if (_header == null)
 		{
-			_header=_buffers.getHeader();
+			_header = _buffers.getHeader();
 			_tok0.update(_header);
 			_tok1.update(_header);
 		}
 		return _header;
 	}
 
-	/* ------------------------------------------------------------ */
-	public Buffer getBodyBuffer()
-	{
-		return _body;
-	}
-
-	/* ------------------------------------------------------------ */
-	/**
-	 * @param force True if a new buffer will be forced to be used for content and the header buffer will not be used.
-	 */
-	public void setForceContentBuffer(boolean force)
-	{
-		_forceContentBuffer=force;
-	}
-
-	/* ------------------------------------------------------------ */
 	public Buffer blockForContent(long maxIdleTime) throws IOException
 	{
 		if (_contentView.length()>0)
 			return _contentView;
 
-		if (getState() <= STATE_END || isState(STATE_SEEKING_EOF))
+		if (_state <= STATE_END || _state==STATE_SEEKING_EOF)
 			return null;
 
 		try
@@ -1186,7 +1063,7 @@
 			parseNext();
 
 			// parse until some progress is made (or IOException thrown for timeout)
-			while(_contentView.length() == 0 && !(isState(HttpParser.STATE_END)||isState(HttpParser.STATE_SEEKING_EOF)) && _endp!=null && _endp.isOpen())
+			while(_contentView.length() == 0 && !(_state==STATE_END||_state==STATE_SEEKING_EOF) && _endp.isOpen())
 			{
 				if (!_endp.isBlocking())
 				{
@@ -1231,27 +1108,19 @@
 		return _contentView==null?0:_contentView.length();
 	}
 
-	/* ------------------------------------------------------------ */
-	/* ------------------------------------------------------------ */
-	/* ------------------------------------------------------------ */
-	public static abstract class EventHandler
+
+	public interface EventHandler
 	{
 		public abstract void content(Buffer ref) throws IOException;
 
-		public void headerComplete() throws IOException
-		{
-		}
+		public void headerComplete() throws IOException;
 
-		public void messageComplete(long contentLength) throws IOException
-		{
-		}
+		public void messageComplete(long contentLength) throws IOException;
 
 		/**
 		 * This is the method called by parser when a HTTP Header name and value is found
 		 */
-		public void parsedHeader(Buffer name, Buffer value) throws IOException
-		{
-		}
+		public void parsedHeader(Buffer name, Buffer value) throws IOException;
 
 		/**
 		 * This is the method called by parser when the HTTP request line is parsed
@@ -1259,14 +1128,7 @@
 		public abstract void startRequest(Buffer method, Buffer url, Buffer version)
 				throws IOException;
 
-		/**
-		 * This is the method called by parser when the HTTP request line is parsed
-		 */
-		public abstract void startResponse(Buffer version, int status, Buffer reason)
-				throws IOException;
-
-		public void earlyEOF()
-		{}
+		public void earlyEOF();
 	}
 
 
--- a/src/org/eclipse/jetty/server/AbstractHttpConnection.java	Sun Oct 16 18:01:39 2016 -0600
+++ b/src/org/eclipse/jetty/server/AbstractHttpConnection.java	Sun Oct 16 21:01:26 2016 -0600
@@ -681,7 +681,7 @@
 	}
 
 
-	private class RequestHandler extends HttpParser.EventHandler
+	private class RequestHandler implements HttpParser.EventHandler
 	{
 		@Override
 		public void startRequest(Buffer method, Buffer uri, Buffer version) throws IOException
@@ -714,13 +714,6 @@
 		}
 
 		@Override
-		public void startResponse(Buffer version, int status, Buffer reason)
-		{
-			if (LOG.isDebugEnabled())
-				LOG.debug("Bad request!: "+version+" "+status+" "+reason);
-		}
-
-		@Override
 		public void earlyEOF()
 		{
 			AbstractHttpConnection.this.earlyEOF();
--- a/src/org/eclipse/jetty/server/HttpInput.java	Sun Oct 16 18:01:39 2016 -0600
+++ b/src/org/eclipse/jetty/server/HttpInput.java	Sun Oct 16 21:01:26 2016 -0600
@@ -26,7 +26,7 @@
 import org.eclipse.jetty.io.Buffer;
 import org.eclipse.jetty.io.EofException;
 
-public class HttpInput extends ServletInputStream
+public final class HttpInput extends ServletInputStream
 {
 	protected final AbstractHttpConnection _connection;
 	protected final HttpParser _parser;
@@ -56,16 +56,15 @@
 	@Override
 	public int read(byte[] b, int off, int len) throws IOException
 	{
-		int l=-1;
-		Buffer content=_parser.blockForContent(_connection.getMaxIdleTime());
+		int l = -1;
+		Buffer content = _parser.blockForContent(_connection.getMaxIdleTime());
 		if (content!=null)
-			l= content.get(b, off, len);
+			l = content.get(b, off, len);
 		else if (_connection.isEarlyEOF())
 			throw new EofException("early EOF");
 		return l;
 	}
 
-	/* ------------------------------------------------------------ */
 	@Override
 	public int available() throws IOException
 	{