📄 httpgenerator.java
字号:
//========================================================================//$Id: HttpGenerator.java,v 1.7 2005/11/25 21:17:12 gregwilkins Exp $//Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.//------------------------------------------------------------------------//Licensed under the Apache License, Version 2.0 (the "License");//you may not use this file except in compliance with the License.//You may obtain a copy of the License at //http://www.apache.org/licenses/LICENSE-2.0//Unless required by applicable law or agreed to in writing, software//distributed under the License is distributed on an "AS IS" BASIS,//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.//See the License for the specific language governing permissions and//limitations under the License.//========================================================================package org.mortbay.jetty;import java.io.IOException;import java.util.Iterator;import org.mortbay.io.Buffer;import org.mortbay.io.BufferUtil;import org.mortbay.io.Buffers;import org.mortbay.io.EndPoint;import org.mortbay.io.Portable;import org.mortbay.io.BufferCache.CachedBuffer;import org.mortbay.log.Log;/* ------------------------------------------------------------ *//** * HttpGenerator. Builds HTTP Messages. * * @author gregw * */public class HttpGenerator extends AbstractGenerator{ // common _content private static byte[] LAST_CHUNK = { (byte) '0', (byte) '\015', (byte) '\012', (byte) '\015', (byte) '\012'}; private static byte[] CONTENT_LENGTH_0 = Portable.getBytes("Content-Length: 0\015\012"); private static byte[] CONNECTION_KEEP_ALIVE = Portable.getBytes("Connection: keep-alive\015\012"); private static byte[] CONNECTION_CLOSE = Portable.getBytes("Connection: close\015\012"); private static byte[] CONNECTION_ = Portable.getBytes("Connection: "); private static byte[] CRLF = Portable.getBytes("\015\012"); private static byte[] TRANSFER_ENCODING_CHUNKED = Portable.getBytes("Transfer-Encoding: chunked\015\012"); private static byte[] SERVER = Portable.getBytes("Server: Jetty(6.0.x)\015\012"); // other statics private static int CHUNK_SPACE = 12; public static void setServerVersion(String version) { SERVER=Portable.getBytes("Server: Jetty("+version+")\015\012"); } // data private 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 headerBufferSize Size of the buffer to allocate for HTTP header * @param contentBufferSize Size of the buffer to allocate for HTTP content */ public HttpGenerator(Buffers buffers, EndPoint io, int headerBufferSize, int contentBufferSize) { super(buffers,io,headerBufferSize,contentBufferSize); } /* ------------------------------------------------------------------------------- */ public void reset(boolean returnBuffers) { super.reset(returnBuffers); _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"); if (_last || _state==STATE_END) { Log.debug("Ignoring extra content {}",content); content.clear(); return; } _last = last; // Handle any unfinished business? if (_content!=null && _content.length()>0 || _bufferChunked) { if (!_endp.isOpen()) throw new EofException(); flush(); if (_content != null && _content.length()>0 || _bufferChunked) throw new IllegalStateException("FULL"); } _content = content; _contentWritten += content.length(); // Handle the _content if (_head) { content.clear(); _content=null; } else if (_endp != null && _buffer == null && content.length() > 0 && _last) { // TODO - use bypass in more cases. // Make _content a direct buffer _bypass = true; } else { // Yes - so we better check we have a buffer if (_buffer == null) _buffer = _buffers.getBuffer(_contentBufferSize); // 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(); _last = true; _content = response; _bypass = true; _state = STATE_FLUSHING; // TODO this is not exactly right, but should do. _contentLength =_contentWritten = response.length(); } /* ------------------------------------------------------------ */ /** * Add content. * * @param b byte * @return true if the buffers are full * @throws IOException */ public boolean addContent(byte b) throws IOException { if (_noContent) throw new IllegalStateException("NO CONTENT"); if (_last || _state==STATE_END) { Log.debug("Ignoring extra content {}",new Byte(b)); return false; } // Handle any unfinished business? if (_content != null && _content.length()>0 || _bufferChunked) { flush(); if (_content != null && _content.length()>0 || _bufferChunked) throw new IllegalStateException("FULL"); } _contentWritten++; // Handle the _content if (_head) return false; // we better check we have a buffer if (_buffer == null) _buffer = _buffers.getBuffer(_contentBufferSize); // Copy _content to buffer; _buffer.put(b); return _buffer.space()<=(_contentLength == HttpTokens.CHUNKED_CONTENT?CHUNK_SPACE:0); } /* ------------------------------------------------------------ */ /** Prepare buffer for unchecked writes. * Prepare the generator buffer to receive unchecked writes * @return the available space in the buffer. * @throws IOException */ protected int prepareUncheckedAddContent() throws IOException { if (_noContent) return -1; if (_last || _state==STATE_END) return -1; // Handle any unfinished business? Buffer content = _content; if (content != null && content.length()>0 || _bufferChunked) { flush(); if (content != null && content.length()>0 || _bufferChunked) throw new IllegalStateException("FULL"); } // we better check we have a buffer if (_buffer == null) _buffer = _buffers.getBuffer(_contentBufferSize); _contentWritten-=_buffer.length(); // Handle the _content if (_head) return Integer.MAX_VALUE; return _buffer.space()-(_contentLength == HttpTokens.CHUNKED_CONTENT?CHUNK_SPACE:0); } /* ------------------------------------------------------------ */ public boolean isBufferFull() { // Should we flush the buffers? boolean full = super.isBufferFull() || _bufferChunked || _bypass || (_contentLength == HttpTokens.CHUNKED_CONTENT && _buffer != null && _buffer.space() < CHUNK_SPACE); return full; } /* ------------------------------------------------------------ */ public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException { if (_state != STATE_HEADER) return; // handle a reset if (_method==null && _status==0) throw new EofException(); if (_last && !allContentAdded) throw new IllegalStateException("last?"); _last = _last | allContentAdded; // get a header buffer if (_header == null) _header = _buffers.getBuffer(_headerBufferSize); boolean has_server = false; if (_method!=null) { _close = false; // Request if (_version == HttpVersions.HTTP_0_9_ORDINAL) { _contentLength = HttpTokens.NO_CONTENT; _header.put(_method); _header.put((byte)' '); _header.put(_uri.getBytes("utf-8")); // TODO WRONG! _header.put(HttpTokens.CRLF); _state = STATE_FLUSHING; _noContent=true; return; } else { _header.put(_method); _header.put((byte)' '); _header.put(_uri.getBytes("utf-8")); // TODO WRONG! _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); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -