📄 httpparser.java
字号:
else if (ch >= 'a' && ch <= 'f') _chunkLength=_chunkLength * 16 + (10 + ch - 'a'); else if (ch >= 'A' && ch <= 'F') _chunkLength=_chunkLength * 16 + (10 + ch - 'A'); else throw new IOException("bad chunk char: " + ch); break; } case STATE_CHUNK_PARAMS: { ch=_buffer.get(); if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) { _eol=ch; if (_chunkLength == 0) { _state=STATE_END; _handler.messageComplete(_contentPosition); return total_filled; } else _state=STATE_CHUNK; } break; } case STATE_CHUNK: { int remaining=_chunkLength - _chunkPosition; if (remaining == 0) { _state=STATE_CHUNKED_CONTENT; break; } else if (length > remaining) length=remaining; chunk=_buffer.get(length); _contentPosition += chunk.length(); _chunkPosition += chunk.length(); _contentView.update(chunk); _handler.content(chunk); // May recurse here // TODO adjust the _buffer to keep unconsumed content return total_filled; } } length=_buffer.length(); } return total_filled; } /* ------------------------------------------------------------------------------- */ /** fill the buffers from the endpoint * */ public long fill() throws IOException { if (_buffer==null) { _buffer=_header=getHeaderBuffer(); _tok0=new View.CaseInsensitive(_buffer); _tok1=new View.CaseInsensitive(_buffer); } if (_body!=null && _buffer!=_body) _buffer=_body; if (_buffer == _body) _buffer.compact(); int space=_buffer.space(); // Fill buffer if we can if (space == 0) throw new HttpException(HttpStatus.ORDINAL_413_Request_Entity_Too_Large, "FULL "+(_buffer==_body?"body":"head")); else { int filled=-1; if (_endp != null ) { try { filled=_endp.fill(_buffer); } catch(IOException e) { Log.debug(e); reset(true); throw (e instanceof EofException) ? e:new EofException(e); } } return filled; } } /* ------------------------------------------------------------------------------- */ /** Skip any CRLFs in buffers * */ public void skipCRLF() { while (_header!=null && _header.length()>0) { byte ch = _header.peek(); if (ch==HttpTokens.CARRIAGE_RETURN || ch==HttpTokens.LINE_FEED) { _eol=ch; _header.skip(1); } else break; } while (_body!=null && _body.length()>0) { byte ch = _body.peek(); if (ch==HttpTokens.CARRIAGE_RETURN || ch==HttpTokens.LINE_FEED) { _eol=ch; _body.skip(1); } else break; } } /* ------------------------------------------------------------------------------- */ public void reset(boolean returnBuffers) { synchronized (this) { if (_input!=null && _contentView.length()>0) _input._contentView=_contentView.duplicate(Buffer.READWRITE); _state=STATE_START; _contentLength=HttpTokens.UNKNOWN_CONTENT; _contentPosition=0; _length=0; _responseStatus=0; if (_buffer!=null && _buffer.length()>0 && _eol == HttpTokens.CARRIAGE_RETURN && _buffer.peek() == HttpTokens.LINE_FEED) { _buffer.skip(1); _eol=HttpTokens.LINE_FEED; } if (_body!=null) { if (_body.hasContent()) { _header.setMarkIndex(-1); _header.compact(); // TODO if pipelined requests received after big input - maybe this is not good?. _body.skip(_header.put(_body)); } if (_body.length()==0) { if (_buffers!=null && returnBuffers) _buffers.returnBuffer(_body); _body=null; } else { _body.setMarkIndex(-1); _body.compact(); } } if (_header!=null) { _header.setMarkIndex(-1); if (!_header.hasContent() && _buffers!=null && returnBuffers) { _buffers.returnBuffer(_header); _header=null; _buffer=null; } else { _header.compact(); _tok0.update(_header); _tok0.update(0,0); _tok1.update(_header); _tok1.update(0,0); } } _buffer=_header; } } /* ------------------------------------------------------------------------------- */ 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(); } /* ------------------------------------------------------------------------------- */ public String toString() { return "state=" + _state + " length=" + _length + " len=" + _contentLength; } /* ------------------------------------------------------------ */ public Buffer getHeaderBuffer() { if (_header == null) { _header=_buffers.getBuffer(_headerBufferSize); } 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 static abstract class EventHandler { public abstract void content(Buffer ref) throws IOException; public void headerComplete() 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 { } /** * This is the method called by parser when the HTTP request line is parsed */ 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 static class Input extends ServletInputStream { protected HttpParser _parser; protected EndPoint _endp; protected long _maxIdleTime; protected Buffer _contentView; /* ------------------------------------------------------------ */ public Input(HttpParser parser, long maxIdleTime) { _parser=parser; _endp=parser._endp; _maxIdleTime=maxIdleTime; _contentView=_parser._contentView; _parser._input=this; } /* ------------------------------------------------------------ */ /* * @see java.io.InputStream#read() */ public int read() throws IOException { int c=-1; if (blockForContent()) c= 0xff & _contentView.get(); return c; } /* ------------------------------------------------------------ */ /* * @see java.io.InputStream#read(byte[], int, int) */ public int read(byte[] b, int off, int len) throws IOException { int l=-1; if (blockForContent()) l= _contentView.get(b, off, len); return l; } /* ------------------------------------------------------------ */ private boolean blockForContent() throws IOException { if (_contentView.length()>0) return true; if (_parser.getState() <= HttpParser.STATE_END) return false; // Handle simple end points. if (_endp==null) _parser.parseNext(); // Handle blocking end points else if (_endp.isBlocking()) { try { _parser.parseNext(); // parse until some progress is made (or IOException thrown for timeout) while(_contentView.length() == 0 && !_parser.isState(HttpParser.STATE_END)) { // Try to get more _parser._content _parser.parseNext(); } } catch(IOException e) { _endp.close(); throw e; } } else // Handle non-blocking end point { _parser.parseNext(); // parse until some progress is made (or IOException thrown for timeout) while(_contentView.length() == 0 && !_parser.isState(HttpParser.STATE_END)) { if (!_endp.blockReadable(_maxIdleTime)) { _endp.close(); throw new EofException("timeout"); } // Try to get more _parser._content _parser.parseNext(); } } return _contentView.length()>0; } /* ------------------------------------------------------------ */ /* (non-Javadoc) * @see java.io.InputStream#available() */ public int available() throws IOException { if (_contentView!=null && _contentView.length()>0) return _contentView.length(); if (!_endp.isBlocking()) _parser.parseNext(); return _contentView==null?0:_contentView.length(); } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -