HttpRequest extends MessageImpl { public static HttpRequest readRequest(Connection connection) throws ConnectionException, InvalidHttpMessageException { RequestBuffer buffer = new RequestBuffer(); boolean newLine = false; boolean lineFeedExpected = false; while(true) { int i = connection.read(); if (i == -1) { log.debug("reached client connection's EOS"); if (buffer.allDiscardableContent()) { return null; } log.warn("connection closed while reading a request"); break; } if (lineFeedExpected) { if (i != '\n') { throw new InvalidHttpHeaderException("missing LF"); } lineFeedExpected = false; } if ('\r' == (char)i) { if (newLine) { lineFeedExpected = true; } continue; } else if ('\n' == (char)i) { if (newLine) { break; } newLine = true; } else { newLine = false; } buffer.write(i); } HttpRequest request = new HttpRequest(buffer.toByteArray()); Integer contentLength = request.getContentLength(); HttpMethod method = request.getMethod(); if (contentLength == null) { if (HttpMethod.GET.equals(method)) { return request; } else if (HttpMethod.POST.equals(method)) { throw new InvalidHttpRequestException("POST request with no Content-Length"); } else { throw new RuntimeException( "NOT YET IMPLEMENTED: We don't know how to handle " + method + " without Content-Length"); } } else { int index = 0; byte[] body = new byte[contentLength]; while(index < body.length) { int b = connection.read(); if (b == -1) { throw new RuntimeException("NOT YET IMPLEMENTED"); } else { body[index ++] = (byte)b; } } request.setBody(body); } return request; } private  HttpRequest();  HttpRequest(HttpMethod method, String pathWithQuery);   HttpRequest(byte[] wireFormat); static HttpRequest readRequest(Connection connection); static String showRequest(HttpRequest r); HttpMethod getMethod(); String getPath(); String getHttpVersion(); String getQueryParameter(String parameterName); @Override String toString();  }
@Test public void readRequest_missingHttpVersion() throws Exception { MockConnection mc = new MockConnection(0, "GET /\r\n"); try { HttpRequest.readRequest(mc); fail("should throw exception"); } catch(InvalidHttpRequestException e) { String msg = e.getMessage(); log.info(msg); assertEquals("missing HTTP version", msg); } }
@Test public void readRequest_missingHttpVersion2() throws Exception { MockConnection mc = new MockConnection(0, "GET / \r\n"); try { HttpRequest.readRequest(mc); fail("should throw exception"); } catch(InvalidHttpRequestException e) { String msg = e.getMessage(); log.info(msg); assertEquals("missing HTTP version", msg); } }
@Test public void readRequest_HTTP10NotSupported() throws Exception { String requestContent = "GET / HTTP/1.0\r\n"; MockConnection mc = new MockConnection(0, requestContent); try { HttpRequest.readRequest(mc); fail("should throw exception"); } catch(InvalidHttpRequestException e) { String msg = e.getMessage(); log.info(msg); assertEquals("HTTP/1.0 protocol version not supported", msg); } }
@Test public void readRequest_InvalidMethod() throws Exception { String requestContent = "blah / HTTP/1.1\r\n"; MockConnection mc = new MockConnection(0, requestContent); try { HttpRequest.readRequest(mc); fail("should throw exception"); } catch(InvalidHttpMethodException e) { String msg = e.getMessage(); log.info(msg); assertEquals("unknown HTTP method: \"blah\"", msg); } }
@Test public void readRequest_GET_connectionClosedAbruptlyInMidstOfReadingARequest() throws Exception { MockConnection mc = new MockConnection(0, "HTT"); try { HttpRequest.readRequest(mc); fail("should throw exception"); } catch(InvalidHttpRequestException e) { String msg = e.getMessage(); log.info(msg); assertEquals("malformed request", msg); } }
@Test public void readRequest_GET_connectionClosedAbruptlyInMidstOfReadingARequest2() throws Exception { MockConnection mc = new MockConnection(0, "\nHTT"); try { HttpRequest.readRequest(mc); fail("should throw exception"); } catch(InvalidHttpRequestException e) { String msg = e.getMessage(); log.info(msg); assertEquals("malformed request", msg); } }
@Test public void readRequest_GET_inputStreamAtEOSToStartWith() throws Exception { MockConnection mc = new MockConnection(0); mc.close(); assertTrue(mc.isClosed()); HttpRequest request = HttpRequest.readRequest(mc); assertNull(request); }
@Test public void readRequest_GET_inputStreamContainsOnlyDiscardableCharacters() throws Exception { MockConnection mc = new MockConnection(0, " \r\n"); HttpRequest request = HttpRequest.readRequest(mc); assertNull(request); }
@Test public void readRequest_GET_nonLFCharacterWhenLFIsExpected() throws Exception { MockConnection mc = new MockConnection(0, "GET / HTTP/1.1\r\n\rx"); try { HttpRequest.readRequest(mc); fail("should throw exception"); } catch(InvalidHttpHeaderException e) { String msg = e.getMessage(); log.info(msg); assertEquals("missing LF", msg); } }
@Test public void readRequest_POST_noContentLengthHeader() throws Exception { String requestContent = "POST /test HTTP/1.1\r\n" + "Host: localhost:10000\r\n" + "\r\n" + "something without a content length"; MockConnection mc = new MockConnection(requestContent); try { HttpRequest.readRequest(mc); fail("should throw exception"); } catch(InvalidHttpRequestException e) { String msg = e.getMessage(); log.info(msg); assertEquals("POST request with no Content-Length", msg); } }