Mercurial Hosting > luan
changeset 877:fef4392f4905
remove sendServerVersion
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 04 Oct 2016 14:36:51 -0600 |
parents | 2efdb98f3543 |
children | 5f8a242392da |
files | src/org/eclipse/jetty/http/AbstractGenerator.java src/org/eclipse/jetty/http/Generator.java src/org/eclipse/jetty/http/HttpGenerator.java src/org/eclipse/jetty/server/AbstractHttpConnection.java src/org/eclipse/jetty/server/Server.java |
diffstat | 5 files changed, 1393 insertions(+), 1429 deletions(-) [+] |
line wrap: on
line diff
--- a/src/org/eclipse/jetty/http/AbstractGenerator.java Tue Oct 04 14:05:45 2016 -0600 +++ b/src/org/eclipse/jetty/http/AbstractGenerator.java Tue Oct 04 14:36:51 2016 -0600 @@ -40,493 +40,479 @@ */ public abstract class AbstractGenerator implements Generator { - private static final Logger LOG = LoggerFactory.getLogger(AbstractGenerator.class); + private static final Logger LOG = LoggerFactory.getLogger(AbstractGenerator.class); - // states - public final static int STATE_HEADER = 0; - public final static int STATE_CONTENT = 2; - public final static int STATE_FLUSHING = 3; - public final static int STATE_END = 4; + // states + public final static int STATE_HEADER = 0; + public final static int STATE_CONTENT = 2; + public final static int STATE_FLUSHING = 3; + public final static int STATE_END = 4; - public static final byte[] NO_BYTES = {}; + public static final byte[] NO_BYTES = {}; - // data + // data - protected final Buffers _buffers; // source of buffers - protected final EndPoint _endp; + protected final Buffers _buffers; // source of buffers + protected final EndPoint _endp; - protected int _state = STATE_HEADER; + protected int _state = STATE_HEADER; - protected int _status = 0; - protected int _version = HttpVersions.HTTP_1_1_ORDINAL; - protected Buffer _reason; - protected Buffer _method; - protected String _uri; + protected int _status = 0; + protected int _version = HttpVersions.HTTP_1_1_ORDINAL; + protected Buffer _reason; + protected Buffer _method; + protected String _uri; - protected long _contentWritten = 0; - protected long _contentLength = HttpTokens.UNKNOWN_CONTENT; - protected boolean _last = false; - protected boolean _head = false; - protected boolean _noContent = false; - protected Boolean _persistent = null; + protected long _contentWritten = 0; + protected long _contentLength = HttpTokens.UNKNOWN_CONTENT; + protected boolean _last = false; + protected boolean _head = false; + protected boolean _noContent = false; + protected Boolean _persistent = null; - protected Buffer _header; // Buffer for HTTP header (and maybe small _content) - protected Buffer _buffer; // Buffer for copy of passed _content - protected Buffer _content; // Buffer passed to addContent + protected Buffer _header; // Buffer for HTTP header (and maybe small _content) + protected Buffer _buffer; // Buffer for copy of passed _content + protected Buffer _content; // Buffer passed to addContent - protected Buffer _date; - - private boolean _sendServerVersion; + protected Buffer _date; - /* ------------------------------------------------------------------------------- */ - /** - * Constructor. - * - * @param buffers buffer pool - * @param io the end point - */ - public AbstractGenerator(Buffers buffers, EndPoint io) - { - this._buffers = buffers; - this._endp = io; - } + /* ------------------------------------------------------------------------------- */ + /** + * Constructor. + * + * @param buffers buffer pool + * @param io the end point + */ + public AbstractGenerator(Buffers buffers, EndPoint io) + { + this._buffers = buffers; + this._endp = io; + } - /* ------------------------------------------------------------------------------- */ - public abstract boolean isRequest(); + /* ------------------------------------------------------------------------------- */ + public abstract boolean isRequest(); - /* ------------------------------------------------------------------------------- */ - public abstract boolean isResponse(); + /* ------------------------------------------------------------------------------- */ + public abstract boolean isResponse(); - /* ------------------------------------------------------------------------------- */ - public boolean isOpen() - { - return _endp.isOpen(); - } + /* ------------------------------------------------------------------------------- */ + public boolean isOpen() + { + return _endp.isOpen(); + } - /* ------------------------------------------------------------------------------- */ - public void reset() - { - _state = STATE_HEADER; - _status = 0; - _version = HttpVersions.HTTP_1_1_ORDINAL; - _reason = null; - _last = false; - _head = false; - _noContent=false; - _persistent = null; - _contentWritten = 0; - _contentLength = HttpTokens.UNKNOWN_CONTENT; - _date = null; + /* ------------------------------------------------------------------------------- */ + public void reset() + { + _state = STATE_HEADER; + _status = 0; + _version = HttpVersions.HTTP_1_1_ORDINAL; + _reason = null; + _last = false; + _head = false; + _noContent=false; + _persistent = null; + _contentWritten = 0; + _contentLength = HttpTokens.UNKNOWN_CONTENT; + _date = null; - _content = null; - _method=null; - } + _content = null; + _method=null; + } - /* ------------------------------------------------------------------------------- */ - public void returnBuffers() - { - if (_buffer!=null && _buffer.length()==0) - { - _buffers.returnBuffer(_buffer); - _buffer=null; - } + /* ------------------------------------------------------------------------------- */ + public void returnBuffers() + { + if (_buffer!=null && _buffer.length()==0) + { + _buffers.returnBuffer(_buffer); + _buffer=null; + } - if (_header!=null && _header.length()==0) - { - _buffers.returnBuffer(_header); - _header=null; - } - } + if (_header!=null && _header.length()==0) + { + _buffers.returnBuffer(_header); + _header=null; + } + } - /* ------------------------------------------------------------------------------- */ - public void resetBuffer() - { - if(_state>=STATE_FLUSHING) - throw new IllegalStateException("Flushed"); + /* ------------------------------------------------------------------------------- */ + public void resetBuffer() + { + if(_state>=STATE_FLUSHING) + throw new IllegalStateException("Flushed"); - _last = false; - _persistent=null; - _contentWritten = 0; - _contentLength = HttpTokens.UNKNOWN_CONTENT; - _content=null; - if (_buffer!=null) - _buffer.clear(); - } + _last = false; + _persistent=null; + _contentWritten = 0; + _contentLength = HttpTokens.UNKNOWN_CONTENT; + _content=null; + if (_buffer!=null) + _buffer.clear(); + } - /* ------------------------------------------------------------ */ - /** - * @return Returns the contentBufferSize. - */ - public int getContentBufferSize() - { - if (_buffer==null) - _buffer=_buffers.getBuffer(); - return _buffer.capacity(); - } + /* ------------------------------------------------------------ */ + /** + * @return Returns the contentBufferSize. + */ + public int getContentBufferSize() + { + if (_buffer==null) + _buffer=_buffers.getBuffer(); + return _buffer.capacity(); + } - /* ------------------------------------------------------------ */ - /** - * @param contentBufferSize The contentBufferSize to set. - */ - public void increaseContentBufferSize(int contentBufferSize) - { - if (_buffer==null) - _buffer=_buffers.getBuffer(); - if (contentBufferSize > _buffer.capacity()) - { - Buffer nb = _buffers.getBuffer(contentBufferSize); - nb.put(_buffer); - _buffers.returnBuffer(_buffer); - _buffer = nb; - } - } + /* ------------------------------------------------------------ */ + /** + * @param contentBufferSize The contentBufferSize to set. + */ + public void increaseContentBufferSize(int contentBufferSize) + { + if (_buffer==null) + _buffer=_buffers.getBuffer(); + if (contentBufferSize > _buffer.capacity()) + { + Buffer nb = _buffers.getBuffer(contentBufferSize); + nb.put(_buffer); + _buffers.returnBuffer(_buffer); + _buffer = nb; + } + } - /* ------------------------------------------------------------ */ - public Buffer getUncheckedBuffer() - { - return _buffer; - } + /* ------------------------------------------------------------ */ + public Buffer getUncheckedBuffer() + { + return _buffer; + } - /* ------------------------------------------------------------ */ - public boolean getSendServerVersion () - { - return _sendServerVersion; - } - - /* ------------------------------------------------------------ */ - public void setSendServerVersion (boolean sendServerVersion) - { - _sendServerVersion = sendServerVersion; - } + /* ------------------------------------------------------------ */ + public int getState() + { + return _state; + } - /* ------------------------------------------------------------ */ - public int getState() - { - return _state; - } + /* ------------------------------------------------------------ */ + public boolean isState(int state) + { + return _state == state; + } - /* ------------------------------------------------------------ */ - public boolean isState(int state) - { - return _state == state; - } + /* ------------------------------------------------------------ */ + public boolean isComplete() + { + return _state == STATE_END; + } - /* ------------------------------------------------------------ */ - public boolean isComplete() - { - return _state == STATE_END; - } + /* ------------------------------------------------------------ */ + public boolean isIdle() + { + return _state == STATE_HEADER && _method==null && _status==0; + } - /* ------------------------------------------------------------ */ - public boolean isIdle() - { - return _state == STATE_HEADER && _method==null && _status==0; - } + /* ------------------------------------------------------------ */ + public boolean isCommitted() + { + return _state != STATE_HEADER; + } - /* ------------------------------------------------------------ */ - public boolean isCommitted() - { - return _state != STATE_HEADER; - } + /* ------------------------------------------------------------ */ + /** + * @return Returns the head. + */ + public boolean isHead() + { + return _head; + } - /* ------------------------------------------------------------ */ - /** - * @return Returns the head. - */ - public boolean isHead() - { - return _head; - } + /* ------------------------------------------------------------ */ + public void setContentLength(long value) + { + if (value<0) + _contentLength=HttpTokens.UNKNOWN_CONTENT; + else + _contentLength=value; + } - /* ------------------------------------------------------------ */ - public void setContentLength(long value) - { - if (value<0) - _contentLength=HttpTokens.UNKNOWN_CONTENT; - else - _contentLength=value; - } + /* ------------------------------------------------------------ */ + /** + * @param head The head to set. + */ + public void setHead(boolean head) + { + _head = head; + } - /* ------------------------------------------------------------ */ - /** - * @param head The head to set. - */ - public void setHead(boolean head) - { - _head = head; - } + /* ------------------------------------------------------------ */ + /** + * @return <code>false</code> if the connection should be closed after a request has been read, + * <code>true</code> if it should be used for additional requests. + */ + public boolean isPersistent() + { + return _persistent!=null + ?_persistent.booleanValue() + :(isRequest()?true:_version>HttpVersions.HTTP_1_0_ORDINAL); + } - /* ------------------------------------------------------------ */ - /** - * @return <code>false</code> if the connection should be closed after a request has been read, - * <code>true</code> if it should be used for additional requests. - */ - public boolean isPersistent() - { - return _persistent!=null - ?_persistent.booleanValue() - :(isRequest()?true:_version>HttpVersions.HTTP_1_0_ORDINAL); - } + /* ------------------------------------------------------------ */ + public void setPersistent(boolean persistent) + { + _persistent=persistent; + } - /* ------------------------------------------------------------ */ - public void setPersistent(boolean persistent) - { - _persistent=persistent; - } - - /* ------------------------------------------------------------ */ - /** - * @param version The version of the client the response is being sent to (NB. Not the version - * in the response, which is the version of the server). - */ - public void setVersion(int version) - { - if (_state != STATE_HEADER) - throw new IllegalStateException("STATE!=START "+_state); - _version = version; - if (_version==HttpVersions.HTTP_0_9_ORDINAL && _method!=null) - _noContent=true; - } + /* ------------------------------------------------------------ */ + /** + * @param version The version of the client the response is being sent to (NB. Not the version + * in the response, which is the version of the server). + */ + public void setVersion(int version) + { + if (_state != STATE_HEADER) + throw new IllegalStateException("STATE!=START "+_state); + _version = version; + if (_version==HttpVersions.HTTP_0_9_ORDINAL && _method!=null) + _noContent=true; + } - /* ------------------------------------------------------------ */ - public int getVersion() - { - return _version; - } + /* ------------------------------------------------------------ */ + public int getVersion() + { + return _version; + } - /* ------------------------------------------------------------ */ - /** - * @see org.eclipse.jetty.http.Generator#setDate(org.eclipse.jetty.io.Buffer) - */ - public void setDate(Buffer timeStampBuffer) - { - _date=timeStampBuffer; - } + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.http.Generator#setDate(org.eclipse.jetty.io.Buffer) + */ + public void setDate(Buffer timeStampBuffer) + { + _date=timeStampBuffer; + } - /* ------------------------------------------------------------ */ - /** - */ - public void setRequest(String method, String uri) - { - if (method==null || HttpMethods.GET.equals(method) ) - _method=HttpMethods.GET_BUFFER; - else - _method=HttpMethods.CACHE.lookup(method); - _uri=uri; - if (_version==HttpVersions.HTTP_0_9_ORDINAL) - _noContent=true; - } + /* ------------------------------------------------------------ */ + /** + */ + public void setRequest(String method, String uri) + { + if (method==null || HttpMethods.GET.equals(method) ) + _method=HttpMethods.GET_BUFFER; + else + _method=HttpMethods.CACHE.lookup(method); + _uri=uri; + if (_version==HttpVersions.HTTP_0_9_ORDINAL) + _noContent=true; + } - /* ------------------------------------------------------------ */ - /** - * @param status The status code to send. - * @param reason the status message to send. - */ - public void setResponse(int status, String reason) - { - if (_state != STATE_HEADER) throw new IllegalStateException("STATE!=START"); - _method=null; - _status = status; - if (reason!=null) - { - int len=reason.length(); + /* ------------------------------------------------------------ */ + /** + * @param status The status code to send. + * @param reason the status message to send. + */ + public void setResponse(int status, String reason) + { + if (_state != STATE_HEADER) throw new IllegalStateException("STATE!=START"); + _method=null; + _status = status; + if (reason!=null) + { + int len=reason.length(); - // TODO don't hard code - if (len>1024) - len=1024; - _reason=new ByteArrayBuffer(len); - for (int i=0;i<len;i++) - { - char ch = reason.charAt(i); - if (ch!='\r'&&ch!='\n') - _reason.put((byte)ch); - else - _reason.put((byte)' '); - } - } - } + // TODO don't hard code + if (len>1024) + len=1024; + _reason=new ByteArrayBuffer(len); + for (int i=0;i<len;i++) + { + char ch = reason.charAt(i); + if (ch!='\r'&&ch!='\n') + _reason.put((byte)ch); + else + _reason.put((byte)' '); + } + } + } - /* ------------------------------------------------------------ */ - /** Prepare buffer for unchecked writes. - * Prepare the generator buffer to receive unchecked writes - * @return the available space in the buffer. - * @throws IOException - */ - public abstract int prepareUncheckedAddContent() throws IOException; + /* ------------------------------------------------------------ */ + /** Prepare buffer for unchecked writes. + * Prepare the generator buffer to receive unchecked writes + * @return the available space in the buffer. + * @throws IOException + */ + public abstract int prepareUncheckedAddContent() throws IOException; - /* ------------------------------------------------------------ */ - void uncheckedAddContent(int b) - { - _buffer.put((byte)b); - } + /* ------------------------------------------------------------ */ + void uncheckedAddContent(int b) + { + _buffer.put((byte)b); + } - /* ------------------------------------------------------------ */ - public void completeUncheckedAddContent() - { - if (_noContent) - { - if(_buffer!=null) - _buffer.clear(); - } - else - { - _contentWritten+=_buffer.length(); - if (_head) - _buffer.clear(); - } - } + /* ------------------------------------------------------------ */ + public void completeUncheckedAddContent() + { + if (_noContent) + { + if(_buffer!=null) + _buffer.clear(); + } + else + { + _contentWritten+=_buffer.length(); + if (_head) + _buffer.clear(); + } + } - /* ------------------------------------------------------------ */ - public boolean isBufferFull() - { - if (_buffer != null && _buffer.space()==0) - { - if (_buffer.length()==0 && !_buffer.isImmutable()) - _buffer.compact(); - return _buffer.space()==0; - } + /* ------------------------------------------------------------ */ + public boolean isBufferFull() + { + if (_buffer != null && _buffer.space()==0) + { + if (_buffer.length()==0 && !_buffer.isImmutable()) + _buffer.compact(); + return _buffer.space()==0; + } - return _content!=null && _content.length()>0; - } + return _content!=null && _content.length()>0; + } - /* ------------------------------------------------------------ */ - public boolean isWritten() - { - return _contentWritten>0; - } + /* ------------------------------------------------------------ */ + public boolean isWritten() + { + return _contentWritten>0; + } - /* ------------------------------------------------------------ */ - public boolean isAllContentWritten() - { - return _contentLength>=0 && _contentWritten>=_contentLength; - } + /* ------------------------------------------------------------ */ + public boolean isAllContentWritten() + { + return _contentLength>=0 && _contentWritten>=_contentLength; + } - /* ------------------------------------------------------------ */ - public abstract void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException; + /* ------------------------------------------------------------ */ + public abstract void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException; - /* ------------------------------------------------------------ */ - /** - * Complete the message. - * - * @throws IOException - */ - public void complete() throws IOException - { - if (_state == STATE_HEADER) - { - throw new IllegalStateException("State==HEADER"); - } + /* ------------------------------------------------------------ */ + /** + * Complete the message. + * + * @throws IOException + */ + public void complete() throws IOException + { + if (_state == STATE_HEADER) + { + throw new IllegalStateException("State==HEADER"); + } - if (_contentLength >= 0 && _contentLength != _contentWritten && !_head) - { - if (LOG.isDebugEnabled()) - LOG.debug("ContentLength written=="+_contentWritten+" != contentLength=="+_contentLength); - _persistent = false; - } - } + if (_contentLength >= 0 && _contentLength != _contentWritten && !_head) + { + if (LOG.isDebugEnabled()) + LOG.debug("ContentLength written=="+_contentWritten+" != contentLength=="+_contentLength); + _persistent = false; + } + } - /* ------------------------------------------------------------ */ - public abstract int flushBuffer() throws IOException; + /* ------------------------------------------------------------ */ + public abstract int flushBuffer() throws IOException; - /* ------------------------------------------------------------ */ - public void flush(long maxIdleTime) throws IOException - { - // block until everything is flushed - long now=System.currentTimeMillis(); - long end=now+maxIdleTime; - Buffer content = _content; - Buffer buffer = _buffer; - if (content!=null && content.length()>0 || buffer!=null && buffer.length()>0 || isBufferFull()) - { - flushBuffer(); + /* ------------------------------------------------------------ */ + public void flush(long maxIdleTime) throws IOException + { + // block until everything is flushed + long now=System.currentTimeMillis(); + long end=now+maxIdleTime; + Buffer content = _content; + Buffer buffer = _buffer; + if (content!=null && content.length()>0 || buffer!=null && buffer.length()>0 || isBufferFull()) + { + flushBuffer(); - while (now<end && (content!=null && content.length()>0 ||buffer!=null && buffer.length()>0) && _endp.isOpen()&& !_endp.isOutputShutdown()) - { - blockForOutput(end-now); - now=System.currentTimeMillis(); - } - } - } + while (now<end && (content!=null && content.length()>0 ||buffer!=null && buffer.length()>0) && _endp.isOpen()&& !_endp.isOutputShutdown()) + { + blockForOutput(end-now); + now=System.currentTimeMillis(); + } + } + } - /* ------------------------------------------------------------ */ - /** - * Utility method to send an error response. If the builder is not committed, this call is - * equivalent to a setResponse, addContent and complete call. - * - * @param code The error code - * @param reason The error reason - * @param content Contents of the error page - * @param close True if the connection should be closed - * @throws IOException if there is a problem flushing the response - */ - public void sendError(int code, String reason, String content, boolean close) throws IOException - { - if (close) - _persistent=false; - if (isCommitted()) - { - LOG.debug("sendError on committed: {} {}",code,reason); - } - else - { - LOG.debug("sendError: {} {}",code,reason); - setResponse(code, reason); - if (content != null) - { - completeHeader(null, false); - addContent(new View(new ByteArrayBuffer(content)), Generator.LAST); - } - else if (code>=400) - { - completeHeader(null, false); - addContent(new View(new ByteArrayBuffer("Error: "+(reason==null?(""+code):reason))), Generator.LAST); - } - else - { - completeHeader(null, true); - } - complete(); - } - } + /* ------------------------------------------------------------ */ + /** + * Utility method to send an error response. If the builder is not committed, this call is + * equivalent to a setResponse, addContent and complete call. + * + * @param code The error code + * @param reason The error reason + * @param content Contents of the error page + * @param close True if the connection should be closed + * @throws IOException if there is a problem flushing the response + */ + public void sendError(int code, String reason, String content, boolean close) throws IOException + { + if (close) + _persistent=false; + if (isCommitted()) + { + LOG.debug("sendError on committed: {} {}",code,reason); + } + else + { + LOG.debug("sendError: {} {}",code,reason); + setResponse(code, reason); + if (content != null) + { + completeHeader(null, false); + addContent(new View(new ByteArrayBuffer(content)), Generator.LAST); + } + else if (code>=400) + { + completeHeader(null, false); + addContent(new View(new ByteArrayBuffer("Error: "+(reason==null?(""+code):reason))), Generator.LAST); + } + else + { + completeHeader(null, true); + } + complete(); + } + } - /* ------------------------------------------------------------ */ - /** - * @return Returns the contentWritten. - */ - public long getContentWritten() - { - return _contentWritten; - } + /* ------------------------------------------------------------ */ + /** + * @return Returns the contentWritten. + */ + public long getContentWritten() + { + return _contentWritten; + } - /* ------------------------------------------------------------ */ - public void blockForOutput(long maxIdleTime) throws IOException - { - if (_endp.isBlocking()) - { - try - { - flushBuffer(); - } - catch(IOException e) - { - _endp.close(); - throw e; - } - } - else - { - if (!_endp.blockWritable(maxIdleTime)) - { - _endp.close(); - throw new EofException("timeout"); - } + /* ------------------------------------------------------------ */ + public void blockForOutput(long maxIdleTime) throws IOException + { + if (_endp.isBlocking()) + { + try + { + flushBuffer(); + } + catch(IOException e) + { + _endp.close(); + throw e; + } + } + else + { + if (!_endp.blockWritable(maxIdleTime)) + { + _endp.close(); + throw new EofException("timeout"); + } - flushBuffer(); - } - } + flushBuffer(); + } + } }
--- a/src/org/eclipse/jetty/http/Generator.java Tue Oct 04 14:05:45 2016 -0600 +++ b/src/org/eclipse/jetty/http/Generator.java Tue Oct 04 14:36:51 2016 -0600 @@ -25,72 +25,70 @@ public interface Generator { - public static final boolean LAST=true; - public static final boolean MORE=false; - - /* ------------------------------------------------------------ */ - /** - * Add content. - * - * @param content - * @param last - * @throws IllegalArgumentException if <code>content</code> is {@link Buffer#isImmutable immutable}. - * @throws IllegalStateException If the request is not expecting any more content, - * or if the buffers are full and cannot be flushed. - * @throws IOException if there is a problem flushing the buffers. - */ - void addContent(Buffer content, boolean last) throws IOException; + public static final boolean LAST=true; + public static final boolean MORE=false; - void complete() throws IOException; - - void completeHeader(HttpFields responseFields, boolean last) throws IOException; - - int flushBuffer() throws IOException; - - int getContentBufferSize(); + /* ------------------------------------------------------------ */ + /** + * Add content. + * + * @param content + * @param last + * @throws IllegalArgumentException if <code>content</code> is {@link Buffer#isImmutable immutable}. + * @throws IllegalStateException If the request is not expecting any more content, + * or if the buffers are full and cannot be flushed. + * @throws IOException if there is a problem flushing the buffers. + */ + void addContent(Buffer content, boolean last) throws IOException; - long getContentWritten(); + void complete() throws IOException; + + void completeHeader(HttpFields responseFields, boolean last) throws IOException; + + int flushBuffer() throws IOException; - boolean isWritten(); - - boolean isAllContentWritten(); + int getContentBufferSize(); + + long getContentWritten(); - void increaseContentBufferSize(int size); - - boolean isBufferFull(); + boolean isWritten(); + + boolean isAllContentWritten(); - boolean isCommitted(); - - boolean isComplete(); + void increaseContentBufferSize(int size); + + boolean isBufferFull(); - boolean isPersistent(); + boolean isCommitted(); - void reset(); + boolean isComplete(); - void resetBuffer(); - - void returnBuffers(); + boolean isPersistent(); + + void reset(); - void sendError(int code, String reason, String content, boolean close) throws IOException; - - void setHead(boolean head); + void resetBuffer(); + + void returnBuffers(); - void setRequest(String method, String uri); - - void setResponse(int status, String reason); + void sendError(int code, String reason, String content, boolean close) throws IOException; + + void setHead(boolean head); + void setRequest(String method, String uri); - void setSendServerVersion(boolean sendServerVersion); - - void setVersion(int version); + void setResponse(int status, String reason); - boolean isIdle(); + + void setVersion(int version); + + boolean isIdle(); - void setContentLength(long length); - - void setPersistent(boolean persistent); + void setContentLength(long length); + + void setPersistent(boolean persistent); - void setDate(Buffer timeStampBuffer); - + void setDate(Buffer timeStampBuffer); + }
--- a/src/org/eclipse/jetty/http/HttpGenerator.java Tue Oct 04 14:05:45 2016 -0600 +++ b/src/org/eclipse/jetty/http/HttpGenerator.java Tue Oct 04 14:36:51 2016 -0600 @@ -41,1052 +41,1049 @@ */ public class HttpGenerator extends AbstractGenerator { - private static final Logger LOG = LoggerFactory.getLogger(HttpGenerator.class); + private static final Logger LOG = LoggerFactory.getLogger(HttpGenerator.class); - // Build cache of response lines for status - private static class Status - { - Buffer _reason; - Buffer _schemeCode; - Buffer _responseLine; - } - private static final Status[] __status = new Status[HttpStatus.MAX_CODE+1]; - static - { - int versionLength=HttpVersions.HTTP_1_1_BUFFER.length(); + // Build cache of response lines for status + private static class Status + { + Buffer _reason; + Buffer _schemeCode; + Buffer _responseLine; + } + private static final Status[] __status = new Status[HttpStatus.MAX_CODE+1]; + static + { + int versionLength=HttpVersions.HTTP_1_1_BUFFER.length(); - for (int i=0;i<__status.length;i++) - { - HttpStatus.Code code = HttpStatus.getCode(i); - if (code==null) - continue; - String reason=code.getMessage(); - byte[] bytes=new byte[versionLength+5+reason.length()+2]; - HttpVersions.HTTP_1_1_BUFFER.peek(0,bytes, 0, versionLength); - bytes[versionLength+0]=' '; - bytes[versionLength+1]=(byte)('0'+i/100); - bytes[versionLength+2]=(byte)('0'+(i%100)/10); - bytes[versionLength+3]=(byte)('0'+(i%10)); - bytes[versionLength+4]=' '; - for (int j=0;j<reason.length();j++) - bytes[versionLength+5+j]=(byte)reason.charAt(j); - bytes[versionLength+5+reason.length()]=HttpTokens.CARRIAGE_RETURN; - bytes[versionLength+6+reason.length()]=HttpTokens.LINE_FEED; + for (int i=0;i<__status.length;i++) + { + HttpStatus.Code code = HttpStatus.getCode(i); + if (code==null) + continue; + String reason=code.getMessage(); + byte[] bytes=new byte[versionLength+5+reason.length()+2]; + HttpVersions.HTTP_1_1_BUFFER.peek(0,bytes, 0, versionLength); + bytes[versionLength+0]=' '; + bytes[versionLength+1]=(byte)('0'+i/100); + bytes[versionLength+2]=(byte)('0'+(i%100)/10); + bytes[versionLength+3]=(byte)('0'+(i%10)); + bytes[versionLength+4]=' '; + for (int j=0;j<reason.length();j++) + bytes[versionLength+5+j]=(byte)reason.charAt(j); + bytes[versionLength+5+reason.length()]=HttpTokens.CARRIAGE_RETURN; + bytes[versionLength+6+reason.length()]=HttpTokens.LINE_FEED; - __status[i] = new Status(); - __status[i]._reason=new ByteArrayBuffer(bytes,versionLength+5,bytes.length-versionLength-7,Buffer.IMMUTABLE); - __status[i]._schemeCode=new ByteArrayBuffer(bytes,0,versionLength+5,Buffer.IMMUTABLE); - __status[i]._responseLine=new ByteArrayBuffer(bytes,0,bytes.length,Buffer.IMMUTABLE); - } - } + __status[i] = new Status(); + __status[i]._reason=new ByteArrayBuffer(bytes,versionLength+5,bytes.length-versionLength-7,Buffer.IMMUTABLE); + __status[i]._schemeCode=new ByteArrayBuffer(bytes,0,versionLength+5,Buffer.IMMUTABLE); + __status[i]._responseLine=new ByteArrayBuffer(bytes,0,bytes.length,Buffer.IMMUTABLE); + } + } - /* ------------------------------------------------------------------------------- */ - public static Buffer getReasonBuffer(int code) - { - Status status = code<__status.length?__status[code]:null; - if (status!=null) - return status._reason; - return null; - } + /* ------------------------------------------------------------------------------- */ + public static Buffer getReasonBuffer(int code) + { + Status status = code<__status.length?__status[code]:null; + if (status!=null) + return status._reason; + return null; + } - // common _content - private static final byte[] LAST_CHUNK = - { (byte) '0', (byte) '\015', (byte) '\012', (byte) '\015', (byte) '\012'}; - private static final byte[] CONTENT_LENGTH_0 = StringUtil.getBytes("Content-Length: 0\015\012"); - private static final byte[] CONNECTION_KEEP_ALIVE = StringUtil.getBytes("Connection: keep-alive\015\012"); - private static final byte[] CONNECTION_CLOSE = StringUtil.getBytes("Connection: close\015\012"); - private static final byte[] CONNECTION_ = StringUtil.getBytes("Connection: "); - private static final byte[] CRLF = StringUtil.getBytes("\015\012"); - private static final byte[] TRANSFER_ENCODING_CHUNKED = StringUtil.getBytes("Transfer-Encoding: chunked\015\012"); - private static byte[] SERVER = StringUtil.getBytes("Server: Jetty(7.0.x)\015\012"); + // common _content + private static final byte[] LAST_CHUNK = + { (byte) '0', (byte) '\015', (byte) '\012', (byte) '\015', (byte) '\012'}; + private static final byte[] CONTENT_LENGTH_0 = StringUtil.getBytes("Content-Length: 0\015\012"); + private static final byte[] CONNECTION_KEEP_ALIVE = StringUtil.getBytes("Connection: keep-alive\015\012"); + private static final byte[] CONNECTION_CLOSE = StringUtil.getBytes("Connection: close\015\012"); + private static final byte[] CONNECTION_ = StringUtil.getBytes("Connection: "); + private static final byte[] CRLF = StringUtil.getBytes("\015\012"); + private static final byte[] TRANSFER_ENCODING_CHUNKED = StringUtil.getBytes("Transfer-Encoding: chunked\015\012"); + private static byte[] SERVER = StringUtil.getBytes("Server: Jetty(7.0.x)\015\012"); - // other statics - private static final int CHUNK_SPACE = 12; + // other statics + private static final int CHUNK_SPACE = 12; - public static void setServerVersion(String version) - { - SERVER=StringUtil.getBytes("Server: Jetty("+version+")\015\012"); - } + public static void setServerVersion(String version) + { + SERVER=StringUtil.getBytes("Server: Jetty("+version+")\015\012"); + } - // data - protected boolean _bypass = false; // True if _content buffer can be written directly to endp and bypass the content buffer - private boolean _needCRLF = false; - private boolean _needEOC = false; - private boolean _bufferChunked = false; + // data + protected boolean _bypass = false; // True if _content buffer can be written directly to endp and bypass the content buffer + private boolean _needCRLF = false; + private boolean _needEOC = false; + private boolean _bufferChunked = false; - /* ------------------------------------------------------------------------------- */ - /** - * Constructor. - * - * @param buffers buffer pool - * @param io the end point to use - */ - public HttpGenerator(Buffers buffers, EndPoint io) - { - super(buffers,io); - } + /* ------------------------------------------------------------------------------- */ + /** + * Constructor. + * + * @param buffers buffer pool + * @param io the end point to use + */ + public HttpGenerator(Buffers buffers, EndPoint io) + { + super(buffers,io); + } - /* ------------------------------------------------------------------------------- */ - @Override - public void reset() - { - if (_persistent!=null && !_persistent && _endp!=null && !_endp.isOutputShutdown()) - { - try - { - _endp.shutdownOutput(); - } - catch(IOException e) - { - LOG.trace("",e); - } - } - super.reset(); - if (_buffer!=null) - _buffer.clear(); - if (_header!=null) - _header.clear(); - if (_content!=null) - _content=null; - _bypass = false; - _needCRLF = false; - _needEOC = false; - _bufferChunked=false; - _method=null; - _uri=null; - _noContent=false; - } + /* ------------------------------------------------------------------------------- */ + @Override + public void reset() + { + if (_persistent!=null && !_persistent && _endp!=null && !_endp.isOutputShutdown()) + { + try + { + _endp.shutdownOutput(); + } + catch(IOException e) + { + LOG.trace("",e); + } + } + super.reset(); + if (_buffer!=null) + _buffer.clear(); + if (_header!=null) + _header.clear(); + if (_content!=null) + _content=null; + _bypass = false; + _needCRLF = false; + _needEOC = false; + _bufferChunked=false; + _method=null; + _uri=null; + _noContent=false; + } - /* ------------------------------------------------------------ */ - /** - * Add content. - * - * @param content - * @param last - * @throws IllegalArgumentException if <code>content</code> is {@link Buffer#isImmutable immutable}. - * @throws IllegalStateException If the request is not expecting any more content, - * or if the buffers are full and cannot be flushed. - * @throws IOException if there is a problem flushing the buffers. - */ - public void addContent(Buffer content, boolean last) throws IOException - { - if (_noContent) - throw new IllegalStateException("NO CONTENT"); + /* ------------------------------------------------------------ */ + /** + * Add content. + * + * @param content + * @param last + * @throws IllegalArgumentException if <code>content</code> is {@link Buffer#isImmutable immutable}. + * @throws IllegalStateException If the request is not expecting any more content, + * or if the buffers are full and cannot be flushed. + * @throws IOException if there is a problem flushing the buffers. + */ + public void addContent(Buffer content, boolean last) throws IOException + { + if (_noContent) + throw new IllegalStateException("NO CONTENT"); - if (_last || _state==STATE_END) - { - LOG.warn("Ignoring extra content {}",content); - content.clear(); - return; - } - _last = last; + if (_last || _state==STATE_END) + { + LOG.warn("Ignoring extra content {}",content); + content.clear(); + return; + } + _last = last; - // Handle any unfinished business? - if (_content!=null && _content.length()>0 || _bufferChunked) - { - if (_endp.isOutputShutdown()) - throw new EofException(); - flushBuffer(); - if (_content != null && _content.length()>0) - { - if (_bufferChunked) - { - Buffer nc=_buffers.getBuffer(_content.length()+CHUNK_SPACE+content.length()); - nc.put(_content); - nc.put(HttpTokens.CRLF); - BufferUtil.putHexInt(nc, content.length()); - nc.put(HttpTokens.CRLF); - nc.put(content); - content=nc; - } - else - { - Buffer nc=_buffers.getBuffer(_content.length()+content.length()); - nc.put(_content); - nc.put(content); - content=nc; - } - } - } + // Handle any unfinished business? + if (_content!=null && _content.length()>0 || _bufferChunked) + { + if (_endp.isOutputShutdown()) + throw new EofException(); + flushBuffer(); + if (_content != null && _content.length()>0) + { + if (_bufferChunked) + { + Buffer nc=_buffers.getBuffer(_content.length()+CHUNK_SPACE+content.length()); + nc.put(_content); + nc.put(HttpTokens.CRLF); + BufferUtil.putHexInt(nc, content.length()); + nc.put(HttpTokens.CRLF); + nc.put(content); + content=nc; + } + else + { + Buffer nc=_buffers.getBuffer(_content.length()+content.length()); + nc.put(_content); + nc.put(content); + content=nc; + } + } + } - _content = content; - _contentWritten += content.length(); + _content = content; + _contentWritten += content.length(); - // Handle the _content - if (_head) - { - content.clear(); - _content=null; - } - else if (_endp != null && (_buffer==null || _buffer.length()==0) && _content.length() > 0 && (_last || isCommitted() && _content.length()>1024)) - { - _bypass = true; - } - else if (!_bufferChunked) - { - // Yes - so we better check we have a buffer - if (_buffer == null) - _buffer = _buffers.getBuffer(); + // Handle the _content + if (_head) + { + content.clear(); + _content=null; + } + else if (_endp != null && (_buffer==null || _buffer.length()==0) && _content.length() > 0 && (_last || isCommitted() && _content.length()>1024)) + { + _bypass = true; + } + else if (!_bufferChunked) + { + // Yes - so we better check we have a buffer + if (_buffer == null) + _buffer = _buffers.getBuffer(); - // Copy _content to buffer; - int len=_buffer.put(_content); - _content.skip(len); - if (_content.length() == 0) - _content = null; - } - } + // Copy _content to buffer; + int len=_buffer.put(_content); + _content.skip(len); + if (_content.length() == 0) + _content = null; + } + } - /* ------------------------------------------------------------ */ - /** - * send complete response. - * - * @param response - */ - public void sendResponse(Buffer response) throws IOException - { - if (_noContent || _state!=STATE_HEADER || _content!=null && _content.length()>0 || _bufferChunked || _head ) - throw new IllegalStateException(); + /* ------------------------------------------------------------ */ + /** + * send complete response. + * + * @param response + */ + public void sendResponse(Buffer response) throws IOException + { + if (_noContent || _state!=STATE_HEADER || _content!=null && _content.length()>0 || _bufferChunked || _head ) + throw new IllegalStateException(); - _last = true; + _last = true; - _content = response; - _bypass = true; - _state = STATE_FLUSHING; + _content = response; + _bypass = true; + _state = STATE_FLUSHING; - // TODO this is not exactly right, but should do. - _contentLength =_contentWritten = response.length(); + // TODO this is not exactly right, but should do. + _contentLength =_contentWritten = response.length(); - } + } - /* ------------------------------------------------------------ */ - /** Prepare buffer for unchecked writes. - * Prepare the generator buffer to receive unchecked writes - * @return the available space in the buffer. - * @throws IOException - */ - @Override - public int prepareUncheckedAddContent() throws IOException - { - if (_noContent) - return -1; + /* ------------------------------------------------------------ */ + /** Prepare buffer for unchecked writes. + * Prepare the generator buffer to receive unchecked writes + * @return the available space in the buffer. + * @throws IOException + */ + @Override + public int prepareUncheckedAddContent() throws IOException + { + if (_noContent) + return -1; - if (_last || _state==STATE_END) - return -1; + if (_last || _state==STATE_END) + return -1; - // Handle any unfinished business? - Buffer content = _content; - if (content != null && content.length()>0 || _bufferChunked) - { - flushBuffer(); - if (content != null && content.length()>0 || _bufferChunked) - throw new IllegalStateException("FULL"); - } + // Handle any unfinished business? + Buffer content = _content; + if (content != null && content.length()>0 || _bufferChunked) + { + flushBuffer(); + if (content != null && content.length()>0 || _bufferChunked) + throw new IllegalStateException("FULL"); + } - // we better check we have a buffer - if (_buffer == null) - _buffer = _buffers.getBuffer(); + // we better check we have a buffer + if (_buffer == null) + _buffer = _buffers.getBuffer(); - _contentWritten-=_buffer.length(); + _contentWritten-=_buffer.length(); - // Handle the _content - if (_head) - return Integer.MAX_VALUE; + // Handle the _content + if (_head) + return Integer.MAX_VALUE; - return _buffer.space()-(_contentLength == HttpTokens.CHUNKED_CONTENT?CHUNK_SPACE:0); - } + return _buffer.space()-(_contentLength == HttpTokens.CHUNKED_CONTENT?CHUNK_SPACE:0); + } - /* ------------------------------------------------------------ */ - @Override - public boolean isBufferFull() - { - // Should we flush the buffers? - return super.isBufferFull() || _bufferChunked || _bypass || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer != null && _buffer.space() < CHUNK_SPACE); - } + /* ------------------------------------------------------------ */ + @Override + public boolean isBufferFull() + { + // Should we flush the buffers? + return super.isBufferFull() || _bufferChunked || _bypass || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer != null && _buffer.space() < CHUNK_SPACE); + } - /* ------------------------------------------------------------ */ - public void send1xx(int code) throws IOException - { - if (_state != STATE_HEADER) - return; + /* ------------------------------------------------------------ */ + public void send1xx(int code) throws IOException + { + if (_state != STATE_HEADER) + return; - if (code<100||code>199) - throw new IllegalArgumentException("!1xx"); - Status status=__status[code]; - if (status==null) - throw new IllegalArgumentException(code+"?"); + if (code<100||code>199) + throw new IllegalArgumentException("!1xx"); + Status status=__status[code]; + if (status==null) + throw new IllegalArgumentException(code+"?"); - // get a header buffer - if (_header == null) - _header = _buffers.getHeader(); + // get a header buffer + if (_header == null) + _header = _buffers.getHeader(); - _header.put(status._responseLine); - _header.put(HttpTokens.CRLF); + _header.put(status._responseLine); + _header.put(HttpTokens.CRLF); - try - { - // nasty semi busy flush! - while(_header.length()>0) - { - int len = _endp.flush(_header); - if (len<0) - throw new EofException(); - if (len==0) - Thread.sleep(100); - } - } - catch(InterruptedException e) - { - LOG.debug("",e); - throw new InterruptedIOException(e.toString()); - } - } + try + { + // nasty semi busy flush! + while(_header.length()>0) + { + int len = _endp.flush(_header); + if (len<0) + throw new EofException(); + if (len==0) + Thread.sleep(100); + } + } + catch(InterruptedException e) + { + LOG.debug("",e); + throw new InterruptedIOException(e.toString()); + } + } - /* ------------------------------------------------------------ */ - @Override - public boolean isRequest() - { - return _method!=null; - } + /* ------------------------------------------------------------ */ + @Override + public boolean isRequest() + { + return _method!=null; + } - /* ------------------------------------------------------------ */ - @Override - public boolean isResponse() - { - return _method==null; - } + /* ------------------------------------------------------------ */ + @Override + public boolean isResponse() + { + return _method==null; + } - /* ------------------------------------------------------------ */ - @Override - public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException - { - if (_state != STATE_HEADER) - return; + /* ------------------------------------------------------------ */ + @Override + public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException + { + if (_state != STATE_HEADER) + return; - // handle a reset - if (isResponse() && _status==0) - throw new EofException(); + // handle a reset + if (isResponse() && _status==0) + throw new EofException(); - if (_last && !allContentAdded) - throw new IllegalStateException("last?"); - _last = _last | allContentAdded; + if (_last && !allContentAdded) + throw new IllegalStateException("last?"); + _last = _last | allContentAdded; - // get a header buffer - if (_header == null) - _header = _buffers.getHeader(); + // get a header buffer + if (_header == null) + _header = _buffers.getHeader(); - boolean has_server = false; + boolean has_server = false; - try - { - if (isRequest()) - { - _persistent=true; + try + { + if (isRequest()) + { + _persistent=true; - if (_version == HttpVersions.HTTP_0_9_ORDINAL) - { - _contentLength = HttpTokens.NO_CONTENT; - _header.put(_method); - _header.put((byte)' '); - _header.put(_uri.getBytes("UTF-8")); // TODO check - _header.put(HttpTokens.CRLF); - _state = STATE_FLUSHING; - _noContent=true; - return; - } - else - { - _header.put(_method); - _header.put((byte)' '); - _header.put(_uri.getBytes("UTF-8")); // TODO check - _header.put((byte)' '); - _header.put(_version==HttpVersions.HTTP_1_0_ORDINAL?HttpVersions.HTTP_1_0_BUFFER:HttpVersions.HTTP_1_1_BUFFER); - _header.put(HttpTokens.CRLF); - } - } - else - { - // Responses - if (_version == HttpVersions.HTTP_0_9_ORDINAL) - { - _persistent = false; - _contentLength = HttpTokens.EOF_CONTENT; - _state = STATE_CONTENT; - return; - } - else - { - if (_persistent==null) - _persistent= (_version > HttpVersions.HTTP_1_0_ORDINAL); + if (_version == HttpVersions.HTTP_0_9_ORDINAL) + { + _contentLength = HttpTokens.NO_CONTENT; + _header.put(_method); + _header.put((byte)' '); + _header.put(_uri.getBytes("UTF-8")); // TODO check + _header.put(HttpTokens.CRLF); + _state = STATE_FLUSHING; + _noContent=true; + return; + } + else + { + _header.put(_method); + _header.put((byte)' '); + _header.put(_uri.getBytes("UTF-8")); // TODO check + _header.put((byte)' '); + _header.put(_version==HttpVersions.HTTP_1_0_ORDINAL?HttpVersions.HTTP_1_0_BUFFER:HttpVersions.HTTP_1_1_BUFFER); + _header.put(HttpTokens.CRLF); + } + } + else + { + // Responses + if (_version == HttpVersions.HTTP_0_9_ORDINAL) + { + _persistent = false; + _contentLength = HttpTokens.EOF_CONTENT; + _state = STATE_CONTENT; + return; + } + else + { + if (_persistent==null) + _persistent= (_version > HttpVersions.HTTP_1_0_ORDINAL); - // add response line - Status status = _status<__status.length?__status[_status]:null; + // add response line + Status status = _status<__status.length?__status[_status]:null; - if (status==null) - { - _header.put(HttpVersions.HTTP_1_1_BUFFER); - _header.put((byte) ' '); - _header.put((byte) ('0' + _status / 100)); - _header.put((byte) ('0' + (_status % 100) / 10)); - _header.put((byte) ('0' + (_status % 10))); - _header.put((byte) ' '); - if (_reason==null) - { - _header.put((byte) ('0' + _status / 100)); - _header.put((byte) ('0' + (_status % 100) / 10)); - _header.put((byte) ('0' + (_status % 10))); - } - else - _header.put(_reason); - _header.put(HttpTokens.CRLF); - } - else - { - if (_reason==null) - _header.put(status._responseLine); - else - { - _header.put(status._schemeCode); - _header.put(_reason); - _header.put(HttpTokens.CRLF); - } - } + if (status==null) + { + _header.put(HttpVersions.HTTP_1_1_BUFFER); + _header.put((byte) ' '); + _header.put((byte) ('0' + _status / 100)); + _header.put((byte) ('0' + (_status % 100) / 10)); + _header.put((byte) ('0' + (_status % 10))); + _header.put((byte) ' '); + if (_reason==null) + { + _header.put((byte) ('0' + _status / 100)); + _header.put((byte) ('0' + (_status % 100) / 10)); + _header.put((byte) ('0' + (_status % 10))); + } + else + _header.put(_reason); + _header.put(HttpTokens.CRLF); + } + else + { + if (_reason==null) + _header.put(status._responseLine); + else + { + _header.put(status._schemeCode); + _header.put(_reason); + _header.put(HttpTokens.CRLF); + } + } - if (_status<200 && _status>=100 ) - { - _noContent=true; - _content=null; - if (_buffer!=null) - _buffer.clear(); - // end the header. + if (_status<200 && _status>=100 ) + { + _noContent=true; + _content=null; + if (_buffer!=null) + _buffer.clear(); + // end the header. - if (_status!=101 ) - { - _header.put(HttpTokens.CRLF); - _state = STATE_CONTENT; - return; - } - } - else if (_status==204 || _status==304) - { - _noContent=true; - _content=null; - if (_buffer!=null) - _buffer.clear(); - } - } - } + if (_status!=101 ) + { + _header.put(HttpTokens.CRLF); + _state = STATE_CONTENT; + return; + } + } + else if (_status==204 || _status==304) + { + _noContent=true; + _content=null; + if (_buffer!=null) + _buffer.clear(); + } + } + } - // Add headers - if (_status>=200 && _date!=null) - { - _header.put(HttpHeaders.DATE_BUFFER); - _header.put((byte)':'); - _header.put((byte)' '); - _header.put(_date); - _header.put(CRLF); - } + // Add headers + if (_status>=200 && _date!=null) + { + _header.put(HttpHeaders.DATE_BUFFER); + _header.put((byte)':'); + _header.put((byte)' '); + _header.put(_date); + _header.put(CRLF); + } - // key field values - HttpFields.Field content_length = null; - HttpFields.Field transfer_encoding = null; - boolean keep_alive = false; - boolean close=false; - boolean content_type=false; - StringBuilder connection = null; + // key field values + HttpFields.Field content_length = null; + HttpFields.Field transfer_encoding = null; + boolean keep_alive = false; + boolean close=false; + boolean content_type=false; + StringBuilder connection = null; - if (fields != null) - { - int s=fields.size(); - for (int f=0;f<s;f++) - { - HttpFields.Field field = fields.getField(f); - if (field==null) - continue; + if (fields != null) + { + int s=fields.size(); + for (int f=0;f<s;f++) + { + HttpFields.Field field = fields.getField(f); + if (field==null) + continue; - switch (field.getNameOrdinal()) - { - case HttpHeaders.CONTENT_LENGTH_ORDINAL: - content_length = field; - _contentLength = field.getLongValue(); + switch (field.getNameOrdinal()) + { + case HttpHeaders.CONTENT_LENGTH_ORDINAL: + content_length = field; + _contentLength = field.getLongValue(); - if (_contentLength < _contentWritten || _last && _contentLength != _contentWritten) - content_length = null; + if (_contentLength < _contentWritten || _last && _contentLength != _contentWritten) + content_length = null; - // write the field to the header buffer - field.putTo(_header); - break; + // write the field to the header buffer + field.putTo(_header); + break; - case HttpHeaders.CONTENT_TYPE_ORDINAL: - if (BufferUtil.isPrefix(MimeTypes.MULTIPART_BYTERANGES_BUFFER, field.getValueBuffer())) _contentLength = HttpTokens.SELF_DEFINING_CONTENT; + case HttpHeaders.CONTENT_TYPE_ORDINAL: + if (BufferUtil.isPrefix(MimeTypes.MULTIPART_BYTERANGES_BUFFER, field.getValueBuffer())) _contentLength = HttpTokens.SELF_DEFINING_CONTENT; - // write the field to the header buffer - content_type=true; - field.putTo(_header); - break; + // write the field to the header buffer + content_type=true; + field.putTo(_header); + break; - case HttpHeaders.TRANSFER_ENCODING_ORDINAL: - if (_version == HttpVersions.HTTP_1_1_ORDINAL) - transfer_encoding = field; - // Do NOT add yet! - break; + case HttpHeaders.TRANSFER_ENCODING_ORDINAL: + if (_version == HttpVersions.HTTP_1_1_ORDINAL) + transfer_encoding = field; + // Do NOT add yet! + break; - case HttpHeaders.CONNECTION_ORDINAL: - if (isRequest()) - field.putTo(_header); + case HttpHeaders.CONNECTION_ORDINAL: + if (isRequest()) + field.putTo(_header); - int connection_value = field.getValueOrdinal(); - switch (connection_value) - { - case -1: - { - String[] values = field.getValue().split(","); - for (int i=0;values!=null && i<values.length;i++) - { - CachedBuffer cb = HttpHeaderValues.CACHE.get(values[i].trim()); + int connection_value = field.getValueOrdinal(); + switch (connection_value) + { + case -1: + { + String[] values = field.getValue().split(","); + for (int i=0;values!=null && i<values.length;i++) + { + CachedBuffer cb = HttpHeaderValues.CACHE.get(values[i].trim()); - if (cb!=null) - { - switch(cb.getOrdinal()) - { - case HttpHeaderValues.CLOSE_ORDINAL: - close=true; - if (isResponse()) - _persistent=false; - keep_alive=false; - if (!_persistent && isResponse() && _contentLength == HttpTokens.UNKNOWN_CONTENT) - _contentLength = HttpTokens.EOF_CONTENT; - break; + if (cb!=null) + { + switch(cb.getOrdinal()) + { + case HttpHeaderValues.CLOSE_ORDINAL: + close=true; + if (isResponse()) + _persistent=false; + keep_alive=false; + if (!_persistent && isResponse() && _contentLength == HttpTokens.UNKNOWN_CONTENT) + _contentLength = HttpTokens.EOF_CONTENT; + break; - case HttpHeaderValues.KEEP_ALIVE_ORDINAL: - if (_version == HttpVersions.HTTP_1_0_ORDINAL) - { - keep_alive = true; - if (isResponse()) - _persistent = true; - } - break; + case HttpHeaderValues.KEEP_ALIVE_ORDINAL: + if (_version == HttpVersions.HTTP_1_0_ORDINAL) + { + keep_alive = true; + if (isResponse()) + _persistent = true; + } + break; - default: - if (connection==null) - connection=new StringBuilder(); - else - connection.append(','); - connection.append(values[i]); - } - } - else - { - if (connection==null) - connection=new StringBuilder(); - else - connection.append(','); - connection.append(values[i]); - } - } + default: + if (connection==null) + connection=new StringBuilder(); + else + connection.append(','); + connection.append(values[i]); + } + } + else + { + if (connection==null) + connection=new StringBuilder(); + else + connection.append(','); + connection.append(values[i]); + } + } - break; - } - case HttpHeaderValues.UPGRADE_ORDINAL: - { - // special case for websocket connection ordering - if (isResponse()) - { - field.putTo(_header); - continue; - } - } - case HttpHeaderValues.CLOSE_ORDINAL: - { - close=true; - if (isResponse()) - _persistent=false; - if (!_persistent && isResponse() && _contentLength == HttpTokens.UNKNOWN_CONTENT) - _contentLength = HttpTokens.EOF_CONTENT; - break; - } - case HttpHeaderValues.KEEP_ALIVE_ORDINAL: - { - if (_version == HttpVersions.HTTP_1_0_ORDINAL) - { - keep_alive = true; - if (isResponse()) - _persistent=true; - } - break; - } - default: - { - if (connection==null) - connection=new StringBuilder(); - else - connection.append(','); - connection.append(field.getValue()); - } - } + break; + } + case HttpHeaderValues.UPGRADE_ORDINAL: + { + // special case for websocket connection ordering + if (isResponse()) + { + field.putTo(_header); + continue; + } + } + case HttpHeaderValues.CLOSE_ORDINAL: + { + close=true; + if (isResponse()) + _persistent=false; + if (!_persistent && isResponse() && _contentLength == HttpTokens.UNKNOWN_CONTENT) + _contentLength = HttpTokens.EOF_CONTENT; + break; + } + case HttpHeaderValues.KEEP_ALIVE_ORDINAL: + { + if (_version == HttpVersions.HTTP_1_0_ORDINAL) + { + keep_alive = true; + if (isResponse()) + _persistent=true; + } + break; + } + default: + { + if (connection==null) + connection=new StringBuilder(); + else + connection.append(','); + connection.append(field.getValue()); + } + } - // Do NOT add yet! - break; + // Do NOT add yet! + break; - case HttpHeaders.SERVER_ORDINAL: - if (getSendServerVersion()) - { - has_server=true; - field.putTo(_header); - } - break; + case HttpHeaders.SERVER_ORDINAL: + has_server=true; + field.putTo(_header); + break; - default: - // write the field to the header buffer - field.putTo(_header); - } - } - } + default: + // write the field to the header buffer + field.putTo(_header); + } + } + } - // Calculate how to end _content and connection, _content length and transfer encoding - // settings. - // From RFC 2616 4.4: - // 1. No body for 1xx, 204, 304 & HEAD response - // 2. Force _content-length? - // 3. If Transfer-Encoding!=identity && HTTP/1.1 && !HttpConnection==close then chunk - // 4. Content-Length - // 5. multipart/byteranges - // 6. close - switch ((int) _contentLength) - { - case HttpTokens.UNKNOWN_CONTENT: - // It may be that we have no _content, or perhaps _content just has not been - // written yet? + // Calculate how to end _content and connection, _content length and transfer encoding + // settings. + // From RFC 2616 4.4: + // 1. No body for 1xx, 204, 304 & HEAD response + // 2. Force _content-length? + // 3. If Transfer-Encoding!=identity && HTTP/1.1 && !HttpConnection==close then chunk + // 4. Content-Length + // 5. multipart/byteranges + // 6. close + switch ((int) _contentLength) + { + case HttpTokens.UNKNOWN_CONTENT: + // It may be that we have no _content, or perhaps _content just has not been + // written yet? - // Response known not to have a body - if (_contentWritten == 0 && isResponse() && (_status < 200 || _status == 204 || _status == 304)) - _contentLength = HttpTokens.NO_CONTENT; - else if (_last) - { - // we have seen all the _content there is - _contentLength = _contentWritten; - if (content_length == null && (isResponse() || _contentLength>0 || content_type ) && !_noContent) - { - // known length but not actually set. - _header.put(HttpHeaders.CONTENT_LENGTH_BUFFER); - _header.put(HttpTokens.COLON); - _header.put((byte) ' '); - BufferUtil.putDecLong(_header, _contentLength); - _header.put(HttpTokens.CRLF); - } - } - else - { - // No idea, so we must assume that a body is coming - _contentLength = (!_persistent || _version < HttpVersions.HTTP_1_1_ORDINAL ) ? HttpTokens.EOF_CONTENT : HttpTokens.CHUNKED_CONTENT; - if (isRequest() && _contentLength==HttpTokens.EOF_CONTENT) - { - _contentLength=HttpTokens.NO_CONTENT; - _noContent=true; - } - } - break; + // Response known not to have a body + if (_contentWritten == 0 && isResponse() && (_status < 200 || _status == 204 || _status == 304)) + _contentLength = HttpTokens.NO_CONTENT; + else if (_last) + { + // we have seen all the _content there is + _contentLength = _contentWritten; + if (content_length == null && (isResponse() || _contentLength>0 || content_type ) && !_noContent) + { + // known length but not actually set. + _header.put(HttpHeaders.CONTENT_LENGTH_BUFFER); + _header.put(HttpTokens.COLON); + _header.put((byte) ' '); + BufferUtil.putDecLong(_header, _contentLength); + _header.put(HttpTokens.CRLF); + } + } + else + { + // No idea, so we must assume that a body is coming + _contentLength = (!_persistent || _version < HttpVersions.HTTP_1_1_ORDINAL ) ? HttpTokens.EOF_CONTENT : HttpTokens.CHUNKED_CONTENT; + if (isRequest() && _contentLength==HttpTokens.EOF_CONTENT) + { + _contentLength=HttpTokens.NO_CONTENT; + _noContent=true; + } + } + break; - case HttpTokens.NO_CONTENT: - if (content_length == null && isResponse() && _status >= 200 && _status != 204 && _status != 304) - _header.put(CONTENT_LENGTH_0); - break; + case HttpTokens.NO_CONTENT: + if (content_length == null && isResponse() && _status >= 200 && _status != 204 && _status != 304) + _header.put(CONTENT_LENGTH_0); + break; - case HttpTokens.EOF_CONTENT: - _persistent = isRequest(); - break; + case HttpTokens.EOF_CONTENT: + _persistent = isRequest(); + break; - case HttpTokens.CHUNKED_CONTENT: - break; + case HttpTokens.CHUNKED_CONTENT: + break; - default: - // TODO - maybe allow forced chunking by setting te ??? - break; - } + default: + // TODO - maybe allow forced chunking by setting te ??? + break; + } - // Add transfer_encoding if needed - if (_contentLength == HttpTokens.CHUNKED_CONTENT) - { - // try to use user supplied encoding as it may have other values. - if (transfer_encoding != null && HttpHeaderValues.CHUNKED_ORDINAL != transfer_encoding.getValueOrdinal()) - { - String c = transfer_encoding.getValue(); - if (c.endsWith(HttpHeaderValues.CHUNKED)) - transfer_encoding.putTo(_header); - else - throw new IllegalArgumentException("BAD TE"); - } - else - _header.put(TRANSFER_ENCODING_CHUNKED); - } + // Add transfer_encoding if needed + if (_contentLength == HttpTokens.CHUNKED_CONTENT) + { + // try to use user supplied encoding as it may have other values. + if (transfer_encoding != null && HttpHeaderValues.CHUNKED_ORDINAL != transfer_encoding.getValueOrdinal()) + { + String c = transfer_encoding.getValue(); + if (c.endsWith(HttpHeaderValues.CHUNKED)) + transfer_encoding.putTo(_header); + else + throw new IllegalArgumentException("BAD TE"); + } + else + _header.put(TRANSFER_ENCODING_CHUNKED); + } - // Handle connection if need be - if (_contentLength==HttpTokens.EOF_CONTENT) - { - keep_alive=false; - _persistent=false; - } + // Handle connection if need be + if (_contentLength==HttpTokens.EOF_CONTENT) + { + keep_alive=false; + _persistent=false; + } - if (isResponse()) - { - if (!_persistent && (close || _version > HttpVersions.HTTP_1_0_ORDINAL)) - { - _header.put(CONNECTION_CLOSE); - if (connection!=null) - { - _header.setPutIndex(_header.putIndex()-2); - _header.put((byte)','); - _header.put(connection.toString().getBytes()); - _header.put(CRLF); - } - } - else if (keep_alive) - { - _header.put(CONNECTION_KEEP_ALIVE); - if (connection!=null) - { - _header.setPutIndex(_header.putIndex()-2); - _header.put((byte)','); - _header.put(connection.toString().getBytes()); - _header.put(CRLF); - } - } - else if (connection!=null) - { - _header.put(CONNECTION_); - _header.put(connection.toString().getBytes()); - _header.put(CRLF); - } - } + if (isResponse()) + { + if (!_persistent && (close || _version > HttpVersions.HTTP_1_0_ORDINAL)) + { + _header.put(CONNECTION_CLOSE); + if (connection!=null) + { + _header.setPutIndex(_header.putIndex()-2); + _header.put((byte)','); + _header.put(connection.toString().getBytes()); + _header.put(CRLF); + } + } + else if (keep_alive) + { + _header.put(CONNECTION_KEEP_ALIVE); + if (connection!=null) + { + _header.setPutIndex(_header.putIndex()-2); + _header.put((byte)','); + _header.put(connection.toString().getBytes()); + _header.put(CRLF); + } + } + else if (connection!=null) + { + _header.put(CONNECTION_); + _header.put(connection.toString().getBytes()); + _header.put(CRLF); + } + } - if (!has_server && _status>199 && getSendServerVersion()) - _header.put(SERVER); + if (!has_server && _status>199) + _header.put(SERVER); - // end the header. - _header.put(HttpTokens.CRLF); - _state = STATE_CONTENT; + // end the header. + _header.put(HttpTokens.CRLF); + _state = STATE_CONTENT; - } - catch(ArrayIndexOutOfBoundsException e) - { - throw new RuntimeException("Header>"+_header.capacity(),e); - } - } + } + catch(ArrayIndexOutOfBoundsException e) + { + throw new RuntimeException("Header>"+_header.capacity(),e); + } + } - /* ------------------------------------------------------------ */ - /** - * Complete the message. - * - * @throws IOException - */ - @Override - public void complete() throws IOException - { - if (_state == STATE_END) - return; + /* ------------------------------------------------------------ */ + /** + * Complete the message. + * + * @throws IOException + */ + @Override + public void complete() throws IOException + { + if (_state == STATE_END) + return; - super.complete(); + super.complete(); - if (_state < STATE_FLUSHING) - { - _state = STATE_FLUSHING; - if (_contentLength == HttpTokens.CHUNKED_CONTENT) - _needEOC = true; - } + if (_state < STATE_FLUSHING) + { + _state = STATE_FLUSHING; + if (_contentLength == HttpTokens.CHUNKED_CONTENT) + _needEOC = true; + } - flushBuffer(); - } + flushBuffer(); + } - /* ------------------------------------------------------------ */ - @Override - public int flushBuffer() throws IOException - { - try - { + /* ------------------------------------------------------------ */ + @Override + public int flushBuffer() throws IOException + { + try + { - if (_state == STATE_HEADER) - throw new IllegalStateException("State==HEADER"); + if (_state == STATE_HEADER) + throw new IllegalStateException("State==HEADER"); - prepareBuffers(); + prepareBuffers(); - if (_endp == null) - { - if (_needCRLF && _buffer!=null) - _buffer.put(HttpTokens.CRLF); - if (_needEOC && _buffer!=null && !_head) - _buffer.put(LAST_CHUNK); - _needCRLF=false; - _needEOC=false; - return 0; - } + if (_endp == null) + { + if (_needCRLF && _buffer!=null) + _buffer.put(HttpTokens.CRLF); + if (_needEOC && _buffer!=null && !_head) + _buffer.put(LAST_CHUNK); + _needCRLF=false; + _needEOC=false; + return 0; + } - int total= 0; + int total= 0; - int len = -1; - int to_flush = flushMask(); - int last_flush; + int len = -1; + int to_flush = flushMask(); + int last_flush; - do - { - last_flush=to_flush; - switch (to_flush) - { - case 7: - throw new IllegalStateException(); // should never happen! - case 6: - len = _endp.flush(_header, _buffer, null); - break; - case 5: - len = _endp.flush(_header, _content, null); - break; - case 4: - len = _endp.flush(_header); - break; - case 3: - len = _endp.flush(_buffer, _content, null); - break; - case 2: - len = _endp.flush(_buffer); - break; - case 1: - len = _endp.flush(_content); - break; - case 0: - { - len=0; - // Nothing more we can write now. - if (_header != null) - _header.clear(); + do + { + last_flush=to_flush; + switch (to_flush) + { + case 7: + throw new IllegalStateException(); // should never happen! + case 6: + len = _endp.flush(_header, _buffer, null); + break; + case 5: + len = _endp.flush(_header, _content, null); + break; + case 4: + len = _endp.flush(_header); + break; + case 3: + len = _endp.flush(_buffer, _content, null); + break; + case 2: + len = _endp.flush(_buffer); + break; + case 1: + len = _endp.flush(_content); + break; + case 0: + { + len=0; + // Nothing more we can write now. + if (_header != null) + _header.clear(); - _bypass = false; - _bufferChunked = false; + _bypass = false; + _bufferChunked = false; - if (_buffer != null) - { - _buffer.clear(); - if (_contentLength == HttpTokens.CHUNKED_CONTENT) - { - // reserve some space for the chunk header - _buffer.setPutIndex(CHUNK_SPACE); - _buffer.setGetIndex(CHUNK_SPACE); + if (_buffer != null) + { + _buffer.clear(); + if (_contentLength == HttpTokens.CHUNKED_CONTENT) + { + // reserve some space for the chunk header + _buffer.setPutIndex(CHUNK_SPACE); + _buffer.setGetIndex(CHUNK_SPACE); - // Special case handling for small left over buffer from - // an addContent that caused a buffer flush. - if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING) - { - _buffer.put(_content); - _content.clear(); - _content=null; - } - } - } + // Special case handling for small left over buffer from + // an addContent that caused a buffer flush. + if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING) + { + _buffer.put(_content); + _content.clear(); + _content=null; + } + } + } - // Are we completely finished for now? - if (!_needCRLF && !_needEOC && (_content==null || _content.length()==0)) - { - if (_state == STATE_FLUSHING) - _state = STATE_END; + // Are we completely finished for now? + if (!_needCRLF && !_needEOC && (_content==null || _content.length()==0)) + { + if (_state == STATE_FLUSHING) + _state = STATE_END; - if (_state==STATE_END && _persistent != null && !_persistent && _status!=100 && _method==null) - _endp.shutdownOutput(); - } - else - // Try to prepare more to write. - prepareBuffers(); - } + if (_state==STATE_END && _persistent != null && !_persistent && _status!=100 && _method==null) + _endp.shutdownOutput(); + } + else + // Try to prepare more to write. + prepareBuffers(); + } - } + } - if (len > 0) - total+=len; + if (len > 0) + total+=len; - to_flush = flushMask(); - } - // loop while progress is being made (OR we have prepared some buffers that might make progress) - while (len>0 || (to_flush!=0 && last_flush==0)); + to_flush = flushMask(); + } + // loop while progress is being made (OR we have prepared some buffers that might make progress) + while (len>0 || (to_flush!=0 && last_flush==0)); - return total; - } - catch (IOException e) - { - LOG.trace("",e); - throw (e instanceof EofException) ? e:new EofException(e); - } - } + return total; + } + catch (IOException e) + { + LOG.trace("",e); + throw (e instanceof EofException) ? e:new EofException(e); + } + } - /* ------------------------------------------------------------ */ - private int flushMask() - { - return ((_header != null && _header.length() > 0)?4:0) - | ((_buffer != null && _buffer.length() > 0)?2:0) - | ((_bypass && _content != null && _content.length() > 0)?1:0); - } + /* ------------------------------------------------------------ */ + private int flushMask() + { + return ((_header != null && _header.length() > 0)?4:0) + | ((_buffer != null && _buffer.length() > 0)?2:0) + | ((_bypass && _content != null && _content.length() > 0)?1:0); + } - /* ------------------------------------------------------------ */ - private void prepareBuffers() - { - // if we are not flushing an existing chunk - if (!_bufferChunked) - { - // Refill buffer if possible - if (!_bypass && _content != null && _content.length() > 0 && _buffer != null && _buffer.space() > 0) - { - int len = _buffer.put(_content); - _content.skip(len); - if (_content.length() == 0) - _content = null; - } + /* ------------------------------------------------------------ */ + private void prepareBuffers() + { + // if we are not flushing an existing chunk + if (!_bufferChunked) + { + // Refill buffer if possible + if (!_bypass && _content != null && _content.length() > 0 && _buffer != null && _buffer.space() > 0) + { + int len = _buffer.put(_content); + _content.skip(len); + if (_content.length() == 0) + _content = null; + } - // Chunk buffer if need be - if (_contentLength == HttpTokens.CHUNKED_CONTENT) - { - if (_bypass && (_buffer==null||_buffer.length()==0) && _content!=null) - { - // this is a bypass write - int size = _content.length(); - _bufferChunked = true; + // Chunk buffer if need be + if (_contentLength == HttpTokens.CHUNKED_CONTENT) + { + if (_bypass && (_buffer==null||_buffer.length()==0) && _content!=null) + { + // this is a bypass write + int size = _content.length(); + _bufferChunked = true; - if (_header == null) - _header = _buffers.getHeader(); + if (_header == null) + _header = _buffers.getHeader(); - // if we need CRLF add this to header - if (_needCRLF) - { - if (_header.length() > 0) throw new IllegalStateException("EOC"); - _header.put(HttpTokens.CRLF); - _needCRLF = false; - } - // Add the chunk size to the header - BufferUtil.putHexInt(_header, size); - _header.put(HttpTokens.CRLF); + // if we need CRLF add this to header + if (_needCRLF) + { + if (_header.length() > 0) throw new IllegalStateException("EOC"); + _header.put(HttpTokens.CRLF); + _needCRLF = false; + } + // Add the chunk size to the header + BufferUtil.putHexInt(_header, size); + _header.put(HttpTokens.CRLF); - // Need a CRLF after the content - _needCRLF=true; - } - else if (_buffer!=null) - { - int size = _buffer.length(); - if (size > 0) - { - // Prepare a chunk! - _bufferChunked = true; + // Need a CRLF after the content + _needCRLF=true; + } + else if (_buffer!=null) + { + int size = _buffer.length(); + if (size > 0) + { + // Prepare a chunk! + _bufferChunked = true; - // Did we leave space at the start of the buffer. - //noinspection ConstantConditions - if (_buffer.getIndex() == CHUNK_SPACE) - { - // Oh yes, goodie! let's use it then! - _buffer.poke(_buffer.getIndex() - 2, HttpTokens.CRLF, 0, 2); - _buffer.setGetIndex(_buffer.getIndex() - 2); - BufferUtil.prependHexInt(_buffer, size); + // Did we leave space at the start of the buffer. + //noinspection ConstantConditions + if (_buffer.getIndex() == CHUNK_SPACE) + { + // Oh yes, goodie! let's use it then! + _buffer.poke(_buffer.getIndex() - 2, HttpTokens.CRLF, 0, 2); + _buffer.setGetIndex(_buffer.getIndex() - 2); + BufferUtil.prependHexInt(_buffer, size); - if (_needCRLF) - { - _buffer.poke(_buffer.getIndex() - 2, HttpTokens.CRLF, 0, 2); - _buffer.setGetIndex(_buffer.getIndex() - 2); - _needCRLF = false; - } - } - else - { - // No space so lets use a header buffer. - if (_header == null) - _header = _buffers.getHeader(); + if (_needCRLF) + { + _buffer.poke(_buffer.getIndex() - 2, HttpTokens.CRLF, 0, 2); + _buffer.setGetIndex(_buffer.getIndex() - 2); + _needCRLF = false; + } + } + else + { + // No space so lets use a header buffer. + if (_header == null) + _header = _buffers.getHeader(); - if (_needCRLF) - { - if (_header.length() > 0) throw new IllegalStateException("EOC"); - _header.put(HttpTokens.CRLF); - _needCRLF = false; - } - BufferUtil.putHexInt(_header, size); - _header.put(HttpTokens.CRLF); - } + if (_needCRLF) + { + if (_header.length() > 0) throw new IllegalStateException("EOC"); + _header.put(HttpTokens.CRLF); + _needCRLF = false; + } + BufferUtil.putHexInt(_header, size); + _header.put(HttpTokens.CRLF); + } - // Add end chunk trailer. - if (_buffer.space() >= 2) - _buffer.put(HttpTokens.CRLF); - else - _needCRLF = true; - } - } + // Add end chunk trailer. + if (_buffer.space() >= 2) + _buffer.put(HttpTokens.CRLF); + else + _needCRLF = true; + } + } - // If we need EOC and everything written - if (_needEOC && (_content == null || _content.length() == 0)) - { - if (_header == null && _buffer == null) - _header = _buffers.getHeader(); + // If we need EOC and everything written + if (_needEOC && (_content == null || _content.length() == 0)) + { + if (_header == null && _buffer == null) + _header = _buffers.getHeader(); - if (_needCRLF) - { - if (_buffer == null && _header != null && _header.space() >= HttpTokens.CRLF.length) - { - _header.put(HttpTokens.CRLF); - _needCRLF = false; - } - else if (_buffer!=null && _buffer.space() >= HttpTokens.CRLF.length) - { - _buffer.put(HttpTokens.CRLF); - _needCRLF = false; - } - } + if (_needCRLF) + { + if (_buffer == null && _header != null && _header.space() >= HttpTokens.CRLF.length) + { + _header.put(HttpTokens.CRLF); + _needCRLF = false; + } + else if (_buffer!=null && _buffer.space() >= HttpTokens.CRLF.length) + { + _buffer.put(HttpTokens.CRLF); + _needCRLF = false; + } + } - if (!_needCRLF && _needEOC) - { - if (_buffer == null && _header != null && _header.space() >= LAST_CHUNK.length) - { - if (!_head) - { - _header.put(LAST_CHUNK); - _bufferChunked=true; - } - _needEOC = false; - } - else if (_buffer!=null && _buffer.space() >= LAST_CHUNK.length) - { - if (!_head) - { - _buffer.put(LAST_CHUNK); - _bufferChunked=true; - } - _needEOC = false; - } - } - } - } - } + if (!_needCRLF && _needEOC) + { + if (_buffer == null && _header != null && _header.space() >= LAST_CHUNK.length) + { + if (!_head) + { + _header.put(LAST_CHUNK); + _bufferChunked=true; + } + _needEOC = false; + } + else if (_buffer!=null && _buffer.space() >= LAST_CHUNK.length) + { + if (!_head) + { + _buffer.put(LAST_CHUNK); + _bufferChunked=true; + } + _needEOC = false; + } + } + } + } + } - if (_content != null && _content.length() == 0) - _content = null; + if (_content != null && _content.length() == 0) + _content = null; - } + } - public int getBytesBuffered() - { - return(_header==null?0:_header.length())+ - (_buffer==null?0:_buffer.length())+ - (_content==null?0:_content.length()); - } + public int getBytesBuffered() + { + return(_header==null?0:_header.length())+ + (_buffer==null?0:_buffer.length())+ + (_content==null?0:_content.length()); + } - public boolean isEmpty() - { - return (_header==null||_header.length()==0) && - (_buffer==null||_buffer.length()==0) && - (_content==null||_content.length()==0); - } + public boolean isEmpty() + { + return (_header==null||_header.length()==0) && + (_buffer==null||_buffer.length()==0) && + (_content==null||_content.length()==0); + } - @Override - public String toString() - { - Buffer header=_header; - Buffer buffer=_buffer; - Buffer content=_content; - return String.format("%s{s=%d,h=%d,b=%d,c=%d}", - getClass().getSimpleName(), - _state, - header == null ? -1 : header.length(), - buffer == null ? -1 : buffer.length(), - content == null ? -1 : content.length()); - } + @Override + public String toString() + { + Buffer header=_header; + Buffer buffer=_buffer; + Buffer content=_content; + return String.format("%s{s=%d,h=%d,b=%d,c=%d}", + getClass().getSimpleName(), + _state, + header == null ? -1 : header.length(), + buffer == null ? -1 : buffer.length(), + content == null ? -1 : content.length()); + } }
--- a/src/org/eclipse/jetty/server/AbstractHttpConnection.java Tue Oct 04 14:05:45 2016 -0600 +++ b/src/org/eclipse/jetty/server/AbstractHttpConnection.java Tue Oct 04 14:36:51 2016 -0600 @@ -160,7 +160,6 @@ _request = new Request(this); _response = new Response(this); _generator = newHttpGenerator(ab.getResponseBuffers(), endpoint); - _generator.setSendServerVersion(server.getSendServerVersion()); _server = server; } @@ -178,7 +177,6 @@ _request = request; _response = new Response(this); _generator = generator; - _generator.setSendServerVersion(server.getSendServerVersion()); _server = server; }
--- a/src/org/eclipse/jetty/server/Server.java Tue Oct 04 14:05:45 2016 -0600 +++ b/src/org/eclipse/jetty/server/Server.java Tue Oct 04 14:36:51 2016 -0600 @@ -64,7 +64,6 @@ private final AttributesMap _attributes = new AttributesMap(); public final ThreadPoolExecutor threadPool; public final Connector connector; - private boolean _sendServerVersion = true; //send Server: header private boolean _sendDateHeader = false; //send Date: header private int _graceful=0; private boolean _stopAtShutdown; @@ -302,20 +301,6 @@ } /* ------------------------------------------------------------ */ - - /* ------------------------------------------------------------ */ - public void setSendServerVersion (boolean sendServerVersion) - { - _sendServerVersion = sendServerVersion; - } - - /* ------------------------------------------------------------ */ - public boolean getSendServerVersion() - { - return _sendServerVersion; - } - - /* ------------------------------------------------------------ */ /** * @param sendDateHeader */