📄 httpparser.java
字号:
if (ch > HttpTokens.SPACE || ch<0) { _buffer.mark(); _state=STATE_FIELD2; } else if (ch < HttpTokens.SPACE) { // HTTP/0.9 _handler.startRequest(HttpMethods.CACHE.lookup(_tok0), _tok1, null); _state=STATE_END; _handler.headerComplete(); _handler.messageComplete(_contentPosition); return total_filled; } break; case STATE_FIELD2: if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) { // TODO - we really should know if we are parsing request or response! final Buffer method = HttpMethods.CACHE.lookup(_tok0); if (method==_tok0 && _tok1.length()==3 && Character.isDigit(_tok1.peek())) { _responseStatus = BufferUtil.toInt(_tok1); _handler.startResponse(HttpVersions.CACHE.lookup(_tok0), _responseStatus,_buffer.sliceFromMark()); } else _handler.startRequest(method, _tok1,HttpVersions.CACHE.lookup(_buffer.sliceFromMark())); _eol=ch; _state=STATE_HEADER; _tok0.setPutIndex(_tok0.getIndex()); _tok1.setPutIndex(_tok1.getIndex()); _multiLineValue=null; continue; // return total_filled; } break; case STATE_HEADER: switch(ch) { case HttpTokens.COLON: case HttpTokens.SPACE: case HttpTokens.TAB: { // header value without name - continuation? _length=-1; _state=STATE_HEADER_VALUE; break; } default: { // handler last header if any if (_cached!=null || _tok0.length() > 0 || _tok1.length() > 0 || _multiLineValue != null) { Buffer header=_cached!=null?_cached:HttpHeaders.CACHE.lookup(_tok0); _cached=null; Buffer value=_multiLineValue == null ? (Buffer) _tok1 : (Buffer) new ByteArrayBuffer(_multiLineValue); int ho=HttpHeaders.CACHE.getOrdinal(header); if (ho >= 0) { int vo=-1; switch (ho) { case HttpHeaders.CONTENT_LENGTH_ORDINAL: if (_contentLength != HttpTokens.CHUNKED_CONTENT) { _contentLength=BufferUtil.toLong(value); if (_contentLength <= 0) _contentLength=HttpTokens.NO_CONTENT; } break; case HttpHeaders.TRANSFER_ENCODING_ORDINAL: value=HttpHeaderValues.CACHE.lookup(value); vo=HttpHeaderValues.CACHE.getOrdinal(value); if (HttpHeaderValues.CHUNKED_ORDINAL == vo) _contentLength=HttpTokens.CHUNKED_CONTENT; else { String c=value.toString(); if (c.endsWith(HttpHeaderValues.CHUNKED)) _contentLength=HttpTokens.CHUNKED_CONTENT; else if (c.indexOf(HttpHeaderValues.CHUNKED) >= 0) throw new HttpException(400,null); } break; } } _handler.parsedHeader(header, value); _tok0.setPutIndex(_tok0.getIndex()); _tok1.setPutIndex(_tok1.getIndex()); _multiLineValue=null; } // now handle ch if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) { // End of header // work out the _content demarcation if (_contentLength == HttpTokens.UNKNOWN_CONTENT) { if (_responseStatus == 0 // request || _responseStatus == 304 // not-modified response || _responseStatus == 204 // no-content response || _responseStatus < 200) // 1xx response _contentLength=HttpTokens.NO_CONTENT; else _contentLength=HttpTokens.EOF_CONTENT; } _contentPosition=0; _eol=ch; // We convert _contentLength to an int for this switch statement because // we don't care about the amount of data available just whether there is some. switch (_contentLength > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) _contentLength) { case HttpTokens.EOF_CONTENT: _state=STATE_EOF_CONTENT; if(_body==null && _buffers!=null) _body=_buffers.getBuffer(_contentBufferSize); _handler.headerComplete(); // May recurse here ! break; case HttpTokens.CHUNKED_CONTENT: _state=STATE_CHUNKED_CONTENT; if (_body==null && _buffers!=null) _body=_buffers.getBuffer(_contentBufferSize); _handler.headerComplete(); // May recurse here ! break; case HttpTokens.NO_CONTENT: _state=STATE_END; _handler.headerComplete(); _handler.messageComplete(_contentPosition); break; default: _state=STATE_CONTENT; if(_forceContentBuffer || (_buffers!=null && _body==null && _buffer==_header && _contentLength>=(_header.capacity()-_header.getIndex()))) _body=_buffers.getBuffer(_contentBufferSize); _handler.headerComplete(); // May recurse here ! break; } return total_filled; } else { // New header _length=1; _buffer.mark(); _state=STATE_HEADER_NAME; // try cached name! if (array!=null) { _cached=HttpHeaders.CACHE.getBest(array, _buffer.markIndex(), length+1); if (_cached!=null) { _length=_cached.length(); _buffer.setGetIndex(_buffer.markIndex()+_length); length=_buffer.length(); } } } } } break; case STATE_HEADER_NAME: switch(ch) { case HttpTokens.CARRIAGE_RETURN: case HttpTokens.LINE_FEED: if (_length > 0) _tok0.update(_buffer.markIndex(), _buffer.markIndex() + _length); _eol=ch; _state=STATE_HEADER; break; case HttpTokens.COLON: if (_length > 0 && _cached==null) _tok0.update(_buffer.markIndex(), _buffer.markIndex() + _length); _length=-1; _state=STATE_HEADER_VALUE; break; case HttpTokens.SPACE: case HttpTokens.TAB: break; default: { _cached=null; if (_length == -1) _buffer.mark(); _length=_buffer.getIndex() - _buffer.markIndex(); _state=STATE_HEADER_IN_NAME; } } break; case STATE_HEADER_IN_NAME: switch(ch) { case HttpTokens.CARRIAGE_RETURN: case HttpTokens.LINE_FEED: if (_length > 0) _tok0.update(_buffer.markIndex(), _buffer.markIndex() + _length); _eol=ch; _state=STATE_HEADER; break; case HttpTokens.COLON: if (_length > 0 && _cached==null) _tok0.update(_buffer.markIndex(), _buffer.markIndex() + _length); _length=-1; _state=STATE_HEADER_VALUE; break; case HttpTokens.SPACE: case HttpTokens.TAB: _state=STATE_HEADER_NAME; break; default: { _cached=null; _length++; } } break; case STATE_HEADER_VALUE: switch(ch) { case HttpTokens.CARRIAGE_RETURN: case HttpTokens.LINE_FEED: if (_length > 0) { if (_tok1.length() == 0) _tok1.update(_buffer.markIndex(), _buffer.markIndex() + _length); else { // Continuation line! if (_multiLineValue == null) _multiLineValue=_tok1.toString(); _tok1.update(_buffer.markIndex(), _buffer.markIndex() + _length); _multiLineValue += " " + _tok1.toString(); } } _eol=ch; _state=STATE_HEADER; break; case HttpTokens.SPACE: case HttpTokens.TAB: break; default: { if (_length == -1) _buffer.mark(); _length=_buffer.getIndex() - _buffer.markIndex(); _state=STATE_HEADER_IN_VALUE; } } break; case STATE_HEADER_IN_VALUE: switch(ch) { case HttpTokens.CARRIAGE_RETURN: case HttpTokens.LINE_FEED: if (_length > 0) { if (_tok1.length() == 0) _tok1.update(_buffer.markIndex(), _buffer.markIndex() + _length); else { // Continuation line! if (_multiLineValue == null) _multiLineValue=_tok1.toString(); _tok1.update(_buffer.markIndex(), _buffer.markIndex() + _length); _multiLineValue += " " + _tok1.toString(); } } _eol=ch; _state=STATE_HEADER; break; case HttpTokens.SPACE: case HttpTokens.TAB: _state=STATE_HEADER_VALUE; break; default: _length++; } break; } } // end of HEADER states loop // ========================== // Handle _content length=_buffer.length(); if (_input!=null) _input._contentView=_contentView; Buffer chunk; while (_state > STATE_END && length > 0) { if (_eol == HttpTokens.CARRIAGE_RETURN && _buffer.peek() == HttpTokens.LINE_FEED) { _eol=_buffer.get(); length=_buffer.length(); continue; } _eol=0; switch (_state) { case STATE_EOF_CONTENT: chunk=_buffer.get(_buffer.length()); _contentPosition += chunk.length(); _contentView.update(chunk); _handler.content(chunk); // May recurse here // TODO adjust the _buffer to keep unconsumed content return total_filled; case STATE_CONTENT: { long remaining=_contentLength - _contentPosition; if (remaining == 0) { _state=STATE_END; _handler.messageComplete(_contentPosition); return total_filled; } if (length > remaining) { // We can cast reamining to an int as we know that it is smaller than // or equal to length which is already an int. length=(int)remaining; } chunk=_buffer.get(length); _contentPosition += chunk.length(); _contentView.update(chunk); _handler.content(chunk); // May recurse here if(_contentPosition == _contentLength) { _state=STATE_END; _handler.messageComplete(_contentPosition); } // TODO adjust the _buffer to keep unconsumed content return total_filled; } case STATE_CHUNKED_CONTENT: { ch=_buffer.peek(); if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED) _eol=_buffer.get(); else if (ch <= HttpTokens.SPACE) _buffer.get(); else { _chunkLength=0; _chunkPosition=0; _state=STATE_CHUNK_SIZE; } break; } case STATE_CHUNK_SIZE: { 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; } else if (ch <= HttpTokens.SPACE || ch == HttpTokens.SEMI_COLON) _state=STATE_CHUNK_PARAMS; else if (ch >= '0' && ch <= '9') _chunkLength=_chunkLength * 16 + (ch - '0');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -