@Test public void test204() throws Exception { ByteBuffer header = BufferUtils.allocate(8096); ByteBuffer content = BufferUtils.toBuffer("0123456789"); HttpGenerator gen = new HttpGenerator(); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 204, "Foo", new HttpFields(), 10); info.getFields().add("Content-Type", "test/data"); info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); HttpGenerator.Result result = gen.generateResponse(info, header, null, content, true); assertEquals(gen.isNoContent(), true); assertEquals(HttpGenerator.Result.FLUSH, result); assertEquals(HttpGenerator.State.COMPLETING, gen.getState()); String responseheaders = BufferUtils.toString(header); BufferUtils.clear(header); result = gen.generateResponse(null, null, null, content, false); assertEquals(HttpGenerator.Result.DONE, result); assertEquals(HttpGenerator.State.END, gen.getState()); assertThat(responseheaders, containsString("HTTP/1.1 204 Foo")); assertThat(responseheaders, containsString("Last-Modified: Thu, 01 Jan 1970 00:00:00 GMT")); assertThat(responseheaders, not(containsString("Content-Length: 10"))); // Note: the HttpConnection.process() method is responsible for actually // excluding the content from the response based on // generator.isNoContent()==true }
@Test public void testResponseUpgrade() throws Exception { ByteBuffer header = BufferUtils.allocate(8096); HttpGenerator gen = new HttpGenerator(); HttpGenerator.Result result = gen.generateResponse(null, null, null, null, true); assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 101, null, new HttpFields(), -1); info.getFields().add("Upgrade", "WebSocket"); info.getFields().add("Connection", "Upgrade"); info.getFields().add("Sec-WebSocket-Accept", "123456789=="); result = gen.generateResponse(info, header, null, null, true); assertEquals(HttpGenerator.Result.FLUSH, result); assertEquals(HttpGenerator.State.COMPLETING, gen.getState()); String head = BufferUtils.toString(header); BufferUtils.clear(header); result = gen.generateResponse(info, null, null, null, false); assertEquals(HttpGenerator.Result.DONE, result); assertEquals(HttpGenerator.State.END, gen.getState()); assertEquals(0, gen.getContentPrepared()); assertThat(head, startsWith("HTTP/1.1 101 Switching Protocols")); assertThat(head, containsString("Upgrade: WebSocket\r\n")); assertThat(head, containsString("Connection: Upgrade\r\n")); }
@Test public void testCachedPut() throws Exception { HttpFields header = new HttpFields(); header.put("Connection", "Keep-Alive"); header.put("tRansfer-EncOding", "CHUNKED"); header.put("CONTENT-ENCODING", "gZIP"); ByteBuffer buffer = BufferUtils.allocate(1024); BufferUtils.flipToFill(buffer); HttpGenerator.putTo(header, buffer); BufferUtils.flipToFlush(buffer, 0); String out = BufferUtils.toString(buffer).toLowerCase(); Assert.assertThat( out, Matchers.containsString( (HttpHeader.CONNECTION + ": " + HttpHeaderValue.KEEP_ALIVE).toLowerCase())); Assert.assertThat( out, Matchers.containsString( (HttpHeader.TRANSFER_ENCODING + ": " + HttpHeaderValue.CHUNKED).toLowerCase())); Assert.assertThat( out, Matchers.containsString( (HttpHeader.CONTENT_ENCODING + ": " + HttpHeaderValue.GZIP).toLowerCase())); }
@Test public void testResponseNoContent() throws Exception { ByteBuffer header = BufferUtils.allocate(8096); HttpGenerator gen = new HttpGenerator(); HttpGenerator.Result result = gen.generateResponse(null, null, null, null, true); assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), -1); info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); result = gen.generateResponse(info, null, null, null, true); assertEquals(HttpGenerator.Result.NEED_HEADER, result); result = gen.generateResponse(info, header, null, null, true); assertEquals(HttpGenerator.Result.FLUSH, result); assertEquals(HttpGenerator.State.COMPLETING, gen.getState()); String head = BufferUtils.toString(header); BufferUtils.clear(header); result = gen.generateResponse(null, null, null, null, false); assertEquals(HttpGenerator.Result.DONE, result); assertEquals(HttpGenerator.State.END, gen.getState()); assertEquals(0, gen.getContentPrepared()); assertThat(head, containsString("HTTP/1.1 200 OK")); assertThat(head, containsString("Last-Modified: Thu, 01 Jan 1970 00:00:00 GMT")); assertThat(head, containsString("Content-Length: 0")); }
@Test public void testConnectionKeepAliveWithAdditionalCustomValue() throws Exception { HttpGenerator generator = new HttpGenerator(); HttpFields fields = new HttpFields(); fields.put(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE); String customValue = "test"; fields.add(HttpHeader.CONNECTION, customValue); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_0, 200, "OK", fields, -1); ByteBuffer header = BufferUtils.allocate(4096); HttpGenerator.Result result = generator.generateResponse(info, header, null, null, true); Assert.assertSame(HttpGenerator.Result.FLUSH, result); String headers = BufferUtils.toString(header); Assert.assertTrue(headers.contains(HttpHeaderValue.KEEP_ALIVE.asString())); Assert.assertTrue(headers.contains(customValue)); }
private IllegalCharacterException(State state, byte ch, ByteBuffer buffer) { super(400, String.format("Illegal character 0x%X", ch)); // Bug #460642 - don't reveal buffers to end user log.warn( String.format( "Illegal character 0x%X in state=%s for buffer %s", ch, state, BufferUtils.toDetailString(buffer))); }
@Test public void testCRLF() throws Exception { HttpFields header = new HttpFields(); header.put("name0", "value\r\n0"); header.put("name\r\n1", "value1"); header.put("name:2", "value:\r\n2"); ByteBuffer buffer = BufferUtils.allocate(1024); BufferUtils.flipToFill(buffer); HttpGenerator.putTo(header, buffer); BufferUtils.flipToFlush(buffer, 0); String out = BufferUtils.toString(buffer); assertThat(out, containsString("name0: value 0")); assertThat(out, containsString("name??1: value1")); assertThat(out, containsString("name?2: value: 2")); }
@Test public void testResponseWithKnownContent() throws Exception { ByteBuffer header = BufferUtils.allocate(4096); ByteBuffer content0 = BufferUtils.toBuffer("Hello World! "); ByteBuffer content1 = BufferUtils.toBuffer("The quick brown fox jumped over the lazy dog. "); HttpGenerator gen = new HttpGenerator(); HttpGenerator.Result result = gen.generateResponse(null, null, null, content0, false); assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), 59); info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); result = gen.generateResponse(info, null, null, content0, false); assertEquals(HttpGenerator.Result.NEED_HEADER, result); assertEquals(HttpGenerator.State.START, gen.getState()); result = gen.generateResponse(info, header, null, content0, false); assertEquals(HttpGenerator.Result.FLUSH, result); assertEquals(HttpGenerator.State.COMMITTED, gen.getState()); String out = BufferUtils.toString(header); BufferUtils.clear(header); out += BufferUtils.toString(content0); BufferUtils.clear(content0); result = gen.generateResponse(null, null, null, content1, false); assertEquals(HttpGenerator.Result.FLUSH, result); assertEquals(HttpGenerator.State.COMMITTED, gen.getState()); out += BufferUtils.toString(content1); BufferUtils.clear(content1); result = gen.generateResponse(null, null, null, null, true); assertEquals(HttpGenerator.Result.CONTINUE, result); assertEquals(HttpGenerator.State.COMPLETING, gen.getState()); result = gen.generateResponse(null, null, null, null, true); assertEquals(HttpGenerator.Result.DONE, result); assertEquals(HttpGenerator.State.END, gen.getState()); assertThat(out, containsString("HTTP/1.1 200 OK")); assertThat(out, containsString("Last-Modified: Thu, 01 Jan 1970 00:00:00 GMT")); assertThat(out, not(containsString("chunked"))); assertThat(out, containsString("Content-Length: 59")); assertThat( out, containsString("\r\n\r\nHello World! The quick brown fox jumped over the lazy dog. ")); }
@Test public void testPutTo() throws Exception { HttpFields header = new HttpFields(); header.put("name0", "value0"); header.put("name1", "value:A"); header.add("name1", "value:B"); header.add("name2", ""); ByteBuffer buffer = BufferUtils.allocate(1024); BufferUtils.flipToFill(buffer); HttpGenerator.putTo(header, buffer); BufferUtils.flipToFlush(buffer, 0); String result = BufferUtils.toString(buffer); assertThat(result, Matchers.containsString("name0: value0")); assertThat(result, Matchers.containsString("name1: value:A")); assertThat(result, Matchers.containsString("name1: value:B")); }
@Test public void testSendServerXPoweredBy() throws Exception { ByteBuffer header = BufferUtils.allocate(8096); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), -1); HttpFields fields = new HttpFields(); fields.add(HttpHeader.SERVER, "SomeServer"); fields.add(HttpHeader.X_POWERED_BY, "SomePower"); MetaData.Response infoF = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); String head; HttpGenerator gen = new HttpGenerator(true, true); gen.generateResponse(info, header, null, null, true); head = BufferUtils.toString(header); BufferUtils.clear(header); assertThat(head, containsString("HTTP/1.1 200 OK")); assertThat(head, containsString("Server: Firefly 3.0")); assertThat(head, containsString("X-Powered-By: Firefly 3.0")); gen.reset(); gen.generateResponse(infoF, header, null, null, true); head = BufferUtils.toString(header); BufferUtils.clear(header); assertThat(head, containsString("HTTP/1.1 200 OK")); assertThat(head, not(containsString("Server: Firefly 3.0"))); assertThat(head, containsString("Server: SomeServer")); assertThat(head, containsString("X-Powered-By: Firefly 3.0")); assertThat(head, containsString("X-Powered-By: SomePower")); gen.reset(); gen = new HttpGenerator(false, false); gen.generateResponse(info, header, null, null, true); head = BufferUtils.toString(header); BufferUtils.clear(header); assertThat(head, containsString("HTTP/1.1 200 OK")); assertThat(head, not(containsString("Server: Firefly 3.0"))); assertThat(head, not(containsString("X-Powered-By: Firefly 3.0"))); gen.reset(); gen.generateResponse(infoF, header, null, null, true); head = BufferUtils.toString(header); BufferUtils.clear(header); assertThat(head, containsString("HTTP/1.1 200 OK")); assertThat(head, not(containsString("Server: Firefly 3.0"))); assertThat(head, containsString("Server: SomeServer")); assertThat(head, not(containsString("X-Powered-By: Firefly 3.0"))); assertThat(head, containsString("X-Powered-By: SomePower")); gen.reset(); }
@Test public void test101SwitchingProtocolsResponse() throws Exception { MetaData.Response switchingProtocolsResponse = new MetaData.Response(HttpVersion.HTTP_1_1, 101, new HttpFields()); switchingProtocolsResponse.getFields().put(HttpHeader.CONNECTION, HttpHeaderValue.UPGRADE); switchingProtocolsResponse.getFields().put(HttpHeader.UPGRADE, "h2c"); ByteBuffer header = BufferUtils.allocate(4096); HttpGenerator gen = new HttpGenerator(); HttpGenerator.Result result = gen.generateResponse(switchingProtocolsResponse, header, null, null, true); System.out.println(result + "|" + gen.getState()); assertEquals(HttpGenerator.Result.FLUSH, result); assertEquals(HttpGenerator.State.COMPLETING, gen.getState()); result = gen.generateResponse(null, null, null, null, true); System.out.println(result + "|" + gen.getState()); assertEquals(HttpGenerator.Result.DONE, result); assertEquals(HttpGenerator.State.END, gen.getState()); System.out.println(BufferUtils.toString(header)); }
@Test public void testComplexChars() throws Exception { ByteBuffer header = BufferUtils.allocate(8096); ByteBuffer content = BufferUtils.toBuffer("0123456789"); HttpGenerator gen = new HttpGenerator(); HttpGenerator.Result result = gen.generateResponse(null, null, null, content, true); assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), 10); info.getFields().add("Content-Type", "test/data;\r\nextra=value"); info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); result = gen.generateResponse(info, null, null, content, true); assertEquals(HttpGenerator.Result.NEED_HEADER, result); result = gen.generateResponse(info, header, null, content, true); assertEquals(HttpGenerator.Result.FLUSH, result); assertEquals(HttpGenerator.State.COMPLETING, gen.getState()); String response = BufferUtils.toString(header); BufferUtils.clear(header); response += BufferUtils.toString(content); BufferUtils.clear(content); result = gen.generateResponse(null, null, null, content, false); assertEquals(HttpGenerator.Result.DONE, result); assertEquals(HttpGenerator.State.END, gen.getState()); assertEquals(10, gen.getContentPrepared()); assertThat(response, containsString("HTTP/1.1 200 OK")); assertThat(response, containsString("Last-Modified: Thu, 01 Jan 1970 00:00:00 GMT")); assertThat(response, containsString("Content-Type: test/data; extra=value")); assertThat(response, containsString("Content-Length: 10")); assertThat(response, containsString("\r\n0123456789")); }
/* * Parse the message headers and return true if the handler has signaled for * a return */ protected boolean parseHeaders(ByteBuffer buffer) { boolean handle = false; // Process headers while (_state.ordinal() < State.CONTENT.ordinal() && buffer.hasRemaining() && !handle) { // process each character byte ch = next(buffer); if (ch == 0) break; if (_maxHeaderBytes > 0 && ++_headerBytes > _maxHeaderBytes) { log.warn("Header is too large > {}", _maxHeaderBytes); throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413); } switch (_state) { case HEADER: switch (ch) { case HttpTokens.COLON: case HttpTokens.SPACE: case HttpTokens.TAB: throw new BadMessageException(HttpStatus.BAD_REQUEST_400, "Bad Continuation"); case HttpTokens.LINE_FEED: { _contentPosition = 0; // End of headers! // Was there a required host header? if (!_host && _version == HttpVersion.HTTP_1_1 && _requestHandler != null) { throw new BadMessageException(HttpStatus.BAD_REQUEST_400, "No Host"); } // is it a response that cannot have a body? if (_responseHandler != null && // response (_responseStatus == 304 || // not-modified response _responseStatus == 204 || // no-content // response _responseStatus < 200)) // 1xx response _endOfContent = EndOfContent.NO_CONTENT; // ignore any // other // headers // set // else if we don't know framing else if (_endOfContent == EndOfContent.UNKNOWN_CONTENT) { if (_responseStatus == 0 // request || _responseStatus == 304 // not-modified // response || _responseStatus == 204 // no-content response || _responseStatus < 200) // 1xx response _endOfContent = EndOfContent.NO_CONTENT; else _endOfContent = EndOfContent.EOF_CONTENT; } // How is the message ended? switch (_endOfContent) { case EOF_CONTENT: setState(State.EOF_CONTENT); handle = _handler.headerComplete() || handle; return handle; case CHUNKED_CONTENT: setState(State.CHUNKED_CONTENT); handle = _handler.headerComplete() || handle; return handle; case NO_CONTENT: handle = _handler.headerComplete() || handle; setState(State.END); handle = _handler.messageComplete() || handle; return handle; default: setState(State.CONTENT); handle = _handler.headerComplete() || handle; return handle; } } default: { // now handle the ch if (ch <= HttpTokens.SPACE) throw new BadMessageException(); if (buffer.hasRemaining()) { // Try a look ahead for the known header name and value. HttpField field = _connectionFields == null ? null : _connectionFields.getBest(buffer, -1, buffer.remaining()); if (field == null) field = CACHE.getBest(buffer, -1, buffer.remaining()); if (field != null) { final String n; final String v; if (_strict) { // Have to get the fields exactly from the // buffer to match case String fn = field.getName(); String fv = field.getValue(); n = BufferUtils.toString( buffer, buffer.position() - 1, fn.length(), StandardCharsets.US_ASCII); if (fv == null) v = null; else { v = BufferUtils.toString( buffer, buffer.position() + fn.length() + 1, fv.length(), StandardCharsets.ISO_8859_1); field = new HttpField(field.getHeader(), n, v); } } else { n = field.getName(); v = field.getValue(); } _header = field.getHeader(); _headerString = n; if (v == null) { // Header only setState(State.HEADER_VALUE); _string.setLength(0); _length = 0; buffer.position(buffer.position() + n.length() + 1); break; } else { // Header and value int pos = buffer.position() + n.length() + v.length() + 1; byte b = buffer.get(pos); if (b == HttpTokens.CARRIAGE_RETURN || b == HttpTokens.LINE_FEED) { _field = field; _valueString = v; setState(State.HEADER_IN_VALUE); if (b == HttpTokens.CARRIAGE_RETURN) { _cr = true; buffer.position(pos + 1); } else buffer.position(pos); break; } else { setState(State.HEADER_IN_VALUE); setString(v); buffer.position(pos); break; } } } } // New header setState(State.HEADER_IN_NAME); _string.setLength(0); _string.append((char) ch); _length = 1; } } break; case HEADER_IN_NAME: if (ch == HttpTokens.COLON) { if (_headerString == null) { _headerString = takeString(); _header = HttpHeader.CACHE.get(_headerString); } _length = -1; setState(State.HEADER_VALUE); break; } if (ch > HttpTokens.SPACE) { if (_header != null) { setString(_header.asString()); _header = null; _headerString = null; } _string.append((char) ch); if (ch > HttpTokens.SPACE) _length = _string.length(); break; } throw new IllegalCharacterException(_state, ch, buffer); case HEADER_VALUE: if (ch > HttpTokens.SPACE || ch < 0) { _string.append((char) (0xff & ch)); _length = _string.length(); setState(State.HEADER_IN_VALUE); break; } if (ch == HttpTokens.SPACE || ch == HttpTokens.TAB) break; if (ch == HttpTokens.LINE_FEED) { _value = null; _string.setLength(0); _valueString = null; _length = -1; parsedHeader(); setState(State.HEADER); break; } throw new IllegalCharacterException(_state, ch, buffer); case HEADER_IN_VALUE: if (ch >= HttpTokens.SPACE || ch < 0 || ch == HttpTokens.TAB) { if (_valueString != null) { setString(_valueString); _valueString = null; _field = null; } _string.append((char) (0xff & ch)); if (ch > HttpTokens.SPACE || ch < 0) _length = _string.length(); break; } if (ch == HttpTokens.LINE_FEED) { if (_length > 0) { _value = null; _valueString = takeString(); _length = -1; } parsedHeader(); setState(State.HEADER); break; } throw new IllegalCharacterException(_state, ch, buffer); default: throw new IllegalStateException(_state.toString()); } } return handle; }
protected boolean parseContent(ByteBuffer buffer) { int remaining = buffer.remaining(); if (remaining == 0 && _state == State.CONTENT) { long content = _contentLength - _contentPosition; if (content == 0) { setState(State.END); return _handler.messageComplete(); } } // Handle _content byte ch; while (_state.ordinal() < State.END.ordinal() && remaining > 0) { switch (_state) { case EOF_CONTENT: _contentChunk = buffer.asReadOnlyBuffer(); _contentPosition += remaining; buffer.position(buffer.position() + remaining); if (_handler.content(_contentChunk)) return true; break; case CONTENT: { long content = _contentLength - _contentPosition; if (content == 0) { setState(State.END); return _handler.messageComplete(); } else { _contentChunk = buffer.asReadOnlyBuffer(); // limit content by expected size if (remaining > content) { // We can cast remaining to an int as we know that it is // smaller than // or equal to length which is already an int. _contentChunk.limit(_contentChunk.position() + (int) content); } _contentPosition += _contentChunk.remaining(); buffer.position(buffer.position() + _contentChunk.remaining()); if (_handler.content(_contentChunk)) return true; if (_contentPosition == _contentLength) { setState(State.END); return _handler.messageComplete(); } } break; } case CHUNKED_CONTENT: { ch = next(buffer); if (ch > HttpTokens.SPACE) { _chunkLength = TypeUtils.convertHexDigit(ch); _chunkPosition = 0; setState(State.CHUNK_SIZE); } break; } case CHUNK_SIZE: { ch = next(buffer); if (ch == 0) break; if (ch == HttpTokens.LINE_FEED) { if (_chunkLength == 0) setState(State.CHUNK_END); else setState(State.CHUNK); } else if (ch <= HttpTokens.SPACE || ch == HttpTokens.SEMI_COLON) setState(State.CHUNK_PARAMS); else _chunkLength = _chunkLength * 16 + TypeUtils.convertHexDigit(ch); break; } case CHUNK_PARAMS: { ch = next(buffer); if (ch == HttpTokens.LINE_FEED) { if (_chunkLength == 0) setState(State.CHUNK_END); else setState(State.CHUNK); } break; } case CHUNK: { int chunk = _chunkLength - _chunkPosition; if (chunk == 0) { setState(State.CHUNKED_CONTENT); } else { _contentChunk = buffer.asReadOnlyBuffer(); if (remaining > chunk) _contentChunk.limit(_contentChunk.position() + chunk); chunk = _contentChunk.remaining(); _contentPosition += chunk; _chunkPosition += chunk; buffer.position(buffer.position() + chunk); if (_handler.content(_contentChunk)) return true; } break; } case CHUNK_END: { // TODO handle chunk trailer ch = next(buffer); if (ch == 0) break; if (ch == HttpTokens.LINE_FEED) { setState(State.END); return _handler.messageComplete(); } throw new IllegalCharacterException(_state, ch, buffer); } case CLOSED: { BufferUtils.clear(buffer); return false; } default: break; } remaining = buffer.remaining(); } return false; }
/** * Parse until next Event. * * @param buffer the buffer to parse * @return True if an {@link RequestHandler} method was called and it returned true; */ public boolean parseNext(ByteBuffer buffer) { if (DEBUG) log.debug("parseNext s={} {}", _state, BufferUtils.toDetailString(buffer)); try { // Start a request/response if (_state == State.START) { _version = null; _method = null; _methodString = null; _endOfContent = EndOfContent.UNKNOWN_CONTENT; _header = null; if (quickStart(buffer)) return true; } // Request/response line if (_state.ordinal() >= State.START.ordinal() && _state.ordinal() < State.HEADER.ordinal()) { if (parseLine(buffer)) return true; } // parse headers if (_state.ordinal() >= State.HEADER.ordinal() && _state.ordinal() < State.CONTENT.ordinal()) { if (parseHeaders(buffer)) return true; } // parse content if (_state.ordinal() >= State.CONTENT.ordinal() && _state.ordinal() < State.END.ordinal()) { // Handle HEAD response if (_responseStatus > 0 && _headResponse) { setState(State.END); return _handler.messageComplete(); } else { if (parseContent(buffer)) return true; } } // handle end states if (_state == State.END) { // eat white space while (buffer.remaining() > 0 && buffer.get(buffer.position()) <= HttpTokens.SPACE) buffer.get(); } else if (_state == State.CLOSE) { // Seeking EOF if (BufferUtils.hasContent(buffer)) { // Just ignore data when closed _headerBytes += buffer.remaining(); BufferUtils.clear(buffer); if (_maxHeaderBytes > 0 && _headerBytes > _maxHeaderBytes) { // Don't want to waste time reading data of a closed // request throw new IllegalStateException("too much data seeking EOF"); } } } else if (_state == State.CLOSED) { BufferUtils.clear(buffer); } // Handle EOF if (_eof && !buffer.hasRemaining()) { switch (_state) { case CLOSED: break; case START: setState(State.CLOSED); _handler.earlyEOF(); break; case END: case CLOSE: setState(State.CLOSED); break; case EOF_CONTENT: setState(State.CLOSED); return _handler.messageComplete(); case CONTENT: case CHUNKED_CONTENT: case CHUNK_SIZE: case CHUNK_PARAMS: case CHUNK: setState(State.CLOSED); _handler.earlyEOF(); break; default: if (DEBUG) log.debug("{} EOF in {}", this, _state); setState(State.CLOSED); _handler.badMessage(400, null); break; } } } catch (BadMessageException e) { BufferUtils.clear(buffer); Throwable cause = e.getCause(); boolean stack = log.isDebugEnable() || (!(cause instanceof NumberFormatException) && (cause instanceof RuntimeException || cause instanceof Error)); if (stack) log.warn( "bad HTTP parsed: " + e._code + (e.getReason() != null ? " " + e.getReason() : "") + " for " + _handler, e); else log.warn( "bad HTTP parsed: " + e._code + (e.getReason() != null ? " " + e.getReason() : "") + " for " + _handler); setState(State.CLOSE); _handler.badMessage(e.getCode(), e.getReason()); } catch (NumberFormatException | IllegalStateException e) { BufferUtils.clear(buffer); log.warn("parse exception: {} in {} for {}", e.toString(), _state, _handler); if (DEBUG) log.debug("parse exception", e); switch (_state) { case CLOSED: break; case CLOSE: _handler.earlyEOF(); break; default: setState(State.CLOSE); _handler.badMessage(400, null); } } catch (Exception | Error e) { BufferUtils.clear(buffer); log.warn("parse exception: " + e.toString() + " for " + _handler, e); switch (_state) { case CLOSED: break; case CLOSE: _handler.earlyEOF(); break; default: setState(State.CLOSE); _handler.badMessage(400, null); } } return false; }