import java.io.*;
import java.util.HashMap;

/**
 * Created by Xinan on 15/9/15.
 */
public class HttpRequest {

  private String method;
  private String url;
  private String httpVersion;
  private HashMap<String, String> headers;
  private byte[] rawRequest;

  public HttpRequest(InputStream clientInputStream) throws IOException, MalformedRequestException {
    try {
      BufferedInputStream in = new BufferedInputStream(clientInputStream);
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      headers = new HashMap<String, String>();

      StringBuilder line = new StringBuilder();
      int b;
      boolean isFirstLine = true;
      String[] parts;
      while ((b = in.read()) > 0) {
        line.append((char) b);
        if (line.length() >= 2 && line.substring(line.length() - 2).equals("\r\n")) {
          if (line.length() == 2) {
            out.write(line.toString().getBytes());
            break;
          } else if (isFirstLine) {
            parts = line.toString().trim().split("\\s");
            method = parts[0];
            url = parts[1];
            httpVersion = parts[2].split("/")[1];
            isFirstLine = false;
          } else {
            parts = line.toString().trim().split("\\s*:\\s*");
            if (parts[0].equals("Connection")) {
              line.setLength(0);
              continue;
            }
            headers.put(parts[0], parts[1]);
          }
          out.write(line.toString().getBytes());
          line.setLength(0);
        }
      }

      if (headers.containsKey("Content-Length")) {
        int bodySize = Integer.parseInt(headers.get("Content-Length"));
        byte[] buffer = new byte[bodySize];
        int read = in.read(buffer, 0, bodySize);
        if (read != bodySize) {
          throw new MalformedRequestException("Content-Length mismatch!");
        }
        out.write(buffer);
      }

      rawRequest = out.toByteArray();
    } catch (IOException e) {
      System.out.printf("Exception in HttpRequest: %s\n", e.getMessage());
      throw e;
    } catch (NullPointerException | ArrayIndexOutOfBoundsException e) {
      throw new MalformedRequestException("Invalid request format!");
    }
  }

  public String getMethod() {
    return method;
  }

  public String getUrl() {
    return url;
  }

  public String getHttpVersion() {
    return httpVersion;
  }

  public HashMap<String, String> getHeaders() {
    return headers;
  }

  public String getHost() {
    return headers.get("Host");
  }

  public byte[] toByteBuffer() {
    return rawRequest;
  }

  public String toString() {
    return String.format("%s %s", method, url);
  }
}

@@ -220,24 +220,56 @@
 ing%3E headers
+ = new HashMap%3CString, String%3E()
 ;%0A  private 
@@ -540,190 +540,121 @@
 ();%0A
+%0A
       
+String 
 header
-s
  = 
-new HashMap%3CString, String%3E();%0A%0A      StringBuilder line = new StringBuilder();%0A      int b;%0A      boolean isFirstLine = 
+%22%22;%0A      int len;%0A%0A      // Reading headers%0A      while (
 true
-;
+) %7B
 %0A      
-String%5B%5D parts;%0A      while ((b =
+  header += (char)
  in.
@@ -663,16 +663,9 @@
 ad()
-) %3E 0) %7B
+;
 %0A   
@@ -674,148 +674,186 @@
    l
-ine.append((char) b);%0A        if (line.length() %3E= 2 && line.substring(line.length() - 2).equals(%22%5Cr%5Cn%22)) %7B%0A          if (line.length(
+en = header.length();%0A        if (header.charAt(len - 1) == '%5Cn' && header.charAt(len - 2) == '%5Cr' &&%0A            header.charAt(len - 3) == '%5Cn' && header.charAt(len - 4
 ) == 
-2
+'%5Cr'
 ) %7B%0A
@@ -866,47 +866,13 @@
     
-  out.write(line.toString().getBytes())
+break
 ;%0A  
@@ -881,97 +881,250 @@
     
+%7D%0A
     
-break;%0A          %7D else if (isFirstLine) %7B%0A            parts = line.toString().trim()
+  %7D%0A%0A      // Process headers%0A      int toIndex = header.indexOf(%22%5Cr%5Cn%22, 0);%0A      String line = header.substring(0, toIndex - 3) + %221.0%22;%0A      out.write(line.getBytes());%0A      out.write(%22%5Cr%5Cn%22.getBytes());%0A      String%5B%5D parts = line
 .spl
@@ -1130,30 +1130,24 @@
 lit(%22%5C%5Cs%22);%0A
-      
       method
@@ -1165,22 +1165,16 @@
 ;%0A      
-      
 url = pa
@@ -1187,22 +1187,16 @@
 ;%0A      
-      
 httpVers
@@ -1215,116 +1215,328 @@
 2%5D.s
-plit(%22/%22)%5B1%5D;%0A            isFirstLine = false;%0A          %7D else %7B%0A            parts = line.toString().trim()
+ubstring(4);%0A%0A      int fromIndex = toIndex + 2;%0A      while ((toIndex = header.indexOf(%22%5Cr%5Cn%22, fromIndex)) != -1) %7B%0A        line = header.substring(fromIndex, toIndex);%0A        fromIndex = toIndex + 2;%0A        if (line.isEmpty()) %7B%0A          out.write(%22%5Cr%5Cn%22.getBytes());%0A          break;%0A        %7D%0A        parts = line
 .spl
@@ -1560,24 +1560,21 @@
         
-    
 if (
+!
 parts%5B0%5D
@@ -1608,36 +1608,41 @@
         
-    
+out.write(
 line.
-setLength(0
+getBytes()
 );%0A     
@@ -1650,38 +1650,38 @@
     
-    continue;%0A            %7D%0A  
+out.write(%22%5Cr%5Cn%22.getBytes());%0A
     
@@ -1727,26 +1727,24 @@
         
-  
 %7D%0A      
     out.
@@ -1739,98 +1739,76 @@
     
-    out.write(line.toString().getBytes());%0A          line.setLength(0);%0A        %7D%0A      %7D%0A
+%7D%0A%0A      // Read body if %22Content-Length%22 is present in the headers.
 %0A   

Optimize `HttpRequest`