[DRE-commits] [SCM] ruby-http-parser.rb.git branch, master, updated. upstream/0.5.3-21-gb0f8f0b

Per Andersson avtobiff at gmail.com
Mon Jun 17 21:53:14 UTC 2013


The following commit has been merged in the master branch:
commit b2004132c323c500148f23020b8eb29a67a70bf4
Author: Per Andersson <avtobiff at gmail.com>
Date:   Mon Jun 17 00:56:15 2013 +0200

    Imported Upstream version 0.6.0~beta.2

diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index d20f94b..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,11 +0,0 @@
-tmp
-*.bundle
-*.gem
-*.o
-*.so
-*.bundle
-*.jar
-*.swp
-Makefile
-tags
-*.rbc
diff --git a/.gitmodules b/.gitmodules
index c36670d..6c289a3 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,6 @@
-[submodule "ext/ruby_http_parser/vendor/http-parser"]
+[submodule "http-parser"]
 	path = ext/ruby_http_parser/vendor/http-parser
 	url = git://github.com/joyent/http-parser.git
-[submodule "ext/ruby_http_parser/vendor/http-parser-java"]
+[submodule "http-parser-java"]
 	path = ext/ruby_http_parser/vendor/http-parser-java
-	url = git://github.com/a2800276/http-parser.java.git
+	url = git://github.com/tmm1/http-parser.java
diff --git a/Gemfile b/Gemfile
index e45e65f..851fabc 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,2 +1,2 @@
-source :rubygems
+source 'https://rubygems.org'
 gemspec
diff --git a/Gemfile.lock b/Gemfile.lock
index 83a5a06..c880187 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,13 +1,17 @@
 PATH
   remote: .
   specs:
-    http_parser.rb (0.5.2)
+    http_parser.rb (0.6.0.beta.2)
 
 GEM
-  remote: http://rubygems.org/
+  remote: https://rubygems.org/
   specs:
+    benchmark_suite (0.8.0)
     diff-lcs (1.1.2)
-    json (1.5.1)
+    ffi (1.0.11)
+    ffi (1.0.11-java)
+    json (1.8.0)
+    json (1.8.0-java)
     rake (0.9.2)
     rake-compiler (0.7.9)
       rake
@@ -19,12 +23,15 @@ GEM
     rspec-expectations (2.4.0)
       diff-lcs (~> 1.1.2)
     rspec-mocks (2.4.0)
-    yajl-ruby (0.8.2)
+    yajl-ruby (1.1.0)
 
 PLATFORMS
+  java
   ruby
 
 DEPENDENCIES
+  benchmark_suite
+  ffi
   http_parser.rb!
   json (>= 1.4.6)
   rake-compiler (>= 0.7.9)
diff --git a/README.md b/README.md
index 38948e9..05ab8b8 100644
--- a/README.md
+++ b/README.md
@@ -16,70 +16,75 @@ This gem aims to work on all major Ruby platforms, including:
 
 ## Usage
 
-    require "http/parser"
+```ruby
+require "http/parser"
 
-    parser = Http::Parser.new
+parser = Http::Parser.new
 
-    parser.on_headers_complete = proc do
-      p parser.http_version
+parser.on_headers_complete = proc do
+  p parser.http_version
 
-      p parser.http_method # for requests
-      p parser.request_url
+  p parser.http_method # for requests
+  p parser.request_url
 
-      p parser.status_code # for responses
+  p parser.status_code # for responses
 
-      p parser.headers
-    end
+  p parser.headers
+end
 
-    parser.on_body = proc do |chunk|
-      # One chunk of the body
-      p chunk
-    end
+parser.on_body = proc do |chunk|
+  # One chunk of the body
+  p chunk
+end
 
-    parser.on_message_complete = proc do |env|
-      # Headers and body is all parsed
-      puts "Done!"
-    end
+parser.on_message_complete = proc do |env|
+  # Headers and body is all parsed
+  puts "Done!"
+end
+```
 
-    # Feed raw data from the socket to the parser
-    parser << raw_data
+# Feed raw data from the socket to the parser
+`parser << raw_data`
 
 ## Advanced Usage
 
 ### Accept callbacks on an object
 
-    module MyHttpConnection
-      def connection_completed
-        @parser = Http::Parser.new(self)
-      end
+```ruby
+module MyHttpConnection
+  def connection_completed
+    @parser = Http::Parser.new(self)
+  end
 
-      def receive_data(data)
-        @parser << data
-      end
+  def receive_data(data)
+    @parser << data
+  end
 
-      def on_message_begin
-        @headers = nil
-        @body = ''
-      end
+  def on_message_begin
+    @headers = nil
+    @body = ''
+  end
 
-      def on_headers_complete
-        @headers = @parser.headers
-      end
+  def on_headers_complete(headers)
+    @headers = headers
+  end
 
-      def on_body(chunk)
-        @body << chunk
-      end
+  def on_body(chunk)
+    @body << chunk
+  end
 
-      def on_message_complete
-        p [@headers, @body]
-      end
-    end
+  def on_message_complete
+    p [@headers, @body]
+  end
+end
+```
 
 ### Stop parsing after headers
 
-    parser = Http::Parser.new
-    parser.on_headers_complete = proc{ :stop }
-
-    offset = parser << request_data
-    body = request_data[offset..-1]
+```ruby
+parser = Http::Parser.new
+parser.on_headers_complete = proc{ :stop }
 
+offset = parser << request_data
+body = request_data[offset..-1]
+```
diff --git a/bench/standalone.rb b/bench/standalone.rb
new file mode 100755
index 0000000..6b4dcb6
--- /dev/null
+++ b/bench/standalone.rb
@@ -0,0 +1,23 @@
+#!/usr/bin/env ruby
+$:.unshift File.dirname(__FILE__) + "/../lib"
+require "rubygems"
+require "http/parser"
+require "benchmark/ips"
+
+request = <<-REQUEST
+GET / HTTP/1.1
+Host: www.example.com
+Connection: keep-alive
+User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.78 S
+Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
+Accept-Encoding: gzip,deflate,sdch
+Accept-Language: en-US,en;q=0.8
+Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
+
+REQUEST
+request.gsub!(/\n/m, "\r\n")
+
+Benchmark.ips do |ips|
+  ips.report("instance") { Http::Parser.new }
+  ips.report("parsing")  { Http::Parser.new << request }
+end
diff --git a/bench/thin.rb b/bench/thin.rb
index fa0effc..fe0dd6d 100644
--- a/bench/thin.rb
+++ b/bench/thin.rb
@@ -3,6 +3,7 @@ require "rubygems"
 require "thin_parser"
 require "http_parser"
 require "benchmark"
+require "stringio"
 
 data = "POST /postit HTTP/1.1\r\n" +
        "Host: localhost:3000\r\n" +
diff --git a/ext/ruby_http_parser/.gitignore b/ext/ruby_http_parser/.gitignore
deleted file mode 100644
index cb899d1..0000000
--- a/ext/ruby_http_parser/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-ryah_http_parser.*
diff --git a/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java b/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java
index 6aa8a09..ac586a9 100644
--- a/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java
+++ b/ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java
@@ -1,36 +1,45 @@
 package org.ruby_http_parser;
 
+import http_parser.HTTPException;
+import http_parser.HTTPMethod;
+import http_parser.HTTPParser;
+import http_parser.lolevel.HTTPCallback;
+import http_parser.lolevel.HTTPDataCallback;
+import http_parser.lolevel.ParserSettings;
+
+import java.nio.ByteBuffer;
+
+import org.jcodings.Encoding;
+import org.jcodings.specific.UTF8Encoding;
 import org.jruby.Ruby;
 import org.jruby.RubyArray;
 import org.jruby.RubyClass;
 import org.jruby.RubyHash;
-import org.jruby.RubyModule;
 import org.jruby.RubyNumeric;
 import org.jruby.RubyObject;
 import org.jruby.RubyString;
-
+import org.jruby.RubySymbol;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.exceptions.RaiseException;
 import org.jruby.runtime.ObjectAllocator;
 import org.jruby.runtime.ThreadContext;
 import org.jruby.runtime.builtin.IRubyObject;
-
-import org.jruby.anno.JRubyMethod;
-import org.jruby.exceptions.RaiseException;
-
-import java.nio.ByteBuffer;
-import http_parser.*;
-import http_parser.lolevel.ParserSettings;
-import http_parser.lolevel.HTTPCallback;
-import http_parser.lolevel.HTTPDataCallback;
+import org.jruby.util.ByteList;
 
 public class RubyHttpParser extends RubyObject {
 
+  @JRubyMethod(name = "strict?", module = true)
+  public static IRubyObject strict(IRubyObject recv) {
+    return recv.getRuntime().newBoolean(true);
+  }
+
   public static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
     public IRubyObject allocate(Ruby runtime, RubyClass klass) {
       return new RubyHttpParser(runtime, klass);
     }
   };
 
-  byte[] fetchBytes (ByteBuffer b, int pos, int len) {
+  byte[] fetchBytes(ByteBuffer b, int pos, int len) {
     byte[] by = new byte[len];
     int saved = b.position();
     b.position(pos);
@@ -65,14 +74,18 @@ public class RubyHttpParser extends RubyObject {
 
   private IRubyObject callback_object;
 
-  private String _current_header;
-  private String _last_header;
+  private boolean completed;
+
+  private byte[] _current_header;
+  private byte[] _last_header;
+
+  private static final Encoding UTF8 = UTF8Encoding.INSTANCE;
 
   public RubyHttpParser(final Ruby runtime, RubyClass clazz) {
-    super(runtime,clazz);
+    super(runtime, clazz);
 
     this.runtime = runtime;
-    this.eParserError = (RubyClass)runtime.getModule("HTTP").getClass("Parser").getConstant("Error");
+    this.eParserError = (RubyClass) runtime.getModule("HTTP").getClass("Parser").getConstant("Error");
 
     this.on_message_begin = null;
     this.on_headers_complete = null;
@@ -81,7 +94,10 @@ public class RubyHttpParser extends RubyObject {
 
     this.callback_object = null;
 
-    this.header_value_type = runtime.getModule("HTTP").getClass("Parser").getInstanceVariable("@default_header_value_type");
+    this.completed = false;
+
+    this.header_value_type = runtime.getModule("HTTP").getClass("Parser")
+        .getInstanceVariable("@default_header_value_type");
 
     initSettings();
     init();
@@ -91,48 +107,39 @@ public class RubyHttpParser extends RubyObject {
     this.settings = new ParserSettings();
 
     this.settings.on_url = new HTTPDataCallback() {
-      public int cb (http_parser.lolevel.HTTPParser p, ByteBuffer buf, int pos, int len) {
+      public int cb(http_parser.lolevel.HTTPParser p, ByteBuffer buf, int pos, int len) {
         byte[] data = fetchBytes(buf, pos, len);
-        ((RubyString)requestUrl).concat(runtime.newString(new String(data)));
-        return 0;
-      }
-    };
-    this.settings.on_path = new HTTPDataCallback() {
-      public int cb (http_parser.lolevel.HTTPParser p, ByteBuffer buf, int pos, int len) {
-        byte[] data = fetchBytes(buf, pos, len);
-        ((RubyString)requestPath).concat(runtime.newString(new String(data)));
-        return 0;
-      }
-    };
-    this.settings.on_query_string = new HTTPDataCallback() {
-      public int cb (http_parser.lolevel.HTTPParser p, ByteBuffer buf, int pos, int len) {
-        byte[] data = fetchBytes(buf, pos, len);
-        ((RubyString)queryString).concat(runtime.newString(new String(data)));
-        return 0;
-      }
-    };
-    this.settings.on_fragment = new HTTPDataCallback() {
-      public int cb (http_parser.lolevel.HTTPParser p, ByteBuffer buf, int pos, int len) {
-        byte[] data = fetchBytes(buf, pos, len);
-        ((RubyString)fragment).concat(runtime.newString(new String(data)));
+        if (runtime.is1_9() || runtime.is2_0()) {
+          ((RubyString) requestUrl).cat(data, 0, data.length, UTF8);
+        } else {
+          ((RubyString) requestUrl).cat(data);
+        }
         return 0;
       }
     };
 
     this.settings.on_header_field = new HTTPDataCallback() {
-      public int cb (http_parser.lolevel.HTTPParser p, ByteBuffer buf, int pos, int len) {
+      public int cb(http_parser.lolevel.HTTPParser p, ByteBuffer buf, int pos, int len) {
         byte[] data = fetchBytes(buf, pos, len);
 
         if (_current_header == null)
-          _current_header = new String(data);
-        else
-          _current_header = _current_header.concat(new String(data));
+          _current_header = data;
+        else {
+          byte[] tmp = new byte[_current_header.length + data.length];
+          System.arraycopy(_current_header, 0, tmp, 0, _current_header.length);
+          System.arraycopy(data, 0, tmp, _current_header.length, data.length);
+          _current_header = tmp;
+        }
 
         return 0;
       }
     };
+    final RubySymbol arraysSym = runtime.newSymbol("arrays");
+    final RubySymbol mixedSym = runtime.newSymbol("mixed");
+    final RubySymbol stopSym = runtime.newSymbol("stop");
+    final RubySymbol resetSym = runtime.newSymbol("reset");
     this.settings.on_header_value = new HTTPDataCallback() {
-      public int cb (http_parser.lolevel.HTTPParser p, ByteBuffer buf, int pos, int len) {
+      public int cb(http_parser.lolevel.HTTPParser p, ByteBuffer buf, int pos, int len) {
         byte[] data = fetchBytes(buf, pos, len);
         ThreadContext context = headers.getRuntime().getCurrentContext();
         IRubyObject key, val;
@@ -144,57 +151,74 @@ public class RubyHttpParser extends RubyObject {
           _current_header = null;
         }
 
-        key = (IRubyObject)runtime.newString(_last_header);
+        key = RubyString.newString(runtime, new ByteList(_last_header, UTF8, false));
         val = headers.op_aref(context, key);
 
         if (new_field == 1) {
           if (val.isNil()) {
-            if (header_value_type == runtime.newSymbol("arrays")) {
-              headers.op_aset(context, key, RubyArray.newArrayLight(runtime, runtime.newString("")));
+            if (header_value_type == arraysSym) {
+              headers.op_aset(context, key,
+                  RubyArray.newArrayLight(runtime, RubyString.newStringLight(runtime, 10, UTF8)));
             } else {
-              headers.op_aset(context, key, runtime.newString(""));
+              headers.op_aset(context, key, RubyString.newStringLight(runtime, 10, UTF8));
             }
           } else {
-            if (header_value_type == runtime.newSymbol("mixed")) {
+            if (header_value_type == mixedSym) {
               if (val instanceof RubyString) {
-                headers.op_aset(context, key, RubyArray.newArrayLight(runtime, val, runtime.newString("")));
+                headers.op_aset(context, key,
+                    RubyArray.newArrayLight(runtime, val, RubyString.newStringLight(runtime, 10, UTF8)));
               } else {
-                ((RubyArray)val).add(runtime.newString(""));
+                ((RubyArray) val).add(RubyString.newStringLight(runtime, 10, UTF8));
               }
-            } else if (header_value_type == runtime.newSymbol("arrays")) {
-              ((RubyArray)val).add(runtime.newString(""));
+            } else if (header_value_type == arraysSym) {
+              ((RubyArray) val).add(RubyString.newStringLight(runtime, 10, UTF8));
             } else {
-              ((RubyString)val).cat(", ".getBytes());
+              if (runtime.is1_9() || runtime.is2_0()) {
+                ((RubyString) val).cat(',', UTF8).cat(' ', UTF8);
+              } else {
+                ((RubyString) val).cat(',').cat(' ');
+              }
             }
           }
           val = headers.op_aref(context, key);
         }
 
         if (val instanceof RubyArray) {
-          val = ((RubyArray)val).entry(-1);
+          val = ((RubyArray) val).entry(-1);
         }
 
-        ((RubyString)val).cat(data);
+        if (runtime.is1_9() || runtime.is2_0()) {
+          ((RubyString) val).cat(data, 0, data.length, UTF8);
+        } else {
+          ((RubyString) val).cat(data);
+        }
 
         return 0;
       }
     };
 
     this.settings.on_message_begin = new HTTPCallback() {
-      public int cb (http_parser.lolevel.HTTPParser p) {
+      public int cb(http_parser.lolevel.HTTPParser p) {
         headers = new RubyHash(runtime);
 
-        requestUrl = runtime.newString("");
-        requestPath = runtime.newString("");
-        queryString = runtime.newString("");
-        fragment = runtime.newString("");
-
-        upgradeData = runtime.newString("");
+        if (runtime.is1_9() || runtime.is2_0()) {
+          requestUrl = RubyString.newEmptyString(runtime, UTF8);
+          requestPath = RubyString.newEmptyString(runtime, UTF8);
+          queryString = RubyString.newEmptyString(runtime, UTF8);
+          fragment = RubyString.newEmptyString(runtime, UTF8);
+          upgradeData = RubyString.newEmptyString(runtime, UTF8);
+        } else {
+          requestUrl = RubyString.newEmptyString(runtime);
+          requestPath = RubyString.newEmptyString(runtime);
+          queryString = RubyString.newEmptyString(runtime);
+          fragment = RubyString.newEmptyString(runtime);
+          upgradeData = RubyString.newEmptyString(runtime);
+        }
 
         IRubyObject ret = runtime.getNil();
 
         if (callback_object != null) {
-          if (((RubyObject)callback_object).respond_to_p(runtime.newSymbol("on_message_begin")).toJava(Boolean.class) == Boolean.TRUE) {
+          if (((RubyObject) callback_object).respondsTo("on_message_begin")) {
             ThreadContext context = callback_object.getRuntime().getCurrentContext();
             ret = callback_object.callMethod(context, "on_message_begin");
           }
@@ -203,7 +227,7 @@ public class RubyHttpParser extends RubyObject {
           ret = on_message_begin.callMethod(context, "call");
         }
 
-        if (ret == runtime.newSymbol("stop")) {
+        if (ret == stopSym) {
           throw new StopException();
         } else {
           return 0;
@@ -211,11 +235,13 @@ public class RubyHttpParser extends RubyObject {
       }
     };
     this.settings.on_message_complete = new HTTPCallback() {
-      public int cb (http_parser.lolevel.HTTPParser p) {
+      public int cb(http_parser.lolevel.HTTPParser p) {
         IRubyObject ret = runtime.getNil();
 
+        completed = true;
+
         if (callback_object != null) {
-          if (((RubyObject)callback_object).respond_to_p(runtime.newSymbol("on_message_complete")).toJava(Boolean.class) == Boolean.TRUE) {
+          if (((RubyObject) callback_object).respondsTo("on_message_complete")) {
             ThreadContext context = callback_object.getRuntime().getCurrentContext();
             ret = callback_object.callMethod(context, "on_message_complete");
           }
@@ -224,7 +250,7 @@ public class RubyHttpParser extends RubyObject {
           ret = on_message_complete.callMethod(context, "call");
         }
 
-        if (ret == runtime.newSymbol("stop")) {
+        if (ret == stopSym) {
           throw new StopException();
         } else {
           return 0;
@@ -232,11 +258,11 @@ public class RubyHttpParser extends RubyObject {
       }
     };
     this.settings.on_headers_complete = new HTTPCallback() {
-      public int cb (http_parser.lolevel.HTTPParser p) {
+      public int cb(http_parser.lolevel.HTTPParser p) {
         IRubyObject ret = runtime.getNil();
 
         if (callback_object != null) {
-          if (((RubyObject)callback_object).respond_to_p(runtime.newSymbol("on_headers_complete")).toJava(Boolean.class) == Boolean.TRUE) {
+          if (((RubyObject) callback_object).respondsTo("on_headers_complete")) {
             ThreadContext context = callback_object.getRuntime().getCurrentContext();
             ret = callback_object.callMethod(context, "on_headers_complete", headers);
           }
@@ -245,29 +271,32 @@ public class RubyHttpParser extends RubyObject {
           ret = on_headers_complete.callMethod(context, "call", headers);
         }
 
-        if (ret == runtime.newSymbol("stop")) {
+        if (ret == stopSym) {
           throw new StopException();
+        } else if (ret == resetSym) {
+          return 1;
         } else {
           return 0;
         }
       }
     };
     this.settings.on_body = new HTTPDataCallback() {
-      public int cb (http_parser.lolevel.HTTPParser p, ByteBuffer buf, int pos, int len) {
+      public int cb(http_parser.lolevel.HTTPParser p, ByteBuffer buf, int pos, int len) {
         IRubyObject ret = runtime.getNil();
         byte[] data = fetchBytes(buf, pos, len);
 
         if (callback_object != null) {
-          if (((RubyObject)callback_object).respond_to_p(runtime.newSymbol("on_body")).toJava(Boolean.class) == Boolean.TRUE) {
+          if (((RubyObject) callback_object).respondsTo("on_body")) {
             ThreadContext context = callback_object.getRuntime().getCurrentContext();
-            ret = callback_object.callMethod(context, "on_body", callback_object.getRuntime().newString(new String(data)));
+            ret = callback_object.callMethod(context, "on_body",
+                RubyString.newString(runtime, new ByteList(data, UTF8, false)));
           }
         } else if (on_body != null) {
           ThreadContext context = on_body.getRuntime().getCurrentContext();
-          ret = on_body.callMethod(context, "call", on_body.getRuntime().newString(new String(data)));
+          ret = on_body.callMethod(context, "call", RubyString.newString(runtime, new ByteList(data, UTF8, false)));
         }
 
-        if (ret == runtime.newSymbol("stop")) {
+        if (ret == stopSym) {
           throw new StopException();
         } else {
           return 0;
@@ -278,6 +307,7 @@ public class RubyHttpParser extends RubyObject {
 
   private void init() {
     this.parser = new HTTPParser();
+    this.parser.HTTP_PARSER_STRICT = true;
     this.headers = null;
 
     this.requestUrl = runtime.getNil();
@@ -331,8 +361,9 @@ public class RubyHttpParser extends RubyObject {
 
   @JRubyMethod(name = "<<")
   public IRubyObject execute(IRubyObject data) {
-    RubyString str = (RubyString)data;
-    ByteBuffer buf = ByteBuffer.wrap(str.getBytes());
+    RubyString str = (RubyString) data;
+    ByteList byteList = str.getByteList();
+    ByteBuffer buf = ByteBuffer.wrap(byteList.getUnsafeBytes(), byteList.getBegin(), byteList.getRealSize());
     boolean stopped = false;
 
     try {
@@ -345,9 +376,12 @@ public class RubyHttpParser extends RubyObject {
 
     if (parser.getUpgrade()) {
       byte[] upData = fetchBytes(buf, buf.position(), buf.limit() - buf.position());
-      ((RubyString)upgradeData).concat(runtime.newString(new String(upData)));
-
-    } else if (buf.hasRemaining()) {
+      if (runtime.is1_9() || runtime.is2_0()) {
+        ((RubyString) upgradeData).cat(upData, 0, upData.length, UTF8);
+      } else {
+        ((RubyString) upgradeData).cat(upData);
+      }
+    } else if (buf.hasRemaining() && !completed) {
       if (!stopped)
         throw new RaiseException(runtime, eParserError, "Could not parse data entirely", true);
     }
@@ -357,12 +391,12 @@ public class RubyHttpParser extends RubyObject {
 
   @JRubyMethod(name = "keep_alive?")
   public IRubyObject shouldKeepAlive() {
-    return parser.shouldKeepAlive() ? runtime.getTrue() : runtime.getFalse();
+    return runtime.newBoolean(parser.shouldKeepAlive());
   }
 
   @JRubyMethod(name = "upgrade?")
   public IRubyObject shouldUpgrade() {
-    return parser.getUpgrade() ? runtime.getTrue() : runtime.getFalse();
+    return runtime.newBoolean(parser.getUpgrade());
   }
 
   @JRubyMethod(name = "http_major")
@@ -439,7 +473,8 @@ public class RubyHttpParser extends RubyObject {
 
   @JRubyMethod(name = "header_value_type=")
   public IRubyObject set_header_value_type(IRubyObject val) {
-    if (val != runtime.newSymbol("mixed") && val != runtime.newSymbol("arrays") && val != runtime.newSymbol("strings")) {
+    String valString = val.toString();
+    if (valString != "mixed" && valString != "arrays" && valString != "strings") {
       throw runtime.newArgumentError("Invalid header value type");
     }
     header_value_type = val;
diff --git a/ext/ruby_http_parser/ruby_http_parser.c b/ext/ruby_http_parser/ruby_http_parser.c
index 3c7eafe..5650652 100644
--- a/ext/ruby_http_parser/ruby_http_parser.c
+++ b/ext/ruby_http_parser/ruby_http_parser.c
@@ -17,9 +17,6 @@ typedef struct ParserWrapper {
   ryah_http_parser parser;
 
   VALUE request_url;
-  VALUE request_path;
-  VALUE query_string;
-  VALUE fragment;
 
   VALUE headers;
 
@@ -49,9 +46,6 @@ void ParserWrapper_init(ParserWrapper *wrapper) {
   wrapper->parser.http_minor = 0;
 
   wrapper->request_url = Qnil;
-  wrapper->request_path = Qnil;
-  wrapper->query_string = Qnil;
-  wrapper->fragment = Qnil;
 
   wrapper->upgrade_data = Qnil;
 
@@ -66,9 +60,6 @@ void ParserWrapper_mark(void *data) {
   if(data) {
     ParserWrapper *wrapper = (ParserWrapper *) data;
     rb_gc_mark_maybe(wrapper->request_url);
-    rb_gc_mark_maybe(wrapper->request_path);
-    rb_gc_mark_maybe(wrapper->query_string);
-    rb_gc_mark_maybe(wrapper->fragment);
     rb_gc_mark_maybe(wrapper->upgrade_data);
     rb_gc_mark_maybe(wrapper->headers);
     rb_gc_mark_maybe(wrapper->on_message_begin);
@@ -111,9 +102,6 @@ int on_message_begin(ryah_http_parser *parser) {
   GET_WRAPPER(wrapper, parser);
 
   wrapper->request_url = rb_str_new2("");
-  wrapper->request_path = rb_str_new2("");
-  wrapper->query_string = rb_str_new2("");
-  wrapper->fragment = rb_str_new2("");
   wrapper->headers = rb_hash_new();
   wrapper->upgrade_data = rb_str_new2("");
 
@@ -139,24 +127,6 @@ int on_url(ryah_http_parser *parser, const char *at, size_t length) {
   return 0;
 }
 
-int on_path(ryah_http_parser *parser, const char *at, size_t length) {
-  GET_WRAPPER(wrapper, parser);
-  rb_str_cat(wrapper->request_path, at, length);
-  return 0;
-}
-
-int on_query_string(ryah_http_parser *parser, const char *at, size_t length) {
-  GET_WRAPPER(wrapper, parser);
-  rb_str_cat(wrapper->query_string, at, length);
-  return 0;
-}
-
-int on_fragment(ryah_http_parser *parser, const char *at, size_t length) {
-  GET_WRAPPER(wrapper, parser);
-  rb_str_cat(wrapper->fragment, at, length);
-  return 0;
-}
-
 int on_header_field(ryah_http_parser *parser, const char *at, size_t length) {
   GET_WRAPPER(wrapper, parser);
 
@@ -278,10 +248,7 @@ int on_message_complete(ryah_http_parser *parser) {
 
 static ryah_http_parser_settings settings = {
   .on_message_begin = on_message_begin,
-  .on_path = on_path,
-  .on_query_string = on_query_string,
   .on_url = on_url,
-  .on_fragment = on_fragment,
   .on_header_field = on_header_field,
   .on_header_value = on_header_value,
   .on_headers_complete = on_headers_complete,
@@ -318,6 +285,10 @@ VALUE ResponseParser_alloc(VALUE klass) {
   return Parser_alloc_by_type(klass, HTTP_RESPONSE);
 }
 
+VALUE Parser_strict_p(VALUE klass) {
+  return HTTP_PARSER_STRICT == 1 ? Qtrue : Qfalse;
+}
+
 VALUE Parser_initialize(int argc, VALUE *argv, VALUE self) {
   ParserWrapper *wrapper = NULL;
   DATA_GET(self, ParserWrapper, wrapper);
@@ -349,11 +320,14 @@ VALUE Parser_execute(VALUE self, VALUE data) {
   size_t nparsed = ryah_http_parser_execute(&wrapper->parser, &settings, ptr, len);
 
   if (wrapper->parser.upgrade) {
-    rb_str_cat(wrapper->upgrade_data, ptr + nparsed + 1, len - nparsed - 1);
+    if (RTEST(wrapper->stopped))
+      nparsed += 1;
+
+    rb_str_cat(wrapper->upgrade_data, ptr + nparsed, len - nparsed);
 
   } else if (nparsed != (size_t)len) {
     if (!RTEST(wrapper->stopped) && !RTEST(wrapper->completed))
-      rb_raise(eParserError, "Could not parse data entirely");
+      rb_raise(eParserError, "Could not parse data entirely (%zu != %zu)", nparsed, len);
     else
       nparsed += 1; // error states fail on the current character
   }
@@ -465,9 +439,6 @@ VALUE Parser_status_code(VALUE self) {
   }
 
 DEFINE_GETTER(request_url);
-DEFINE_GETTER(request_path);
-DEFINE_GETTER(query_string);
-DEFINE_GETTER(fragment);
 DEFINE_GETTER(headers);
 DEFINE_GETTER(upgrade_data);
 DEFINE_GETTER(header_value_type);
@@ -515,6 +486,7 @@ void Init_ruby_http_parser() {
   rb_define_alloc_func(cRequestParser, RequestParser_alloc);
   rb_define_alloc_func(cResponseParser, ResponseParser_alloc);
 
+  rb_define_singleton_method(cParser, "strict?", Parser_strict_p, 0);
   rb_define_method(cParser, "initialize", Parser_initialize, -1);
 
   rb_define_method(cParser, "on_message_begin=", Parser_set_on_message_begin, 1);
@@ -534,9 +506,6 @@ void Init_ruby_http_parser() {
   rb_define_method(cParser, "status_code", Parser_status_code, 0);
 
   rb_define_method(cParser, "request_url", Parser_request_url, 0);
-  rb_define_method(cParser, "request_path", Parser_request_path, 0);
-  rb_define_method(cParser, "query_string", Parser_query_string, 0);
-  rb_define_method(cParser, "fragment", Parser_fragment, 0);
   rb_define_method(cParser, "headers", Parser_headers, 0);
   rb_define_method(cParser, "upgrade_data", Parser_upgrade_data, 0);
   rb_define_method(cParser, "header_value_type", Parser_header_value_type, 0);
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/LICENSE-MIT b/ext/ruby_http_parser/vendor/http-parser-java/LICENSE-MIT
deleted file mode 100644
index fd99d4d..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/LICENSE-MIT
+++ /dev/null
@@ -1,44 +0,0 @@
-Copyright 2010 Tim Becker <tim.becker at kuriositaet.de>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to
-deal in the Software without restriction, including without limitation the
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-IN THE SOFTWARE.
-
---- END OF LICENSE
-
-This code mainly based on code with the following license:
-
-
-Copyright Joyent, Inc. and other Node contributors. All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to
-deal in the Software without restriction, including without limitation the
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-IN THE SOFTWARE. 
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/Makefile b/ext/ruby_http_parser/vendor/http-parser-java/Makefile
deleted file mode 100644
index 2b945c1..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/Makefile
+++ /dev/null
@@ -1,41 +0,0 @@
-OPT_DEBUG=-O0 -g -Wall -Wextra -Werror -I.
-OPT_FAST=-O3 -DHTTP_PARSER_STRICT=0 -I.
-
-CC?=gcc
-
-
-test: test_g
-	./test_g
-
-test_g: http_parser_g.o test_g.o
-	$(CC) $(OPT_DEBUG) http_parser_g.o test_g.o -o $@
-
-test_g.o: test.c http_parser.h Makefile
-	$(CC) $(OPT_DEBUG) -c test.c -o $@
-
-test.o: test.c http_parser.h Makefile
-	$(CC) $(OPT_FAST) -c test.c -o $@
-
-http_parser_g.o: http_parser.c http_parser.h Makefile
-	$(CC) $(OPT_DEBUG) -c http_parser.c -o $@
-
-test-valgrind: test_g
-	valgrind ./test_g
-
-http_parser.o: http_parser.c http_parser.h Makefile
-	$(CC) $(OPT_FAST) -c http_parser.c
-
-test_fast: http_parser.o test.c http_parser.h
-	$(CC) $(OPT_FAST) http_parser.o test.c -o $@
-
-test-run-timed: test_fast
-	while(true) do time ./test_fast > /dev/null; done
-
-
-tags: http_parser.c http_parser.h test.c
-	ctags $^
-
-clean:
-	rm -f *.o test test_fast test_g http_parser.tar tags
-
-.PHONY: clean package test-run test-run-timed test-valgrind
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/README.md b/ext/ruby_http_parser/vendor/http-parser-java/README.md
deleted file mode 100644
index 6a10580..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/README.md
+++ /dev/null
@@ -1,51 +0,0 @@
-HTTP Parser
-===========
-
-This is a parser for HTTP written in Java, based quite heavily on
-the Ryan Dahl's C Version: `http-parser` available here:
-
-  http://github.com/ry/http-parser
-
-It parses both requests and responses. The parser is designed to be used
-in performance HTTP applications. 
-
-Features:
-
-  * No dependencies (probably won't be able to keep it up)
-  * Handles persistent streams (keep-alive).
-  * Decodes chunked encoding.
-  * Upgrade support
-
-The parser extracts the following information from HTTP messages:
-
-  * Header fields and values
-  * Content-Length
-  * Request method
-  * Response status code
-  * Transfer-Encoding
-  * HTTP version
-  * Request path, query string, fragment
-  * Message body
-
-Building
---------
-
-use `ant compile|test|jar`
-
-Usage
------
-
-  TODO: in the present form, usage of the Java version of the parser
-  shouldn't be too difficult to figure out for someone familiar with the
-  C version.
-
-  More documentation will follow shortly, in case you're looking for an
-  easy to use http library, this lib is probably not what you are
-  looking for anyway ...
-
-  All text after this paragraph (and most of the text above it) are from
-  the original C version of the README and are currently only here for
-  reference. In case you encounter any difficulties, find bugs, need
-  help or have suggestions, feel free to contact me at
-  (tim.becker at kuriositaet.de).
-
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/TODO b/ext/ruby_http_parser/vendor/http-parser-java/TODO
deleted file mode 100644
index 7a39948..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/TODO
+++ /dev/null
@@ -1,22 +0,0 @@
-some tests from test.c left to port
-documentation
-
-hi level callback interface 
-eventloop
-state() as a function (?)
-  - perhaps, the idea being to be able to log/debug better...
-more tests
-  - in particular, port available c tests
-impl bits of servlet api.
-
-DONE
-
-Sun Jul 18 12:19:18 CEST 2010
-
-error handling
-  - consider callback based error handling and the current highlevel
-    "nice" logging moved to high level http impl.
-  - use Exceptions "ProtocolException"?
-
-better testing
-  - no junit to avoid dependencies
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/build.xml b/ext/ruby_http_parser/vendor/http-parser-java/build.xml
deleted file mode 100755
index d2c6af4..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/build.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0"?>
-
-<project name="http-parser" default="compile" basedir=".">
-
-<echo message="pulling in property files"/>
-<property file="build.properties"/>
-<property name="classes.dir" value="classes"/>
-<property name="assemble.dir" value="assemble"/>
-<property name="lib.dir" value="lib"/>
-
-
-
-<target name="prepare">
-  <mkdir dir="${classes.dir}" />
-  <mkdir dir="${assemble.dir}" />
-  <mkdir dir="${lib.dir}" />
-</target>
-
-<target name="clean">
-	<delete dir="${classes.dir}"/>
-	<delete dir="lib"/>
-	<delete dir="doc"/>
-	<delete dir="${assemble.dir}"/>
-</target>
-
-<target name="compile" depends="prepare">
-  <javac srcdir="src" destdir="${classes.dir}" debug='true'>
-    <classpath>
-      <pathelement path="${classpath}"/>
-      <pathelement location="ext/http-parser.jar"/>
-      <pathelement location="ext/primitives.jar"/>
-    </classpath>
-  </javac>
-</target>
-
-<target name="jar" depends="compile">
-	<copy todir="${assemble.dir}">
-		<fileset dir="classes"/>
-	</copy>
-	<jar basedir="${assemble.dir}" destfile="lib/${ant.project.name}.jar"/>
-</target>
-
-<target name="run" depends="jar">
-	<echo message="don't know how to run"/>
-</target>
-
-<target name="doc" depends="prepare">
-  <javadoc sourcepath="src/impl" destdir="doc">  
-	</javadoc>
-</target>
-
-<target name="test_permutations" depends="compile">
-  <java classname="http_parser.lolevel.TestLoaderNG">
-    <arg value="tests.dumped"/>
-    <classpath>
-      <pathelement location="classes/"/>
-      <pathelement location="ext/primitives.jar/"/>
-    </classpath> 
-  </java>
-</target>
-
-<target name="test_unit" depends="compile">
-  <java classname="http_parser.lolevel.Test">
-    <arg value="tests.dumped"/>
-    <classpath>
-      <pathelement location="classes/"/>
-      <pathelement location="ext/primitives.jar/"/>
-    </classpath> 
-  </java>
-</target>
-
-<target name="test" depends="test_permutations, test_unit"/>
-
-</project>
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/compile b/ext/ruby_http_parser/vendor/http-parser-java/compile
deleted file mode 100644
index 61166ae..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/compile
+++ /dev/null
@@ -1 +0,0 @@
-javac -d classes/ `find src -name '*.java'` && java -cp classes http_parser.lolevel.TestLoaderNG tests.dumped
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/ext/primitives.jar b/ext/ruby_http_parser/vendor/http-parser-java/ext/primitives.jar
deleted file mode 100644
index 2900c5f..0000000
Binary files a/ext/ruby_http_parser/vendor/http-parser-java/ext/primitives.jar and /dev/null differ
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/http_parser.c b/ext/ruby_http_parser/vendor/http-parser-java/http_parser.c
deleted file mode 100644
index 0fe0e8f..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/http_parser.c
+++ /dev/null
@@ -1,1644 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <http_parser.h>
-#include <assert.h>
-#include <stddef.h>
-
-
-#ifndef MIN
-# define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-
-#define CALLBACK2(FOR)                                               \
-do {                                                                 \
-  if (settings->on_##FOR) {                                          \
-    if (0 != settings->on_##FOR(parser)) return (p - data);          \
-  }                                                                  \
-} while (0)
-
-
-#define MARK(FOR)                                                    \
-do {                                                                 \
-  FOR##_mark = p;                                                    \
-} while (0)
-
-#define CALLBACK_NOCLEAR(FOR)                                        \
-do {                                                                 \
-  if (FOR##_mark) {                                                  \
-    if (settings->on_##FOR) {                                        \
-      if (0 != settings->on_##FOR(parser,                            \
-                                 FOR##_mark,                         \
-                                 p - FOR##_mark))                    \
-      {                                                              \
-        return (p - data);                                           \
-      }                                                              \
-    }                                                                \
-  }                                                                  \
-} while (0)
-
-
-#define CALLBACK(FOR)                                                \
-do {                                                                 \
-  CALLBACK_NOCLEAR(FOR);                                             \
-  FOR##_mark = NULL;                                                 \
-} while (0)
-
-
-#define PROXY_CONNECTION "proxy-connection"
-#define CONNECTION "connection"
-#define CONTENT_LENGTH "content-length"
-#define TRANSFER_ENCODING "transfer-encoding"
-#define UPGRADE "upgrade"
-#define CHUNKED "chunked"
-#define KEEP_ALIVE "keep-alive"
-#define CLOSE "close"
-
-
-static const char *method_strings[] =
-  { "DELETE"
-  , "GET"
-  , "HEAD"
-  , "POST"
-  , "PUT"
-  , "CONNECT"
-  , "OPTIONS"
-  , "TRACE"
-  , "COPY"
-  , "LOCK"
-  , "MKCOL"
-  , "MOVE"
-  , "PROPFIND"
-  , "PROPPATCH"
-  , "UNLOCK"
-  , "REPORT"
-  , "MKACTIVITY"
-  , "CHECKOUT"
-  , "MERGE"
-  , "M-SEARCH"
-  , "NOTIFY"
-  , "SUBSCRIBE"
-  , "UNSUBSCRIBE"
-  };
-
-
-/* Tokens as defined by rfc 2616. Also lowercases them.
- *        token       = 1*<any CHAR except CTLs or separators>
- *     separators     = "(" | ")" | "<" | ">" | "@"
- *                    | "," | ";" | ":" | "\" | <">
- *                    | "/" | "[" | "]" | "?" | "="
- *                    | "{" | "}" | SP | HT
- */
-static const char tokens[256] = {
-/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */
-       ' ',      '!',     '"',     '#',     '$',     '%',     '&',    '\'',
-/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */
-        0,       0,      '*',     '+',      0,      '-',     '.',     '/',
-/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */
-       '0',     '1',     '2',     '3',     '4',     '5',     '6',     '7',
-/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */
-       '8',     '9',      0,       0,       0,       0,       0,       0,
-/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */
-        0,      'a',     'b',     'c',     'd',     'e',     'f',     'g',
-/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */
-       'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',
-/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */
-       'p',     'q',     'r',     's',     't',     'u',     'v',     'w',
-/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */
-       'x',     'y',     'z',      0,       0,       0,      '^',     '_',
-/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */
-       '`',     'a',     'b',     'c',     'd',     'e',     'f',     'g',
-/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */
-       'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',
-/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */
-       'p',     'q',     'r',     's',     't',     'u',     'v',     'w',
-/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */
-       'x',     'y',     'z',      0,      '|',     '}',     '~',       0 };
-
-
-static const int8_t unhex[256] =
-  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
-  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  };
-
-
-static const uint8_t normal_url_char[256] = {
-/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */
-        0,       1,       1,       0,       1,       1,       1,       1,
-/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */
-        1,       1,       1,       1,       1,       1,       1,       0,
-/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */
-        1,       1,       1,       1,       1,       1,       1,       0,
-
-/* Remainder of non-ASCII range are accepted as-is to support implicitly UTF-8
-   encoded paths. This is out of spec, but clients generate this and most other
-   HTTP servers support it. We should, too. */
-
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1 };
-
-
-enum state
-  { s_dead = 1 /* important that this is > 0 */
-
-  , s_start_req_or_res
-  , s_res_or_resp_H
-  , s_start_res
-  , s_res_H
-  , s_res_HT
-  , s_res_HTT
-  , s_res_HTTP
-  , s_res_first_http_major
-  , s_res_http_major
-  , s_res_first_http_minor
-  , s_res_http_minor
-  , s_res_first_status_code
-  , s_res_status_code
-  , s_res_status
-  , s_res_line_almost_done
-
-  , s_start_req
-
-  , s_req_method
-  , s_req_spaces_before_url
-  , s_req_schema
-  , s_req_schema_slash
-  , s_req_schema_slash_slash
-  , s_req_host
-  , s_req_port
-  , s_req_path
-  , s_req_query_string_start
-  , s_req_query_string
-  , s_req_fragment_start
-  , s_req_fragment
-  , s_req_http_start
-  , s_req_http_H
-  , s_req_http_HT
-  , s_req_http_HTT
-  , s_req_http_HTTP
-  , s_req_first_http_major
-  , s_req_http_major
-  , s_req_first_http_minor
-  , s_req_http_minor
-  , s_req_line_almost_done
-
-  , s_header_field_start
-  , s_header_field
-  , s_header_value_start
-  , s_header_value
-
-  , s_header_almost_done
-
-  , s_chunk_size_start
-  , s_chunk_size
-  , s_chunk_parameters
-  , s_chunk_size_almost_done
-  
-  , s_headers_almost_done
-  /* Important: 's_headers_almost_done' must be the last 'header' state. All
-   * states beyond this must be 'body' states. It is used for overflow
-   * checking. See the PARSING_HEADER() macro.
-   */
-
-  , s_chunk_data
-  , s_chunk_data_almost_done
-  , s_chunk_data_done
-
-  , s_body_identity
-  , s_body_identity_eof
-  };
-
-
-#define PARSING_HEADER(state) (state <= s_headers_almost_done)
-
-
-enum header_states
-  { h_general = 0
-  , h_C
-  , h_CO
-  , h_CON
-
-  , h_matching_connection
-  , h_matching_proxy_connection
-  , h_matching_content_length
-  , h_matching_transfer_encoding
-  , h_matching_upgrade
-
-  , h_connection
-  , h_content_length
-  , h_transfer_encoding
-  , h_upgrade
-
-  , h_matching_transfer_encoding_chunked
-  , h_matching_connection_keep_alive
-  , h_matching_connection_close
-
-  , h_transfer_encoding_chunked
-  , h_connection_keep_alive
-  , h_connection_close
-  };
-
-
-enum flags
-  { F_CHUNKED               = 1 << 0
-  , F_CONNECTION_KEEP_ALIVE = 1 << 1
-  , F_CONNECTION_CLOSE      = 1 << 2
-  , F_TRAILING              = 1 << 3
-  , F_UPGRADE               = 1 << 4
-  , F_SKIPBODY              = 1 << 5
-  };
-
-
-#define CR '\r'
-#define LF '\n'
-#define LOWER(c) (unsigned char)(c | 0x20)
-#define TOKEN(c) tokens[(unsigned char)c]
-
-
-#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
-
-
-#if HTTP_PARSER_STRICT
-# define STRICT_CHECK(cond) if (cond) goto error
-# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
-#else
-# define STRICT_CHECK(cond)
-# define NEW_MESSAGE() start_state
-#endif
-
-
-size_t http_parser_execute (http_parser *parser,
-                            const http_parser_settings *settings,
-                            const char *data,
-                            size_t len)
-{
-  char c, ch;
-  const char *p = data, *pe;
-  int64_t to_read;
-
-  enum state state = (enum state) parser->state;
-  enum header_states header_state = (enum header_states) parser->header_state;
-  uint64_t index = parser->index;
-  uint64_t nread = parser->nread;
-
-  if (len == 0) {
-    switch (state) {
-      case s_body_identity_eof:
-        CALLBACK2(message_complete);
-        return 0;
-
-      case s_dead:
-      case s_start_req_or_res:
-      case s_start_res:
-      case s_start_req:
-        return 0;
-
-      default:
-        return 1; // error
-    }
-  }
-
-  /* technically we could combine all of these (except for url_mark) into one
-     variable, saving stack space, but it seems more clear to have them
-     separated. */
-  const char *header_field_mark = 0;
-  const char *header_value_mark = 0;
-  const char *fragment_mark = 0;
-  const char *query_string_mark = 0;
-  const char *path_mark = 0;
-  const char *url_mark = 0;
-
-  if (state == s_header_field)
-    header_field_mark = data;
-  if (state == s_header_value)
-    header_value_mark = data;
-  if (state == s_req_fragment)
-    fragment_mark = data;
-  if (state == s_req_query_string)
-    query_string_mark = data;
-  if (state == s_req_path)
-    path_mark = data;
-  if (state == s_req_path || state == s_req_schema || state == s_req_schema_slash
-      || state == s_req_schema_slash_slash || state == s_req_port
-      || state == s_req_query_string_start || state == s_req_query_string
-      || state == s_req_host
-      || state == s_req_fragment_start || state == s_req_fragment)
-    url_mark = data;
-
-  for (p=data, pe=data+len; p != pe; p++) {
-    ch = *p;
-
-    if (PARSING_HEADER(state)) {
-      ++nread;
-      /* Buffer overflow attack */
-      if (nread > HTTP_MAX_HEADER_SIZE) goto error;
-    }
-
-    switch (state) {
-
-      case s_dead:
-        /* this state is used after a 'Connection: close' message
-         * the parser will error out if it reads another message
-         */
-        goto error;
-
-      case s_start_req_or_res:
-      {
-        if (ch == CR || ch == LF)
-          break;
-        parser->flags = 0;
-        parser->content_length = -1;
-
-        CALLBACK2(message_begin);
-
-        if (ch == 'H')
-          state = s_res_or_resp_H;
-        else {
-          parser->type = HTTP_REQUEST;
-          goto start_req_method_assign;
-        }
-        break;
-      }
-
-      case s_res_or_resp_H:
-        if (ch == 'T') {
-          parser->type = HTTP_RESPONSE;
-          state = s_res_HT;
-        } else {
-          if (ch != 'E') goto error;
-          parser->type = HTTP_REQUEST;
-          parser->method = HTTP_HEAD;
-          index = 2;
-          state = s_req_method;
-        }
-        break;
-
-      case s_start_res:
-      {
-        parser->flags = 0;
-        parser->content_length = -1;
-
-        CALLBACK2(message_begin);
-
-        switch (ch) {
-          case 'H':
-            state = s_res_H;
-            break;
-
-          case CR:
-          case LF:
-            break;
-
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_res_H:
-        STRICT_CHECK(ch != 'T');
-        state = s_res_HT;
-        break;
-
-      case s_res_HT:
-        STRICT_CHECK(ch != 'T');
-        state = s_res_HTT;
-        break;
-
-      case s_res_HTT:
-        STRICT_CHECK(ch != 'P');
-        state = s_res_HTTP;
-        break;
-
-      case s_res_HTTP:
-        STRICT_CHECK(ch != '/');
-        state = s_res_first_http_major;
-        break;
-
-      case s_res_first_http_major:
-        if (ch < '1' || ch > '9') goto error;
-        parser->http_major = ch - '0';
-        state = s_res_http_major;
-        break;
-
-      /* major HTTP version or dot */
-      case s_res_http_major:
-      {
-        if (ch == '.') {
-          state = s_res_first_http_minor;
-          break;
-        }
-
-        if (ch < '0' || ch > '9') goto error;
-
-        parser->http_major *= 10;
-        parser->http_major += ch - '0';
-
-        if (parser->http_major > 999) goto error;
-        break;
-      }
-
-      /* first digit of minor HTTP version */
-      case s_res_first_http_minor:
-        if (ch < '0' || ch > '9') goto error;
-        parser->http_minor = ch - '0';
-        state = s_res_http_minor;
-        break;
-
-      /* minor HTTP version or end of request line */
-      case s_res_http_minor:
-      {
-        if (ch == ' ') {
-          state = s_res_first_status_code;
-          break;
-        }
-
-        if (ch < '0' || ch > '9') goto error;
-
-        parser->http_minor *= 10;
-        parser->http_minor += ch - '0';
-
-        if (parser->http_minor > 999) goto error;
-        break;
-      }
-
-      case s_res_first_status_code:
-      {
-        if (ch < '0' || ch > '9') {
-          if (ch == ' ') {
-            break;
-          }
-          goto error;
-        }
-        parser->status_code = ch - '0';
-        state = s_res_status_code;
-        break;
-      }
-
-      case s_res_status_code:
-      {
-        if (ch < '0' || ch > '9') {
-          switch (ch) {
-            case ' ':
-              state = s_res_status;
-              break;
-            case CR:
-              state = s_res_line_almost_done;
-              break;
-            case LF:
-              state = s_header_field_start;
-              break;
-            default:
-              goto error;
-          }
-          break;
-        }
-
-        parser->status_code *= 10;
-        parser->status_code += ch - '0';
-
-        if (parser->status_code > 999) goto error;
-        break;
-      }
-
-      case s_res_status:
-        /* the human readable status. e.g. "NOT FOUND"
-         * we are not humans so just ignore this */
-        if (ch == CR) {
-          state = s_res_line_almost_done;
-          break;
-        }
-
-        if (ch == LF) {
-          state = s_header_field_start;
-          break;
-        }
-        break;
-
-      case s_res_line_almost_done:
-        STRICT_CHECK(ch != LF);
-        state = s_header_field_start;
-        break;
-
-      case s_start_req:
-      {
-        if (ch == CR || ch == LF)
-          break;
-        parser->flags = 0;
-        parser->content_length = -1;
-
-        CALLBACK2(message_begin);
-
-        if (ch < 'A' || 'Z' < ch) goto error;
-
-      start_req_method_assign:
-        parser->method = (enum http_method) 0;
-        index = 1;
-        switch (ch) {
-          case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
-          case 'D': parser->method = HTTP_DELETE; break;
-          case 'G': parser->method = HTTP_GET; break;
-          case 'H': parser->method = HTTP_HEAD; break;
-          case 'L': parser->method = HTTP_LOCK; break;
-          case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH */ break;
-          case 'N': parser->method = HTTP_NOTIFY; break;
-          case 'O': parser->method = HTTP_OPTIONS; break;
-          case 'P': parser->method = HTTP_POST; /* or PROPFIND or PROPPATCH or PUT */ break;
-          case 'R': parser->method = HTTP_REPORT; break;
-          case 'S': parser->method = HTTP_SUBSCRIBE; break;
-          case 'T': parser->method = HTTP_TRACE; break;
-          case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE */ break;
-          default: goto error;
-        }
-        state = s_req_method;
-        break;
-      }
-
-      case s_req_method:
-      {
-        if (ch == '\0')
-          goto error;
-
-        const char *matcher = method_strings[parser->method];
-        if (ch == ' ' && matcher[index] == '\0') {
-          state = s_req_spaces_before_url;
-        } else if (ch == matcher[index]) {
-          ; /* nada */
-        } else if (parser->method == HTTP_CONNECT) {
-          if (index == 1 && ch == 'H') {
-            parser->method = HTTP_CHECKOUT;
-          } else if (index == 2  && ch == 'P') {
-            parser->method = HTTP_COPY;
-          }
-        } else if (parser->method == HTTP_MKCOL) {
-          if (index == 1 && ch == 'O') {
-            parser->method = HTTP_MOVE;
-          } else if (index == 1 && ch == 'E') {
-            parser->method = HTTP_MERGE;
-          } else if (index == 1 && ch == '-') {
-            parser->method = HTTP_MSEARCH;
-          } else if (index == 2 && ch == 'A') {
-            parser->method = HTTP_MKACTIVITY;
-          }
-        } else if (index == 1 && parser->method == HTTP_POST && ch == 'R') {
-          parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */
-        } else if (index == 1 && parser->method == HTTP_POST && ch == 'U') {
-          parser->method = HTTP_PUT;
-        } else if (index == 2 && parser->method == HTTP_UNLOCK && ch == 'S') {
-          parser->method = HTTP_UNSUBSCRIBE;
-        } else if (index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') {
-          parser->method = HTTP_PROPPATCH;
-        } else {
-          goto error;
-        }
-
-        ++index;
-        break;
-      }
-      case s_req_spaces_before_url:
-      {
-        if (ch == ' ') break;
-
-        if (ch == '/' || ch == '*') {
-          MARK(url);
-          MARK(path);
-          state = s_req_path;
-          break;
-        }
-
-        c = LOWER(ch);
-
-        if (c >= 'a' && c <= 'z') {
-          MARK(url);
-          state = s_req_schema;
-          break;
-        }
-
-        goto error;
-      }
-
-      case s_req_schema:
-      {
-        c = LOWER(ch);
-
-        if (c >= 'a' && c <= 'z') break;
-
-        if (ch == ':') {
-          state = s_req_schema_slash;
-          break;
-        } else if (ch == '.') {
-          state = s_req_host;
-          break;
-        } else if ('0' <= ch && ch <= '9') {
-          state = s_req_host;
-          break;
-        }
-
-        goto error;
-      }
-
-      case s_req_schema_slash:
-        STRICT_CHECK(ch != '/');
-        state = s_req_schema_slash_slash;
-        break;
-
-      case s_req_schema_slash_slash:
-        STRICT_CHECK(ch != '/');
-        state = s_req_host;
-        break;
-
-      case s_req_host:
-      {
-        c = LOWER(ch);
-        if (c >= 'a' && c <= 'z') break;
-        if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') break;
-        switch (ch) {
-          case ':':
-            state = s_req_port;
-            break;
-          case '/':
-            MARK(path);
-            state = s_req_path;
-            break;
-          case ' ':
-            /* The request line looks like:
-             *   "GET http://foo.bar.com HTTP/1.1"
-             * That is, there is no path.
-             */
-            CALLBACK(url);
-            state = s_req_http_start;
-            break;
-          case '?':
-            state = s_req_query_string_start;
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_port:
-      {
-        if (ch >= '0' && ch <= '9') break;
-        switch (ch) {
-          case '/':
-            MARK(path);
-            state = s_req_path;
-            break;
-          case ' ':
-            /* The request line looks like:
-             *   "GET http://foo.bar.com:1234 HTTP/1.1"
-             * That is, there is no path.
-             */
-            CALLBACK(url);
-            state = s_req_http_start;
-            break;
-          case '?':
-            state = s_req_query_string_start;
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_path:
-      {
-        if (normal_url_char[(unsigned char)ch]) break;
-
-        switch (ch) {
-          case ' ':
-            CALLBACK(url);
-            CALLBACK(path);
-            state = s_req_http_start;
-            break;
-          case CR:
-            CALLBACK(url);
-            CALLBACK(path);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_req_line_almost_done;
-            break;
-          case LF:
-            CALLBACK(url);
-            CALLBACK(path);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_header_field_start;
-            break;
-          case '?':
-            CALLBACK(path);
-            state = s_req_query_string_start;
-            break;
-          case '#':
-            CALLBACK(path);
-            state = s_req_fragment_start;
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_query_string_start:
-      {
-        if (normal_url_char[(unsigned char)ch]) {
-          MARK(query_string);
-          state = s_req_query_string;
-          break;
-        }
-
-        switch (ch) {
-          case '?':
-            break; /* XXX ignore extra '?' ... is this right? */
-          case ' ':
-            CALLBACK(url);
-            state = s_req_http_start;
-            break;
-          case CR:
-            CALLBACK(url);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_req_line_almost_done;
-            break;
-          case LF:
-            CALLBACK(url);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_header_field_start;
-            break;
-          case '#':
-            state = s_req_fragment_start;
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_query_string:
-      {
-        if (normal_url_char[(unsigned char)ch]) break;
-
-        switch (ch) {
-          case '?':
-            /* allow extra '?' in query string */
-            break;
-          case ' ':
-            CALLBACK(url);
-            CALLBACK(query_string);
-            state = s_req_http_start;
-            break;
-          case CR:
-            CALLBACK(url);
-            CALLBACK(query_string);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_req_line_almost_done;
-            break;
-          case LF:
-            CALLBACK(url);
-            CALLBACK(query_string);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_header_field_start;
-            break;
-          case '#':
-            CALLBACK(query_string);
-            state = s_req_fragment_start;
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_fragment_start:
-      {
-        if (normal_url_char[(unsigned char)ch]) {
-          MARK(fragment);
-          state = s_req_fragment;
-          break;
-        }
-
-        switch (ch) {
-          case ' ':
-            CALLBACK(url);
-            state = s_req_http_start;
-            break;
-          case CR:
-            CALLBACK(url);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_req_line_almost_done;
-            break;
-          case LF:
-            CALLBACK(url);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_header_field_start;
-            break;
-          case '?':
-            MARK(fragment);
-            state = s_req_fragment;
-            break;
-          case '#':
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_fragment:
-      {
-        if (normal_url_char[(unsigned char)ch]) break;
-
-        switch (ch) {
-          case ' ':
-            CALLBACK(url);
-            CALLBACK(fragment);
-            state = s_req_http_start;
-            break;
-          case CR:
-            CALLBACK(url);
-            CALLBACK(fragment);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_req_line_almost_done;
-            break;
-          case LF:
-            CALLBACK(url);
-            CALLBACK(fragment);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_header_field_start;
-            break;
-          case '?':
-          case '#':
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_http_start:
-        switch (ch) {
-          case 'H':
-            state = s_req_http_H;
-            break;
-          case ' ':
-            break;
-          default:
-            goto error;
-        }
-        break;
-
-      case s_req_http_H:
-        STRICT_CHECK(ch != 'T');
-        state = s_req_http_HT;
-        break;
-
-      case s_req_http_HT:
-        STRICT_CHECK(ch != 'T');
-        state = s_req_http_HTT;
-        break;
-
-      case s_req_http_HTT:
-        STRICT_CHECK(ch != 'P');
-        state = s_req_http_HTTP;
-        break;
-
-      case s_req_http_HTTP:
-        STRICT_CHECK(ch != '/');
-        state = s_req_first_http_major;
-        break;
-
-      /* first digit of major HTTP version */
-      case s_req_first_http_major:
-        if (ch < '1' || ch > '9') goto error;
-        parser->http_major = ch - '0';
-        state = s_req_http_major;
-        break;
-
-      /* major HTTP version or dot */
-      case s_req_http_major:
-      {
-        if (ch == '.') {
-          state = s_req_first_http_minor;
-          break;
-        }
-
-        if (ch < '0' || ch > '9') goto error;
-
-        parser->http_major *= 10;
-        parser->http_major += ch - '0';
-
-        if (parser->http_major > 999) goto error;
-        break;
-      }
-
-      /* first digit of minor HTTP version */
-      case s_req_first_http_minor:
-        if (ch < '0' || ch > '9') goto error;
-        parser->http_minor = ch - '0';
-        state = s_req_http_minor;
-        break;
-
-      /* minor HTTP version or end of request line */
-      case s_req_http_minor:
-      {
-        if (ch == CR) {
-          state = s_req_line_almost_done;
-          break;
-        }
-
-        if (ch == LF) {
-          state = s_header_field_start;
-          break;
-        }
-
-        /* XXX allow spaces after digit? */
-
-        if (ch < '0' || ch > '9') goto error;
-
-        parser->http_minor *= 10;
-        parser->http_minor += ch - '0';
-
-        if (parser->http_minor > 999) goto error;
-        break;
-      }
-
-      /* end of request line */
-      case s_req_line_almost_done:
-      {
-        if (ch != LF) goto error;
-        state = s_header_field_start;
-        break;
-      }
-
-      case s_header_field_start:
-      {
-        if (ch == CR) {
-          state = s_headers_almost_done;
-          break;
-        }
-
-        if (ch == LF) {
-          /* they might be just sending \n instead of \r\n so this would be
-           * the second \n to denote the end of headers*/
-          state = s_headers_almost_done;
-          goto headers_almost_done;
-        }
-
-        c = TOKEN(ch);
-
-        if (!c) goto error;
-
-        MARK(header_field);
-
-        index = 0;
-        state = s_header_field;
-
-        switch (c) {
-          case 'c':
-            header_state = h_C;
-            break;
-
-          case 'p':
-            header_state = h_matching_proxy_connection;
-            break;
-
-          case 't':
-            header_state = h_matching_transfer_encoding;
-            break;
-
-          case 'u':
-            header_state = h_matching_upgrade;
-            break;
-
-          default:
-            header_state = h_general;
-            break;
-        }
-        break;
-      }
-
-      case s_header_field:
-      {
-        c = TOKEN(ch);
-
-        if (c) {
-          switch (header_state) {
-            case h_general:
-              break;
-
-            case h_C:
-              index++;
-              header_state = (c == 'o' ? h_CO : h_general);
-              break;
-
-            case h_CO:
-              index++;
-              header_state = (c == 'n' ? h_CON : h_general);
-              break;
-
-            case h_CON:
-              index++;
-              switch (c) {
-                case 'n':
-                  header_state = h_matching_connection;
-                  break;
-                case 't':
-                  header_state = h_matching_content_length;
-                  break;
-                default:
-                  header_state = h_general;
-                  break;
-              }
-              break;
-
-            /* connection */
-
-            case h_matching_connection:
-              index++;
-              if (index > sizeof(CONNECTION)-1
-                  || c != CONNECTION[index]) {
-                header_state = h_general;
-              } else if (index == sizeof(CONNECTION)-2) {
-                header_state = h_connection;
-              }
-              break;
-
-            /* proxy-connection */
-
-            case h_matching_proxy_connection:
-              index++;
-              if (index > sizeof(PROXY_CONNECTION)-1
-                  || c != PROXY_CONNECTION[index]) {
-                header_state = h_general;
-              } else if (index == sizeof(PROXY_CONNECTION)-2) {
-                header_state = h_connection;
-              }
-              break;
-
-            /* content-length */
-
-            case h_matching_content_length:
-              index++;
-              if (index > sizeof(CONTENT_LENGTH)-1
-                  || c != CONTENT_LENGTH[index]) {
-                header_state = h_general;
-              } else if (index == sizeof(CONTENT_LENGTH)-2) {
-                header_state = h_content_length;
-              }
-              break;
-
-            /* transfer-encoding */
-
-            case h_matching_transfer_encoding:
-              index++;
-              if (index > sizeof(TRANSFER_ENCODING)-1
-                  || c != TRANSFER_ENCODING[index]) {
-                header_state = h_general;
-              } else if (index == sizeof(TRANSFER_ENCODING)-2) {
-                header_state = h_transfer_encoding;
-              }
-              break;
-
-            /* upgrade */
-
-            case h_matching_upgrade:
-              index++;
-              if (index > sizeof(UPGRADE)-1
-                  || c != UPGRADE[index]) {
-                header_state = h_general;
-              } else if (index == sizeof(UPGRADE)-2) {
-                header_state = h_upgrade;
-              }
-              break;
-
-            case h_connection:
-            case h_content_length:
-            case h_transfer_encoding:
-            case h_upgrade:
-              if (ch != ' ') header_state = h_general;
-              break;
-
-            default:
-              assert(0 && "Unknown header_state");
-              break;
-          }
-          break;
-        }
-
-        if (ch == ':') {
-          CALLBACK(header_field);
-          state = s_header_value_start;
-          break;
-        }
-
-        if (ch == CR) {
-          state = s_header_almost_done;
-          CALLBACK(header_field);
-          break;
-        }
-
-        if (ch == LF) {
-          CALLBACK(header_field);
-          state = s_header_field_start;
-          break;
-        }
-
-        goto error;
-      }
-
-      case s_header_value_start:
-      {
-        if (ch == ' ') break;
-
-        MARK(header_value);
-
-        state = s_header_value;
-        index = 0;
-
-        c = LOWER(ch);
-
-        if (ch == CR) {
-          CALLBACK(header_value);
-          header_state = h_general;
-          state = s_header_almost_done;
-          break;
-        }
-
-        if (ch == LF) {
-          CALLBACK(header_value);
-          state = s_header_field_start;
-          break;
-        }
-
-        switch (header_state) {
-          case h_upgrade:
-            parser->flags |= F_UPGRADE;
-            header_state = h_general;
-            break;
-
-          case h_transfer_encoding:
-            /* looking for 'Transfer-Encoding: chunked' */
-            if ('c' == c) {
-              header_state = h_matching_transfer_encoding_chunked;
-            } else {
-              header_state = h_general;
-            }
-            break;
-
-          case h_content_length:
-            if (ch < '0' || ch > '9') goto error;
-            parser->content_length = ch - '0';
-            break;
-
-          case h_connection:
-            /* looking for 'Connection: keep-alive' */
-            if (c == 'k') {
-              header_state = h_matching_connection_keep_alive;
-            /* looking for 'Connection: close' */
-            } else if (c == 'c') {
-              header_state = h_matching_connection_close;
-            } else {
-              header_state = h_general;
-            }
-            break;
-
-          default:
-            header_state = h_general;
-            break;
-        }
-        break;
-      }
-
-      case s_header_value:
-      {
-        c = LOWER(ch);
-
-        if (ch == CR) {
-          CALLBACK(header_value);
-          state = s_header_almost_done;
-          break;
-        }
-
-        if (ch == LF) {
-          CALLBACK(header_value);
-          goto header_almost_done;
-        }
-
-        switch (header_state) {
-          case h_general:
-            break;
-
-          case h_connection:
-          case h_transfer_encoding:
-            assert(0 && "Shouldn't get here.");
-            break;
-
-          case h_content_length:
-            if (ch == ' ') break;
-            if (ch < '0' || ch > '9') goto error;
-            parser->content_length *= 10;
-            parser->content_length += ch - '0';
-            break;
-
-          /* Transfer-Encoding: chunked */
-          case h_matching_transfer_encoding_chunked:
-            index++;
-            if (index > sizeof(CHUNKED)-1
-                || c != CHUNKED[index]) {
-              header_state = h_general;
-            } else if (index == sizeof(CHUNKED)-2) {
-              header_state = h_transfer_encoding_chunked;
-            }
-            break;
-
-          /* looking for 'Connection: keep-alive' */
-          case h_matching_connection_keep_alive:
-            index++;
-            if (index > sizeof(KEEP_ALIVE)-1
-                || c != KEEP_ALIVE[index]) {
-              header_state = h_general;
-            } else if (index == sizeof(KEEP_ALIVE)-2) {
-              header_state = h_connection_keep_alive;
-            }
-            break;
-
-          /* looking for 'Connection: close' */
-          case h_matching_connection_close:
-            index++;
-            if (index > sizeof(CLOSE)-1 || c != CLOSE[index]) {
-              header_state = h_general;
-            } else if (index == sizeof(CLOSE)-2) {
-              header_state = h_connection_close;
-            }
-            break;
-
-          case h_transfer_encoding_chunked:
-          case h_connection_keep_alive:
-          case h_connection_close:
-            if (ch != ' ') header_state = h_general;
-            break;
-
-          default:
-            state = s_header_value;
-            header_state = h_general;
-            break;
-        }
-        break;
-      }
-
-      case s_header_almost_done:
-      header_almost_done:
-      {
-        STRICT_CHECK(ch != LF);
-
-        state = s_header_field_start;
-
-        switch (header_state) {
-          case h_connection_keep_alive:
-            parser->flags |= F_CONNECTION_KEEP_ALIVE;
-            break;
-          case h_connection_close:
-            parser->flags |= F_CONNECTION_CLOSE;
-            break;
-          case h_transfer_encoding_chunked:
-            parser->flags |= F_CHUNKED;
-            break;
-          default:
-            break;
-        }
-        break;
-      }
-
-      case s_headers_almost_done:
-      headers_almost_done:
-      {
-        STRICT_CHECK(ch != LF);
-
-        if (parser->flags & F_TRAILING) {
-          /* End of a chunked request */
-          CALLBACK2(message_complete);
-          state = NEW_MESSAGE();
-          break;
-        }
-
-        nread = 0;
-
-        if (parser->flags & F_UPGRADE || parser->method == HTTP_CONNECT) {
-          parser->upgrade = 1;
-        }
-
-        /* Here we call the headers_complete callback. This is somewhat
-         * different than other callbacks because if the user returns 1, we
-         * will interpret that as saying that this message has no body. This
-         * is needed for the annoying case of recieving a response to a HEAD
-         * request.
-         */
-        if (settings->on_headers_complete) {
-          switch (settings->on_headers_complete(parser)) {
-            case 0:
-              break;
-
-            case 1:
-              parser->flags |= F_SKIPBODY;
-              break;
-
-            default:
-              parser->state = state;
-              return p - data; /* Error */
-          }
-        }
-
-        /* Exit, the rest of the connect is in a different protocol. */
-        if (parser->upgrade) {
-          CALLBACK2(message_complete);
-          return (p - data);
-        }
-
-        if (parser->flags & F_SKIPBODY) {
-          CALLBACK2(message_complete);
-          state = NEW_MESSAGE();
-        } else if (parser->flags & F_CHUNKED) {
-          /* chunked encoding - ignore Content-Length header */
-          state = s_chunk_size_start;
-        } else {
-          if (parser->content_length == 0) {
-            /* Content-Length header given but zero: Content-Length: 0\r\n */
-            CALLBACK2(message_complete);
-            state = NEW_MESSAGE();
-          } else if (parser->content_length > 0) {
-            /* Content-Length header given and non-zero */
-            state = s_body_identity;
-          } else {
-            if (parser->type == HTTP_REQUEST || http_should_keep_alive(parser)) {
-              /* Assume content-length 0 - read the next */
-              CALLBACK2(message_complete);
-              state = NEW_MESSAGE();
-            } else {
-              /* Read body until EOF */
-              state = s_body_identity_eof;
-            }
-          }
-        }
-
-        break;
-      }
-
-      case s_body_identity:
-        to_read = MIN(pe - p, (int64_t)parser->content_length);
-        if (to_read > 0) {
-          if (settings->on_body) settings->on_body(parser, p, to_read);
-          p += to_read - 1;
-          parser->content_length -= to_read;
-          if (parser->content_length == 0) {
-            CALLBACK2(message_complete);
-            state = NEW_MESSAGE();
-          }
-        }
-        break;
-
-      /* read until EOF */
-      case s_body_identity_eof:
-        to_read = pe - p;
-        if (to_read > 0) {
-          if (settings->on_body) settings->on_body(parser, p, to_read);
-          p += to_read - 1;
-        }
-        break;
-
-      case s_chunk_size_start:
-      {
-        assert(nread == 1);
-        assert(parser->flags & F_CHUNKED);
-
-        c = unhex[(unsigned char)ch];
-        if (c == -1) goto error;
-        parser->content_length = c;
-        state = s_chunk_size;
-        break;
-      }
-
-      case s_chunk_size:
-      {
-        assert(parser->flags & F_CHUNKED);
-
-        if (ch == CR) {
-          state = s_chunk_size_almost_done;
-          break;
-        }
-
-        c = unhex[(unsigned char)ch];
-
-        if (c == -1) {
-          if (ch == ';' || ch == ' ') {
-            state = s_chunk_parameters;
-            break;
-          }
-          goto error;
-        }
-
-        parser->content_length *= 16;
-        parser->content_length += c;
-        break;
-      }
-
-      case s_chunk_parameters:
-      {
-        assert(parser->flags & F_CHUNKED);
-        /* just ignore this shit. TODO check for overflow */
-        if (ch == CR) {
-          state = s_chunk_size_almost_done;
-          break;
-        }
-        break;
-      }
-
-      case s_chunk_size_almost_done:
-      {
-        assert(parser->flags & F_CHUNKED);
-        STRICT_CHECK(ch != LF);
-
-        nread = 0;
-
-        if (parser->content_length == 0) {
-          parser->flags |= F_TRAILING;
-          state = s_header_field_start;
-        } else {
-          state = s_chunk_data;
-        }
-        break;
-      }
-
-      case s_chunk_data:
-      {
-        assert(parser->flags & F_CHUNKED);
-
-        to_read = MIN(pe - p, (int64_t)(parser->content_length));
-
-        if (to_read > 0) {
-          if (settings->on_body) settings->on_body(parser, p, to_read);
-          p += to_read - 1;
-        }
-
-        if (to_read == parser->content_length) {
-          state = s_chunk_data_almost_done;
-        }
-
-        parser->content_length -= to_read;
-        break;
-      }
-
-      case s_chunk_data_almost_done:
-        assert(parser->flags & F_CHUNKED);
-        STRICT_CHECK(ch != CR);
-        state = s_chunk_data_done;
-        break;
-
-      case s_chunk_data_done:
-        assert(parser->flags & F_CHUNKED);
-        STRICT_CHECK(ch != LF);
-        state = s_chunk_size_start;
-        break;
-
-      default:
-        assert(0 && "unhandled state");
-        goto error;
-    }
-  }
-
-  CALLBACK_NOCLEAR(header_field);
-  CALLBACK_NOCLEAR(header_value);
-  CALLBACK_NOCLEAR(fragment);
-  CALLBACK_NOCLEAR(query_string);
-  CALLBACK_NOCLEAR(path);
-  CALLBACK_NOCLEAR(url);
-
-  parser->state = state;
-  parser->header_state = header_state;
-  parser->index = index;
-  parser->nread = nread;
-
-  return len;
-
-error:
-  parser->state = s_dead;
-  return (p - data);
-}
-
-
-int
-http_should_keep_alive (http_parser *parser)
-{
-  if (parser->http_major > 0 && parser->http_minor > 0) {
-    /* HTTP/1.1 */
-    if (parser->flags & F_CONNECTION_CLOSE) {
-      return 0;
-    } else {
-      return 1;
-    }
-  } else {
-    /* HTTP/1.0 or earlier */
-    if (parser->flags & F_CONNECTION_KEEP_ALIVE) {
-      return 1;
-    } else {
-      return 0;
-    }
-  }
-}
-
-
-const char * http_method_str (enum http_method m)
-{
-  return method_strings[m];
-}
-
-
-void
-http_parser_init (http_parser *parser, enum http_parser_type t)
-{
-  parser->type = t;
-  parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
-  parser->nread = 0;
-  parser->upgrade = 0;
-  parser->flags = 0;
-  parser->method = 0;
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/http_parser.h b/ext/ruby_http_parser/vendor/http-parser-java/http_parser.h
deleted file mode 100644
index 9c7a26d..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/http_parser.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#ifndef http_parser_h
-#define http_parser_h
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define HTTP_PARSER_VERSION_MAJOR 1
-#define HTTP_PARSER_VERSION_MINOR 0
-
-#include <sys/types.h>
-#if defined(_WIN32) && !defined(__MINGW32__)
-typedef __int8 int8_t;
-typedef unsigned __int8 uint8_t;
-typedef __int16 int16_t;
-typedef unsigned __int16 uint16_t;
-typedef __int32 int32_t;
-typedef unsigned __int32 uint32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-
-typedef unsigned int size_t;
-typedef int ssize_t;
-#else
-#include <stdint.h>
-#endif
-
-/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
- * faster
- */
-#ifndef HTTP_PARSER_STRICT
-# define HTTP_PARSER_STRICT 1
-#else
-# define HTTP_PARSER_STRICT 0
-#endif
-
-
-/* Maximium header size allowed */
-#define HTTP_MAX_HEADER_SIZE (80*1024)
-
-
-typedef struct http_parser http_parser;
-typedef struct http_parser_settings http_parser_settings;
-
-
-/* Callbacks should return non-zero to indicate an error. The parser will
- * then halt execution.
- *
- * The one exception is on_headers_complete. In a HTTP_RESPONSE parser
- * returning '1' from on_headers_complete will tell the parser that it
- * should not expect a body. This is used when receiving a response to a
- * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
- * chunked' headers that indicate the presence of a body.
- *
- * http_data_cb does not return data chunks. It will be call arbitrarally
- * many times for each string. E.G. you might get 10 callbacks for "on_path"
- * each providing just a few characters more data.
- */
-typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
-typedef int (*http_cb) (http_parser*);
-
-
-/* Request Methods */
-enum http_method
-  { HTTP_DELETE    = 0
-  , HTTP_GET
-  , HTTP_HEAD
-  , HTTP_POST
-  , HTTP_PUT
-  /* pathological */
-  , HTTP_CONNECT
-  , HTTP_OPTIONS
-  , HTTP_TRACE
-  /* webdav */
-  , HTTP_COPY
-  , HTTP_LOCK
-  , HTTP_MKCOL
-  , HTTP_MOVE
-  , HTTP_PROPFIND
-  , HTTP_PROPPATCH
-  , HTTP_UNLOCK
-  /* subversion */
-  , HTTP_REPORT
-  , HTTP_MKACTIVITY
-  , HTTP_CHECKOUT
-  , HTTP_MERGE
-  /* upnp */
-  , HTTP_MSEARCH
-  , HTTP_NOTIFY
-  , HTTP_SUBSCRIBE
-  , HTTP_UNSUBSCRIBE
-  };
-
-
-enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
-
-
-struct http_parser {
-  /** PRIVATE **/
-  unsigned char type : 2;
-  unsigned char flags : 6;
-  unsigned char state;
-  unsigned char header_state;
-  unsigned char index;
-
-  uint32_t nread;
-  int64_t content_length;
-
-  /** READ-ONLY **/
-  unsigned short http_major;
-  unsigned short http_minor;
-  unsigned short status_code; /* responses only */
-  unsigned char method;    /* requests only */
-
-  /* 1 = Upgrade header was present and the parser has exited because of that.
-   * 0 = No upgrade header present.
-   * Should be checked when http_parser_execute() returns in addition to
-   * error checking.
-   */
-  char upgrade;
-
-  /** PUBLIC **/
-  void *data; /* A pointer to get hook to the "connection" or "socket" object */
-};
-
-
-struct http_parser_settings {
-  http_cb      on_message_begin;
-  http_data_cb on_path;
-  http_data_cb on_query_string;
-  http_data_cb on_url;
-  http_data_cb on_fragment;
-  http_data_cb on_header_field;
-  http_data_cb on_header_value;
-  http_cb      on_headers_complete;
-  http_data_cb on_body;
-  http_cb      on_message_complete;
-};
-
-
-void http_parser_init(http_parser *parser, enum http_parser_type type);
-
-
-size_t http_parser_execute(http_parser *parser,
-                           const http_parser_settings *settings,
-                           const char *data,
-                           size_t len);
-
-
-/* If http_should_keep_alive() in the on_headers_complete or
- * on_message_complete callback returns true, then this will be should be
- * the last message on the connection.
- * If you are the server, respond with the "Connection: close" header.
- * If you are the client, close the connection.
- */
-int http_should_keep_alive(http_parser *parser);
-
-/* Returns a string version of the HTTP method. */
-const char *http_method_str(enum http_method);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPCallback.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPCallback.java
deleted file mode 100644
index 5380b0f..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPCallback.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package http_parser;
-
-public abstract class HTTPCallback implements http_parser.lolevel.HTTPCallback{
-	public int cb (http_parser.lolevel.HTTPParser parser) {
-	  return this.cb((HTTPParser)parser);
-	}
-	public abstract int cb (HTTPParser parser);
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPDataCallback.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPDataCallback.java
deleted file mode 100644
index bfe576f..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPDataCallback.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package http_parser;
-
-import java.nio.ByteBuffer;
-
-public abstract class HTTPDataCallback implements  http_parser.lolevel.HTTPDataCallback{
-	/*
-		Very raw and extremly foolhardy! DANGER!
-		The whole Buffer concept is difficult enough to grasp as it is,
-		we pass in a buffer with an arbitrary position.
-
-		The interesting data is located at position pos and is len 
-		bytes long.
-		
-		The contract of this callback is that the buffer is
-		returned in the state that it was passed in, so implementing
-		this require good citizenship, you'll need to remember the current
-		position, change the position to get at the data you're interested 
-		in and then set the position back to how you found it...
-
-		Therefore: there is an abstract implementation that implements
-		cb as described above, and provides a new callback
-		with signature @see cb(byte[], int, int)
-	*/
-	public int cb(http_parser.lolevel.HTTPParser p, ByteBuffer buf, int pos, int len) {
-	  byte [] by = new byte[len];
-    int saved = buf.position();
-    buf.position(pos);
-    buf.get(by);
-    buf.position(saved);
-    return cb((HTTPParser)p, by, 0, len);
-	}
-
-  public abstract int cb(HTTPParser p, byte[] by, int pos, int len);
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPErrorCallback.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPErrorCallback.java
deleted file mode 100644
index a74206e..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPErrorCallback.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package http_parser;
-
-
-import java.nio.ByteBuffer;
-
-public abstract class HTTPErrorCallback implements http_parser.lolevel.HTTPErrorCallback{
-	public void cb (http_parser.lolevel.HTTPParser parser, String mes, ByteBuffer buf, int initial_position) {
-	  this.cb((HTTPParser)parser, Util.error(mes, buf, initial_position));
-	}
-
-  public abstract void cb(HTTPParser parser, String error); 
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPException.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPException.java
deleted file mode 100644
index 9ccaf14..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package http_parser;
-
- at SuppressWarnings("serial")
-public class HTTPException extends RuntimeException {
-  
-public HTTPException(String mes) {
-    super(mes);
-  }  
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java
deleted file mode 100644
index 8c4b1ed..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package http_parser;
-
-import java.nio.charset.Charset;
-
-public enum HTTPMethod {
-    HTTP_DELETE("DELETE")//    = 0
-  , HTTP_GET("GET")
-  , HTTP_HEAD("HEAD")
-  , HTTP_POST("POST")
-  , HTTP_PUT("PUT")
-  /* pathological */
-  , HTTP_CONNECT("CONNECT")
-  , HTTP_OPTIONS("OPTIONS")
-  , HTTP_TRACE("TRACE")
-  /* webdav */
-  , HTTP_COPY("COPY")
-  , HTTP_LOCK("LOCK")
-  , HTTP_MKCOL("MKCOL")
-  , HTTP_MOVE("MOVE")
-  , HTTP_PROPFIND("PROPFIND")
-  , HTTP_PROPPATCH("PROPPATCH")
-  , HTTP_UNLOCK("UNLOCK")
-  , HTTP_REPORT("REPORT")
-  , HTTP_MKACTIVITY("MKACTIVITY")
-  , HTTP_CHECKOUT("CHECKOUT")
-  , HTTP_MERGE("MERGE")
-  , HTTP_MSEARCH("M-SEARCH")
-  , HTTP_NOTIFY("NOTIFY")
-  , HTTP_SUBSCRIBE("SUBSCRIBE")
-  , HTTP_UNSUBSCRIBE("UNSUBSCRIBE")
-  
-  ;
-
-  private static Charset ASCII;
-  static {
-    ASCII = Charset.forName("US-ASCII");;
-  }
-  public byte[] bytes;
-
-  HTTPMethod(String name) {
-    // good grief, Charlie Brown, the following is necessary because 
-    // java is retarded:
-    // illegal reference to static field from initializer
-    //            this.bytes = name.getBytes(ASCII);
-    // yet it's not illegal to reference static fields from
-    // methods called from initializer.
-    init(name);
-  }
-  public static HTTPMethod parse(String s) {
-         if ("HTTP_DELETE".equalsIgnoreCase(s))  {return HTTP_DELETE;}
-    else if ("DELETE".equalsIgnoreCase(s))       {return HTTP_DELETE;}
-    else if ("HTTP_GET".equalsIgnoreCase(s))     {return HTTP_GET;}
-    else if ("GET".equalsIgnoreCase(s))          {return HTTP_GET;}
-    else if ("HTTP_HEAD".equalsIgnoreCase(s))    {return HTTP_HEAD;}
-    else if ("HEAD".equalsIgnoreCase(s))         {return HTTP_HEAD;}
-    else if ("HTTP_POST".equalsIgnoreCase(s))    {return HTTP_POST;}
-    else if ("POST".equalsIgnoreCase(s))         {return HTTP_POST;}
-    else if ("HTTP_PUT".equalsIgnoreCase(s))     {return HTTP_PUT;}
-    else if ("PUT".equalsIgnoreCase(s))          {return HTTP_PUT;}
-    else if ("HTTP_CONNECT".equalsIgnoreCase(s)) {return HTTP_CONNECT;}
-    else if ("CONNECT".equalsIgnoreCase(s))      {return HTTP_CONNECT;}
-    else if ("HTTP_OPTIONS".equalsIgnoreCase(s)) {return HTTP_OPTIONS;}
-    else if ("OPTIONS".equalsIgnoreCase(s))      {return HTTP_OPTIONS;}
-    else if ("HTTP_TRACE".equalsIgnoreCase(s))   {return HTTP_TRACE;}
-    else if ("TRACE".equalsIgnoreCase(s))        {return HTTP_TRACE;}
-    else if ("HTTP_COPY".equalsIgnoreCase(s))    {return HTTP_COPY;}
-    else if ("COPY".equalsIgnoreCase(s))         {return HTTP_COPY;}
-    else if ("HTTP_LOCK".equalsIgnoreCase(s))    {return HTTP_LOCK;}
-    else if ("LOCK".equalsIgnoreCase(s))         {return HTTP_LOCK;}
-    else if ("HTTP_MKCOL".equalsIgnoreCase(s))   {return HTTP_MKCOL;}
-    else if ("MKCOL".equalsIgnoreCase(s))        {return HTTP_MKCOL;}
-    else if ("HTTP_MOVE".equalsIgnoreCase(s))    {return HTTP_MOVE;}
-    else if ("MOVE".equalsIgnoreCase(s))         {return HTTP_MOVE;}
-    else if ("HTTP_PROPFIND".equalsIgnoreCase(s)){return HTTP_PROPFIND;}
-    else if ("PROPFIND".equalsIgnoreCase(s))     {return HTTP_PROPFIND;}
-    else if ("HTTP_PROPPATCH".equalsIgnoreCase(s)){return HTTP_PROPPATCH;}
-    else if ("PROPPATCH".equalsIgnoreCase(s))    {return HTTP_PROPPATCH;}
-    else if ("HTTP_UNLOCK".equalsIgnoreCase(s))  {return HTTP_UNLOCK;}
-    else if ("UNLOCK".equalsIgnoreCase(s))       {return HTTP_UNLOCK;}
-    else if ("HTTP_REPORT".equalsIgnoreCase(s)) {return HTTP_REPORT;}
-    else if ("REPORT".equalsIgnoreCase(s)){return HTTP_REPORT;}
-    else if ("HTTP_MKACTIVITY".equalsIgnoreCase(s)) {return HTTP_MKACTIVITY;}
-    else if ("MKACTIVITY".equalsIgnoreCase(s)){return HTTP_MKACTIVITY;}
-    else if ("HTTP_CHECKOUT".equalsIgnoreCase(s)) {return HTTP_CHECKOUT;}
-    else if ("CHECKOUT".equalsIgnoreCase(s)){return HTTP_CHECKOUT;}
-    else if ("HTTP_MERGE".equalsIgnoreCase(s)) {return HTTP_MERGE;}
-    else if ("MERGE".equalsIgnoreCase(s)){return HTTP_MERGE;}
-    else if ("HTTP_MSEARCH".equalsIgnoreCase(s))     {return HTTP_MSEARCH;}
-    else if ("M-SEARCH".equalsIgnoreCase(s))         {return HTTP_MSEARCH;}
-    else if ("HTTP_NOTIFY".equalsIgnoreCase(s))      {return HTTP_NOTIFY;}
-    else if ("NOTIFY".equalsIgnoreCase(s))           {return HTTP_NOTIFY;}
-    else if ("HTTP_SUBSCRIBE".equalsIgnoreCase(s))   {return HTTP_SUBSCRIBE;}
-    else if ("SUBSCRIBE".equalsIgnoreCase(s))        {return HTTP_SUBSCRIBE;}
-    else if ("HTTP_UNSUBSCRIBE".equalsIgnoreCase(s)) {return HTTP_UNSUBSCRIBE;}
-    else if ("UNSUBSCRIBE".equalsIgnoreCase(s))      {return HTTP_UNSUBSCRIBE;}
-	  else                                             {return null;}
-	}	
-  void init (String name) {
-    ASCII = null == ASCII ? Charset.forName("US-ASCII") : ASCII;
-    this.bytes = name.getBytes(ASCII);
-  }
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParser.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParser.java
deleted file mode 100644
index 7ab4fb4..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParser.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package http_parser;
-
-import java.nio.ByteBuffer;
-
-public class HTTPParser extends http_parser.lolevel.HTTPParser {
-  
-  public HTTPParser() { super(); }
-  public HTTPParser(ParserType type) { super(type); }
-
-  public int getMajor() {
-    return super.http_major;
-  }
-
-  public int getMinor() {
-    return super.http_minor;
-  }
-
-  public int getStatusCode() {
-    return super.status_code;
-  }
-
-  public HTTPMethod getHTTPMethod() {
-    return super.method;
-  }
-
-  public boolean getUpgrade() {
-    return super.upgrade;
-  }
-  
-  public boolean shouldKeepAlive() {
-    return super.http_should_keep_alive();
-  }
-  public void execute(ParserSettings settings, ByteBuffer data) {
-   this.execute(settings.getLoLevelSettings(), data);
-  }
-} 
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java
deleted file mode 100644
index 058002a..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java
+++ /dev/null
@@ -1,323 +0,0 @@
-package http_parser;
-
-
-
-import primitive.collection.ByteList;
-
-public class ParserSettings extends http_parser.lolevel.ParserSettings {
-  
-  public HTTPCallback       on_message_begin;
-  public HTTPDataCallback   on_path;
-  public HTTPDataCallback   on_query_string;
-  public HTTPDataCallback   on_url;
-  public HTTPDataCallback   on_fragment;
-  public HTTPDataCallback   on_header_field;
-  public HTTPDataCallback   on_header_value;
- 
-  public HTTPCallback       on_headers_complete;
-  public HTTPDataCallback   on_body;
-  public HTTPCallback       on_message_complete;
-  
-  public HTTPErrorCallback  on_error;
-  
-  private HTTPCallback      _on_message_begin;
-  private HTTPDataCallback  _on_path;
-  private HTTPDataCallback  _on_query_string;
-  private HTTPDataCallback  _on_url;
-  private HTTPDataCallback  _on_fragment;
-  private HTTPDataCallback  _on_header_field;
-  private HTTPDataCallback  _on_header_value;
-  private HTTPCallback      _on_headers_complete;
-  private HTTPDataCallback  _on_body;
-  private HTTPCallback      _on_message_complete;
-  private HTTPErrorCallback _on_error;
-  
-  private http_parser.lolevel.ParserSettings settings;
-  
-  protected ByteList field = new ByteList();
-  protected ByteList value = new ByteList();
-  protected ByteList body  = new ByteList();
-  
-  public ParserSettings() {
-    this.settings = new http_parser.lolevel.ParserSettings();
-    createMirrorCallbacks();
-    attachCallbacks();
-  }
-  
-  protected http_parser.lolevel.ParserSettings getLoLevelSettings() {
-    return this.settings;
-  }
-
-  private void createMirrorCallbacks() {
-    this._on_message_begin = new HTTPCallback() {
-      public int cb(HTTPParser p) {
-        if (null != ParserSettings.this.on_message_begin) {
-          return ParserSettings.this.on_message_begin.cb(p);
-        }
-        return 0;
-      }
-    };
-    this._on_path = new HTTPDataCallback() {
-      @Override
-      public int cb(HTTPParser p, byte[] by, int pos, int len) {
-        if (null != ParserSettings.this.on_path) {
-          return ParserSettings.this.on_path.cb(p, by, pos, len);
-        }
-        return 0;
-      }
-    };
-    this._on_query_string = new HTTPDataCallback() {
-      @Override
-      public int cb(HTTPParser p, byte[] by, int pos, int len) {
-        if (null != ParserSettings.this.on_query_string) {
-          return ParserSettings.this.on_query_string.cb(p, by, pos, len);
-        }
-        return 0;
-      }
-    };
-    this._on_url = new HTTPDataCallback() {
-      @Override
-      public int cb(HTTPParser p, byte[] by, int pos, int len) {
-        if (null != ParserSettings.this.on_url) {
-          return ParserSettings.this.on_url.cb(p, by, pos, len);
-        }
-        return 0;
-      }
-    };
-    this._on_fragment = new HTTPDataCallback() {
-      @Override
-      public int cb(HTTPParser p, byte[] by, int pos, int len) {
-        if (null != ParserSettings.this.on_fragment) {
-          return ParserSettings.this.on_fragment.cb(p, by, pos, len);
-        }
-        return 0;
-      }
-    };
-    this._on_error = new HTTPErrorCallback() {    
-      @Override
-      public void cb(HTTPParser parser, String error) {
-        if (null != ParserSettings.this.on_error) {
-          ParserSettings.this.on_error.cb(parser, error);
-        } else {
-          throw new HTTPException(error);
-        }
-        
-      }
-    };
-      
-      
-
-//    (on_header_field and on_header_value shortened to on_h_*)
-//    ------------------------ ------------ --------------------------------------------
-//   | State (prev. callback) | Callback   | Description/action                         |
-//    ------------------------ ------------ --------------------------------------------
-//   | nothing (first call)   | on_h_field | Allocate new buffer and copy callback data |
-//   |                        |            | into it                                    |
-//    ------------------------ ------------ --------------------------------------------
-//   | value                  | on_h_field | New header started.                        |
-//   |                        |            | Copy current name,value buffers to headers |
-//   |                        |            | list and allocate new buffer for new name  |
-//    ------------------------ ------------ --------------------------------------------
-//   | field                  | on_h_field | Previous name continues. Reallocate name   |
-//   |                        |            | buffer and append callback data to it      |
-//    ------------------------ ------------ --------------------------------------------
-//   | field                  | on_h_value | Value for current header started. Allocate |
-//   |                        |            | new buffer and copy callback data to it    |
-//    ------------------------ ------------ --------------------------------------------
-//   | value                  | on_h_value | Value continues. Reallocate value buffer   |
-//   |                        |            | and append callback data to it             |
-//    ------------------------ ------------ --------------------------------------------
-    this._on_header_field = new HTTPDataCallback() {
-      @Override
-      public int cb(HTTPParser p, byte[] by, int pos, int len) {
-        // previous value complete, call on_value with full value, reset value.
-        if (0 != ParserSettings.this.value.size()) {
-          // check we're even interested...
-          if (null != ParserSettings.this.on_header_value) {
-            byte [] valueArr = ParserSettings.this.value.toArray();
-            int ret = ParserSettings.this.on_header_value.cb(p, valueArr, 0, valueArr.length);
-            if (0 != ret) {
-              return ret;
-            }
-            ParserSettings.this.value.clear();
-          }
-        }
-        
-        if (null == ParserSettings.this.on_header_field) {
-          return 0;
-        }
-        
-        ParserSettings.this.field.addAll(by);
-        return 0;
-      }
-    };
-    this._on_header_value = new HTTPDataCallback() {    
-      @Override
-      public int cb(HTTPParser p, byte[] by, int pos, int len) {
-        
-        // previous field complete, call on_field with full field value, reset field.
-        if (0 != ParserSettings.this.field.size()) {
-          // check we're even interested...
-          if (null != ParserSettings.this.on_header_field) {
-            byte [] fieldArr = ParserSettings.this.field.toArray();
-            int ret = ParserSettings.this.on_header_field.cb(p, fieldArr, 0, fieldArr.length);
-            if (0 != ret) {
-              return ret;
-            }
-            ParserSettings.this.field.clear();
-          }
-        }
-        
-        if (null == ParserSettings.this.on_header_value) {
-          return 0;
-        }
-        ParserSettings.this.value.addAll(by);
-        return 0;
-      }
-    };
-    this._on_headers_complete = new HTTPCallback() {
-      @Override
-      public int cb(HTTPParser parser) {
-        // is there an uncompleted value ... ?
-        if (0 != ParserSettings.this.value.size()) {
-          // check we're even interested...
-          if (null != ParserSettings.this.on_header_value) {
-            byte [] valueArr = ParserSettings.this.value.toArray();
-            int ret = ParserSettings.this.on_header_value.cb(parser, valueArr, 0, valueArr.length);
-            if (0 != ret) {
-              return ret;
-            }
-            ParserSettings.this.value.clear();
-          }
-        }
-        if (null != ParserSettings.this.on_headers_complete) {
-          return ParserSettings.this.on_headers_complete.cb(parser);
-        }
-        return 0;
-      }
-      
-    };
-    this._on_body = new HTTPDataCallback() {    
-      @Override
-      public int cb(HTTPParser p, byte[] by, int pos, int len) {
-        if (null != ParserSettings.this.on_body) {
-          ParserSettings.this.body.addAll(by, pos, len);
-        }
-        return 0;
-      }
-    };
-    
-    this._on_message_complete = new HTTPCallback() {     
-      @Override
-      public int cb(HTTPParser parser) {
-        if (null != ParserSettings.this.on_body) {
-          byte [] body = ParserSettings.this.body.toArray();
-          int ret = ParserSettings.this.on_body.cb(parser, body, 0, body.length);
-          if (0!=ret) {
-            return ret;
-          }
-          ParserSettings.this.body.clear();
-        }
-        if (null != ParserSettings.this.on_message_complete) {
-          return ParserSettings.this.on_message_complete.cb(parser);
-        }
-        return 0;
-      }
-    };
-    
-  }
-
-  private void attachCallbacks() {
-    // these are certainly set, because we mirror them ...
-    this.settings.on_message_begin    = this._on_message_begin;
-    this.settings.on_path             = this._on_path;
-    this.settings.on_query_string     = this._on_query_string;
-    this.settings.on_url              = this._on_url;
-    this.settings.on_fragment         = this._on_fragment;
-    this.settings.on_header_field     = this._on_header_field;
-    this.settings.on_header_value     = this._on_header_value; 
-    this.settings.on_headers_complete = this._on_headers_complete;
-    this.settings.on_body             = this._on_body;
-    this.settings.on_message_complete = this._on_message_complete;
-    this.settings.on_error            = this._on_error;
-  }
-}
-//import http_parser.HTTPException;
-//public class ParserSettings extends http_parser.lolevel.ParserSettings{
-//	
-//  
-//  
-//  
-//  public HTTPCallback       on_message_begin;
-//  public HTTPDataCallback 	on_path;
-//  public HTTPDataCallback 	on_query_string;
-//  public HTTPDataCallback 	on_url;
-//  public HTTPDataCallback 	on_fragment;
-//  public HTTPDataCallback 	on_header_field;
-//  public HTTPDataCallback 	on_header_value;
-//  public HTTPCallback       on_headers_complete;
-//  public HTTPDataCallback 	on_body;
-//  public HTTPCallback       on_message_complete;
-//  public HTTPErrorCallback  on_error;
-//
-//	void call_on_message_begin (HTTPParser p) {
-//		call_on(on_message_begin, p);
-//	}
-//
-//	void call_on_message_complete (HTTPParser p) {
-//		call_on(on_message_complete, p);
-//	}
-//  
-//  // this one is a little bit different:
-//  // the current `position` of the buffer is the location of the
-//  // error, `ini_pos` indicates where the position of
-//  // the buffer when it was passed to the `execute` method of the parser, i.e.
-//  // using this information and `limit` we'll know all the valid data
-//  // in the buffer around the error we can use to print pretty error
-//  // messages.
-//  void call_on_error (HTTPParser p, String mes, ByteBuffer buf, int ini_pos) {
-//    if (null != on_error) {
-//      on_error.cb(p, mes, buf, ini_pos);
-//    }
-//    // if on_error gets called it MUST throw an exception, else the parser 
-//    // will attempt to continue parsing, which it can't because it's
-//    // in an invalid state.
-//    throw new HTTPException(mes);
-//	}
-//
-//	void call_on_header_field (HTTPParser p, ByteBuffer buf, int pos, int len) {
-//		call_on(on_header_field, p, buf, pos, len);
-//	}
-//	void call_on_query_string (HTTPParser p, ByteBuffer buf, int pos, int len) {
-//		call_on(on_query_string, p, buf, pos, len);
-//	}
-//	void call_on_fragment (HTTPParser p, ByteBuffer buf, int pos, int len) {
-//		call_on(on_fragment, p, buf, pos, len);
-//	}
-//	void call_on_path (HTTPParser p, ByteBuffer buf, int pos, int len) {
-//		call_on(on_path, p, buf, pos, len);
-//	}
-//	void call_on_header_value (HTTPParser p, ByteBuffer buf, int pos, int len) {
-//		call_on(on_header_value, p, buf, pos, len);
-//	}
-//	void call_on_url (HTTPParser p, ByteBuffer buf, int pos, int len) {
-//		call_on(on_url, p, buf, pos, len);
-//	}
-//	void call_on_body(HTTPParser p, ByteBuffer buf, int pos, int len) {
-//		call_on(on_body, p, buf, pos, len);
-//	}
-//	void call_on_headers_complete(HTTPParser p) {
-//		call_on(on_headers_complete, p);
-//	} 
-//	void call_on (HTTPCallback cb, HTTPParser p) {
-//		// cf. CALLBACK2 macro
-//		if (null != cb) {
-//			cb.cb(p);
-//		}
-//	}
-//	void call_on (HTTPDataCallback cb, HTTPParser p, ByteBuffer buf, int pos, int len) {
-//		if (null != cb && -1 != pos) {
-//			cb.cb(p,buf,pos,len);
-//		}
-//	}
-//}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserType.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserType.java
deleted file mode 100644
index a51f5b4..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserType.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package http_parser;
-
-public enum ParserType {
-HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH;
-
-	public static ParserType parse(String s) {
-		     if ("HTTP_REQUEST".equalsIgnoreCase(s))  { return HTTP_REQUEST; }
-		else if ("HTTP_RESPONSE".equalsIgnoreCase(s)) { return HTTP_RESPONSE; }
-		else if ("HTTP_BOTH".equalsIgnoreCase(s))     { return HTTP_BOTH; }
-		else                                          { return null; }
-	}
-}
-
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/Util.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/Util.java
deleted file mode 100644
index fdda2b6..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/Util.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package http_parser;
-
-import java.nio.ByteBuffer;
-
-public class Util {
-//  public static String toString(http_parser.lolevel.HTTPParser p) {
-//    StringBuilder builder = new StringBuilder();
-//    
-//    // the stuff up to the break is ephermeral and only meaningful
-//    // while the parser is parsing. In general, this method is 
-//    // probably only useful during debugging.
-//
-//    builder.append("state :"); builder.append(p.state); builder.append("\n");
-//    builder.append("header_state :"); builder.append(p.header_state); builder.append("\n");
-//    builder.append("strict :"); builder.append(p.strict); builder.append("\n");
-//    builder.append("index :"); builder.append(p.index); builder.append("\n");
-//    builder.append("flags :"); builder.append(p.flags); builder.append("\n");
-//    builder.append("nread :"); builder.append(p.nread); builder.append("\n");
-//    builder.append("content_length :"); builder.append(p.content_length); builder.append("\n");
-//
-//
-//    builder.append("type :"); builder.append(p.type); builder.append("\n");
-//    builder.append("http_major :"); builder.append(p.http_major); builder.append("\n");
-//    builder.append("http_minor :"); builder.append(p.http_minor); builder.append("\n");
-//    builder.append("status_code :"); builder.append(p.status_code); builder.append("\n");
-//    builder.append("method :"); builder.append(p.method); builder.append("\n");
-//    builder.append("upgrade :"); builder.append(p.upgrade); builder.append("\n");
-//
-//    return builder.toString();
-//
-//  }
-
-  public static String error (String mes, ByteBuffer b, int begining) {
-      // the error message should look like this:
-      //
-      // Bla expected something, but it's not there (mes)
-      // GEt / HTTP 1_1
-      // ............^.
-      //
-      // |----------------- 72 -------------------------|
-
-      // This is ridiculously complicated and probably riddled with
-      // off-by-one errors, should be moved into high level interface.
-      // TODO.
-      
-      // also: need to keep track of the initial buffer position in
-      // execute so that we don't screw up any `mark()` that may have
-      // been set outside of our control to be nice.
-
-      final int mes_width = 72;
-      int p   = b.position();      // error position
-      int end = b.limit();         // this is the end
-      int m   = end - begining;    // max mes length  
-      
-      StringBuilder builder = new StringBuilder();
-      int p_adj = p;
-
-      byte [] orig = new byte[0];
-      if (m <= mes_width) {
-        orig = new byte[m];
-        b.position(begining);
-        b.get(orig, 0, m);
-        p_adj = p-begining;
-        
-        
-      } else {
-        // we'll need to trim bit off the beginning and/or end
-        orig = new byte[mes_width];
-        // three possibilities:
-        // a.) plenty of stuff around p
-        // b.) plenty of stuff in front of p
-        // c.) plenty of stuff behind p
-        // CAN'T be not enough stuff aorund p in total, because 
-        // m>meswidth (see if to this else)
-
-        int before = p-begining;
-        int after  = end - p;
-        if ( (before > mes_width/2) && (after > mes_width/2)) {
-          // plenty of stuff in front of and behind error
-          p_adj = mes_width/2;
-          b.position(p - mes_width/2);
-          b.get(orig, 0, mes_width);
-        } else if  (before <= mes_width/2) {
-          // take all of the begining.
-          b.position(begining);
-          // and as much of the rest as possible
-          
-          b.get(orig, 0, mes_width);
-
-        } else {
-          // plenty of stuff before
-          before = end-mes_width;
-          b.position(before);
-          p_adj = p - before;
-          b.get(orig, 0, mes_width);
-        }
-      }
-
-      builder.append(new String(orig));
-      builder.append("\n");
-      for (int i = 0; i!= p_adj; ++i) {
-        builder.append(".");
-      }
-      builder.append("^");
-
-
-      b.position(p); // restore position
-      return builder.toString();
-
-  }
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPCallback.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPCallback.java
deleted file mode 100644
index 95c29b3..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPCallback.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package http_parser.lolevel;
-
-public interface HTTPCallback {
-	public int cb (HTTPParser parser);
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPDataCallback.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPDataCallback.java
deleted file mode 100644
index 6cad156..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPDataCallback.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package http_parser.lolevel;
-
-import java.nio.ByteBuffer;
-
-public interface HTTPDataCallback {
-	/*
-		very raw and extremly foolhardy! DANGER!
-		The whole Buffer concept is difficult enough to grasp as it is,
-		we pass in a buffer with an arbitrary position.
-
-		The interesting data is located at position pos and is len 
-		bytes long.
-		
-		The contract of this callback is that the buffer is
-		returned in the state that it was passed in, so implementing
-		this require good citizenship, you'll need to remember the current
-		position, change the position to get at the data you're interested 
-		in and then set the position back to how you found it...
-
-		//TODO: there should be an abstract implementation that implements
-		cb as described above, marks it final an provides a new callback
-		with signature cb(byte[], int, int)
-	*/
-	public int cb(HTTPParser p, ByteBuffer buf, int pos, int len);
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPErrorCallback.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPErrorCallback.java
deleted file mode 100644
index d38d9d4..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPErrorCallback.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package http_parser.lolevel;
-
-import java.nio.ByteBuffer;
-
-public interface HTTPErrorCallback {
-	public void cb (HTTPParser parser, String mes, ByteBuffer buf, int initial_position);
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java
deleted file mode 100644
index d9c666b..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java
+++ /dev/null
@@ -1,2068 +0,0 @@
-package http_parser.lolevel;
-
-import java.nio.ByteBuffer;
-import http_parser.HTTPException;
-import http_parser.HTTPMethod;
-import http_parser.ParserType;
-import static http_parser.lolevel.HTTPParser.C.*;
-import static http_parser.lolevel.HTTPParser.State.*;
-
-public class  HTTPParser {
-	/* lots of unsigned chars here, not sure what
-	   to about them, `bytes` in java suck...  */
-
-	ParserType type;
-	State state;
-	HState header_state;
-  boolean strict;
-
-	int index; 
-	int flags; // TODO
-
-	int nread;
-	int content_length;
-
-  int start_position;
-  ByteBuffer data;
-
-  /** READ-ONLY **/
-  public int http_major;
-  public int http_minor;
-  public int status_code;   /* responses only */
-  public HTTPMethod method; /* requests only */
-
-  /* true  = Upgrade header was present and the parser has exited because of that.
-   * false = No upgrade header present.
-   * Should be checked when http_parser_execute() returns in addition to
-   * error checking.
-   */
-  public boolean upgrade; 
-
-  /** PUBLIC **/
-	// TODO : this is used in c to maintain application state.
-	// is this even necessary? we have state in java ?
-	// consider 
-  // Object data; /* A pointer to get hook to the "connection" or "socket" object */
-			
-
-  /* 
-   * technically we could combine all of these (except for url_mark) into one
-   * variable, saving stack space, but it seems more clear to have them
-   * separated. 
-   */
-  int header_field_mark = -1;
-  int header_value_mark = -1;
-  int fragment_mark = -1;
-  int query_string_mark = -1;
-  int path_mark = -1;
-  int url_mark = -1;
-	
-  /**
-   * Construct a Parser for ParserType.HTTP_BOTH, meaning it
-   * determines whether it's parsing a request or a response.
-   */
-	public HTTPParser() {
-		this(ParserType.HTTP_BOTH);
-	}
-	
-  /**
-   * Construct a Parser and initialise it to parse either 
-   * requests or responses.
-   */
-	public HTTPParser(ParserType type) {
-		this.type  = type;
-		switch(type) {
-			case HTTP_REQUEST:
-				this.state = State.start_req;
-				break;
-			case HTTP_RESPONSE:
-				this.state = State.start_res;
-				break;
-			case HTTP_BOTH:
-				this.state = State.start_res_or_res;
-				break;
-			default:
-				throw new HTTPException("can't happen, invalid ParserType enum");
-		}
-	}
-	
-  /*
-   * Utility to facilitate System.out.println style debugging (the way god intended)
-   */
-	static void p(Object o) {System.out.println(o);}
-
-
-  /** Execute the parser with the currently available data contained in
-   * the buffer. The buffers position() and limit() need to be set
-   * correctly (obviously) and a will be updated approriately when the
-   * method returns to reflect the consumed data.
-   */
-  public int execute(ParserSettings settings, ByteBuffer data) {
-
-    int p     = data.position();
-    int p_err = p; // this is used for pretty printing errors.
-    
-    this.start_position = p;
-    this.data           = data;
-
-    // In case the headers don't provide information about the content
-    // length, `execute` needs to be called with an empty buffer to
-    // indicate that all the data has been send be the client/server,
-    // else there is no way of knowing the message is complete. 
-    int len = (data.limit() - data.position());
-    if (0 == len) {
-      //			if (State.body_identity_eof == state) {
-      //				settings.call_on_message_complete(this);
-      //			}
-      switch (state) {
-        case body_identity_eof:
-          settings.call_on_message_complete(this);
-          return data.position() - start_position;
-
-        case dead:
-        case start_res_or_res:
-        case start_res:
-        case start_req:
-          return data.position() - start_position;
-
-        default:
-          // should we really consider this an error!?
-          throw new HTTPException("empty bytes! "+state); // error
-      }
-    }
-
-		
-    // in case the _previous_ call to the parser only has data to get to
-    // the middle of certain fields, we need to update marks to point at
-    // the beginning of the current buffer.
-    switch (state) {
-      case header_field:
-        header_field_mark = p;
-        break;
-      case header_value:
-        header_value_mark = p;
-        break;
-      case req_fragment:
-        fragment_mark = p;
-        url_mark = p;
-        break;
-      case req_query_string:
-        query_string_mark = p;
-        url_mark = p;
-        break;
-      case req_path:
-        path_mark = p;
-
-      case req_host:
-      case req_schema:
-      case req_schema_slash:
-      case req_schema_slash_slash:
-      case req_port:
-      case req_query_string_start:
-      case req_fragment_start:
-        url_mark = p;
-        break;
-    }
-
-    // this is where the work gets done, traverse the available data...
-    while (data.position() != data.limit()) {
-
-            p = data.position();
-      int  pe = data.limit();
-
-      byte ch     = data.get();           // the current character to process.
-      int  chi    = ch & 0xff;            // utility, ch without signedness for table lookups.
-      byte c      = -1;                   // utility variably used for up- and downcasing etc.
-      int to_read =  0;                   // used to keep track of how much of body, etc. is left to read
-
-      if (parsing_header(state)) {
-        ++nread;
-        if (nread > HTTP_MAX_HEADER_SIZE) {
-          settings.call_on_error(this, "possible buffer overflow", data, p_err);
-          return error();
-        }
-      }
-//p(state + ":" + ch +":"+p);
-      switch (state) {
-         /*
-          * this state is used after a 'Connection: close' message
-          * the parser will error out if it reads another message
-          */
-        case dead:
-          settings.call_on_error(this, "Connection already closed", data, p_err);
-          return error();
-
-
-
-        case start_res_or_res:
-          if (CR == ch || LF == ch){
-            break;
-          }
-          flags = 0;
-          content_length = -1;
-
-          settings.call_on_message_begin(this);
-          
-          if (H == ch) { 
-            state = State.res_or_resp_H;
-          } else {
-            type   = ParserType.HTTP_REQUEST;  
-            method = start_req_method_assign(ch);     
-            if (null == method) {
-              settings.call_on_error(this, "invalid method", data, p_err);
-              return error();
-            }
-            index  = 1;
-            state  = State.req_method;
-          }
-          break;
-
-
-
-        case res_or_resp_H:
-          if (T == ch) {
-            type  = ParserType.HTTP_RESPONSE;
-            state = State.res_HT;
-          } else {
-            if (E != ch) {
-              settings.call_on_error(this, "not E", data, p_err);
-              return error();
-            }
-            type   = ParserType.HTTP_REQUEST;
-            method = HTTPMethod.HTTP_HEAD;
-            index  = 2;
-            state  = State.req_method;
-          }
-          break;
-
-
-
-        case start_res:
-          flags = 0;
-          content_length = -1;
-
-          settings.call_on_message_begin(this);
-          
-          switch(ch) {
-            case H:
-              state = State.res_H;
-              break;
-            case CR:
-            case LF:
-              break;
-            default:
-              settings.call_on_error(this, "Not H or CR/LF", data, p_err);
-              return error();
-          }
-          break;
-
-
-
-        case res_H:
-          if (strict && T != ch) {
-            settings.call_on_error(this, "Not T", data, p_err);
-            return error();
-          }
-          state = State.res_HT;
-          break;
-        case res_HT:
-          if (strict && T != ch) {
-            settings.call_on_error(this, "Not T2", data, p_err);
-            return error();
-          }
-          state = State.res_HTT;
-          break;
-        case res_HTT:
-          if (strict && P != ch) {
-            settings.call_on_error(this, "Not P", data, p_err);
-            return error();
-          }
-          state = State.res_HTTP;
-          break;
-        case res_HTTP:
-          if (strict && SLASH != ch) {
-            settings.call_on_error(this, "Not '/'", data, p_err);
-            return error();
-          }
-          state = State.res_first_http_major;
-          break;
-
-
-
-        case res_first_http_major:
-          if (!isDigit(ch)) {
-            settings.call_on_error(this, "Not a digit", data, p_err);
-            return error();
-          }
-          http_major = (int) ch - 0x30;
-          state = State.res_http_major;
-          break;
-
-        /* major HTTP version or dot */
-        case res_http_major:
-          if (DOT == ch) {
-            state = State.res_first_http_minor;
-            break;
-          }
-          if (!isDigit(ch)) {
-            settings.call_on_error(this, "Not a digit", data, p_err);
-            return error();
-          }
-          http_major *= 10;
-          http_major += (ch - 0x30);
-
-          if (http_major > 999) {
-            settings.call_on_error(this, "invalid http major version: "+http_major, data, p_err);
-            return error();
-          }
-          break;
-          
-        /* first digit of minor HTTP version */
-        case res_first_http_minor:
-          if (!isDigit(ch)) {
-            settings.call_on_error(this, "Not a digit", data, p_err);
-            return error();
-          }
-          http_minor = (int)ch - 0x30;
-          state = State.res_http_minor;
-          break;
-
-        /* minor HTTP version or end of request line */
-        case res_http_minor:
-          if (SPACE == ch) {
-            state = State.res_first_status_code;
-            break;
-          }
-          if (!isDigit(ch)) {
-            settings.call_on_error(this, "Not a digit", data, p_err);
-            return error();
-          }
-          http_minor *= 10;
-          http_minor += (ch - 0x30);
-          if (http_minor > 999) {
-            settings.call_on_error(this, "invalid http minor version: "+http_minor, data, p_err);
-            return error();
-          }
-          break;
-
-
-
-        case res_first_status_code:
-          if (!isDigit(ch)) {
-            if (SPACE == ch) {
-              break;
-            }
-            settings.call_on_error(this, "Not a digit (status code)", data, p_err);
-            return error();
-          }
-          status_code = (int)ch - 0x30;
-          state = State.res_status_code;
-          break;
-
-        case res_status_code:
-          if (!isDigit(ch)) {
-            switch(ch) {
-              case SPACE:
-                state = State.res_status;
-                break;
-              case CR:
-                state = State.res_line_almost_done;
-                break;
-              case LF:
-                state = State.header_field_start;
-                break;
-              default:
-                settings.call_on_error(this, "not a valid status code", data, p_err);
-                return error();
-            }
-            break;
-          }
-          status_code *= 10;
-          status_code += (int)ch - 0x30;
-          if (status_code > 999) {
-            settings.call_on_error(this, "ridiculous status code:"+status_code, data, p_err);
-            return error();
-          }
-          break;
-
-        case res_status:
-          /* the human readable status. e.g. "NOT FOUND"
-           * we are not humans so just ignore this 
-           * we are not men, we are devo. */
-
-           if (CR == ch) {
-            state = State.res_line_almost_done;
-            break;
-           }
-           if (LF == ch) { 
-            state = State.header_field_start;
-            break;
-           }
-           break;
-
-        case res_line_almost_done:
-          if (strict && LF != ch) {
-            settings.call_on_error(this, "not LF", data, p_err);
-            return error();
-          }
-          state = State.header_field_start;
-          break;
-
-
-
-        case start_req:
-          if (CR==ch || LF == ch) {
-            break;
-          }
-          flags = 0;
-          content_length = -1;
-          settings.call_on_message_begin(this);
-          method = start_req_method_assign(ch);
-          if (null == method) {
-            settings.call_on_error(this, "invalid method", data, p_err);
-            return error();
-          }
-          index  = 1;
-          state  = State.req_method;
-          break;
-        
-
-
-        case req_method:
-          if (0 == ch) {
-            settings.call_on_error(this, "NULL in method", data, p_err);
-            return error();
-          }
-          
-          byte [] arr = method.bytes;
-
-          if (SPACE == ch && index == arr.length) {
-            state = State.req_spaces_before_url;
-          } else if (arr[index] == ch) {
-            // wuhu!
-          } else if (HTTPMethod.HTTP_CONNECT == method) {
-              if (1 == index && H == ch) {
-                method = HTTPMethod.HTTP_CHECKOUT;
-              } else if (2 == index && P == ch) {
-                method = HTTPMethod.HTTP_COPY;
-              }
-          } else if (HTTPMethod.HTTP_MKCOL == method) {
-              if        (1 == index && O == ch) {
-                method = HTTPMethod.HTTP_MOVE;
-              } else if (1 == index && E == ch) {
-                method = HTTPMethod.HTTP_MERGE;
-              } else if (1 == index && DASH == ch) { /* M-SEARCH */
-                method = HTTPMethod.HTTP_MSEARCH;
-              } else if (2 == index && A == ch) {
-                method = HTTPMethod.HTTP_MKACTIVITY;
-              }
-          } else if (1 == index && HTTPMethod.HTTP_POST     == method && R == ch) {
-            method = HTTPMethod.HTTP_PROPFIND;
-          } else if (1 == index && HTTPMethod.HTTP_POST     == method && U == ch) {
-            method = HTTPMethod.HTTP_PUT;
-          } else if (2 == index && HTTPMethod.HTTP_UNLOCK   == method && S == ch) {
-            method = HTTPMethod.HTTP_UNSUBSCRIBE;
-          } else if (4 == index && HTTPMethod.HTTP_PROPFIND == method && P == ch) {
-            method = HTTPMethod.HTTP_PROPPATCH;
-          } else {
-            settings.call_on_error(this, "Invalid HTTP method", data, p_err);
-            return error();
-          }
-
-          ++index;
-          break;
-      
-
-
-        /******************* URL *******************/
-        case req_spaces_before_url:
-          if (SPACE == ch) {
-            break;
-          }
-          if (SLASH == ch || STAR == ch) {
-            url_mark  = p;
-            path_mark = p;
-            state = State.req_path;
-            break;
-          }
-          if (isAtoZ(ch)) {
-            url_mark = p;
-            state = State.req_schema;
-            break;
-          }
-          settings.call_on_error(this, "Invalid something", data, p_err);
-          return error();
-
-        case req_schema:
-          if (isAtoZ(ch)){
-            break;
-          }
-          if (COLON == ch) {
-            state = State.req_schema_slash;
-            break;
-          } else if (DOT == ch || isDigit(ch)) {
-            state = State.req_host;
-            break;
-          }
-          settings.call_on_error(this, "invalid char in schema: "+ch, data, p_err);
-          return error();
-
-        case req_schema_slash:
-          if (strict && SLASH != ch) {
-            settings.call_on_error(this, "invalid char in schema, not /", data, p_err);
-            return error();
-          }
-          state = State.req_schema_slash_slash;
-          break;
-
-        case req_schema_slash_slash:
-          if (strict && SLASH != ch) {
-            settings.call_on_error(this, "invalid char in schema, not /", data, p_err);
-            return error();
-          }
-          state = State.req_host;
-          break;
-        
-        case req_host:
-          if (isAtoZ(ch)) {
-            break;
-          }	
-          if (isDigit(ch) || DOT == ch || DASH == ch) break;
-          switch (ch) {
-            case COLON:
-              state = State.req_port;
-              break;
-            case SLASH:
-              path_mark = p;
-              break;
-            case SPACE:
-              /* The request line looks like:
-               *   "GET http://foo.bar.com HTTP/1.1"
-               * That is, there is no path.
-               */
-              settings.call_on_url(this, data, url_mark, p-url_mark);
-              url_mark = -1;
-              state = State.req_http_start;
-              break;
-            case QMARK:
-              state = State.req_query_string_start;
-              break;
-            default:
-              settings.call_on_error(this, "host error in method line", data, p_err);
-              return error();
-          }
-          break;
-
-        case req_port:
-          if (isDigit(ch)) break;
-          switch (ch) {
-            case SLASH:
-              path_mark = p; 
-              state = State.req_path;
-              break;
-            case SPACE:
-              /* The request line looks like:
-               *   "GET http://foo.bar.com:1234 HTTP/1.1"
-               * That is, there is no path.
-               */
-              settings.call_on_url(this,data,url_mark,p-url_mark);
-              url_mark = -1;
-              state = State.req_http_start;
-              break;
-            case QMARK:
-              state = State.req_query_string_start;
-              break;
-            default:
-              settings.call_on_error(this, "invalid port", data, p_err);
-              return error();
-          }
-          break;
-      
-        case req_path:
-          if (normal_url_char[chi]) break;
-          switch (ch) {
-            case SPACE:
-              settings.call_on_url(this,data,url_mark, p-url_mark);
-              url_mark = -1;
-
-              settings.call_on_path(this,data,path_mark, p-path_mark);
-              path_mark = -1;
-              
-              state = State.req_http_start;
-              break;
-
-            case CR:
-              settings.call_on_url(this,data,url_mark, p-url_mark);
-              url_mark = -1;
-              
-              settings.call_on_path(this,data,path_mark, p-path_mark);
-              path_mark = -1;
-              
-              http_minor = 9;
-              state = State.res_line_almost_done;
-              break;
-
-            case LF:
-              settings.call_on_url(this,data,url_mark, p-url_mark);
-              url_mark = -1;
-              
-              settings.call_on_path(this,data,path_mark, p-path_mark);
-              path_mark = -1;
-              
-              http_minor = 9;
-              state = State.header_field_start;
-              break;
-
-            case QMARK:
-              settings.call_on_path(this,data,path_mark, p-path_mark);
-              path_mark = -1;
-              
-              state = State.req_query_string_start;
-              break;
-            
-            case HASH:
-              settings.call_on_path(this,data,path_mark, p-path_mark);
-              path_mark = -1;
-              
-              state = State.req_fragment_start;
-              break;
-            
-            default:
-              settings.call_on_error(this, "unexpected char in path", data, p_err);
-              return error();
-          }
-          break;
-      
-        case req_query_string_start:
-          if (normal_url_char[chi]) {
-            query_string_mark = p;
-            state = State.req_query_string;
-            break;
-          }
-
-          switch (ch) {
-            case QMARK: break;
-            case SPACE: 
-              settings.call_on_url(this, data, url_mark, p-url_mark);
-              url_mark = -1;
-              state = State.req_http_start;
-              break;
-            case CR:
-              settings.call_on_url(this,data,url_mark, p-url_mark);
-              url_mark = -1; 
-              http_minor = 9;
-              state = State.res_line_almost_done;
-              break;
-            case LF:
-              settings.call_on_url(this,data,url_mark, p-url_mark);
-              url_mark = -1;
-              http_minor = 9;
-              state = State.header_field_start;
-              break;
-            case HASH:
-              state = State.req_fragment_start;
-              break;
-            default:
-              settings.call_on_error(this, "unexpected char in path", data, p_err);
-              return error();
-          }
-          break;
-        
-        case req_query_string:
-          if (normal_url_char[chi]) {
-            break;
-          }
-
-          switch (ch) {
-            case QMARK: break; // allow extra '?' in query string
-            case SPACE: 
-              settings.call_on_url(this, data, url_mark, p-url_mark);
-              url_mark = -1;
-
-              settings.call_on_query_string(this, data, query_string_mark, p-query_string_mark);
-              query_string_mark = -1;
-
-              state = State.req_http_start;
-              break;
-            case CR:
-              settings.call_on_url(this,data,url_mark, p-url_mark);
-              url_mark = -1; 
-
-              settings.call_on_query_string(this, data, query_string_mark, p-query_string_mark);
-              query_string_mark = -1;
-              
-              http_minor = 9;
-              state = State.res_line_almost_done;
-              break;
-            case LF:
-              settings.call_on_url(this,data,url_mark, p-url_mark);
-              url_mark = -1;
-
-              settings.call_on_query_string(this, data, query_string_mark, p-query_string_mark);
-              query_string_mark = -1;
-              http_minor = 9;
-
-              state = State.header_field_start;
-              break;
-            case HASH:
-              settings.call_on_query_string(this, data, query_string_mark, p-query_string_mark);
-              query_string_mark = -1;
-              
-              state = State.req_fragment_start;
-              break;
-            default:
-              settings.call_on_error(this, "unexpected char in path", data, p_err);
-              return error();
-          }
-          break;
-
-        case req_fragment_start:
-          if (normal_url_char[chi]) {
-            fragment_mark = p;
-            state = State.req_fragment;
-            break;
-          }
-
-          switch (ch) {
-            case SPACE: 
-              settings.call_on_url(this, data, url_mark, p-url_mark);
-              url_mark = -1;
-     
-              state = State.req_http_start;
-              break;
-            case CR:
-              settings.call_on_url(this,data,url_mark, p-url_mark);
-              url_mark = -1; 
-
-              http_minor = 9;
-              state = State.res_line_almost_done;
-              break;
-            case LF:
-              settings.call_on_url(this,data,url_mark, p-url_mark);
-              url_mark = -1;
-              
-              http_minor = 9;
-              state = State.header_field_start;
-              break;
-            case QMARK:
-              fragment_mark = p;
-              state = State.req_fragment;
-              break;
-            case HASH:
-              break;
-            default:
-              settings.call_on_error(this, "unexpected char in path", data, p_err);
-              return error();
-          }
-          break;
-
-        case req_fragment:
-          if (normal_url_char[chi]) {
-            break;
-          }
-
-          switch (ch) {
-            case SPACE: 
-              settings.call_on_url(this, data, url_mark, p-url_mark);
-              url_mark = -1;
-          
-              settings.call_on_fragment(this, data, fragment_mark, p-fragment_mark);
-              fragment_mark = -1;
-              
-              state = State.req_http_start;
-              break;
-            case CR:
-              settings.call_on_url(this,data,url_mark, p-url_mark);
-              url_mark = -1; 
-              
-              settings.call_on_fragment(this, data, query_string_mark, p-query_string_mark);
-              fragment_mark = -1;
-              
-              http_minor = 9;
-              state = State.res_line_almost_done;
-              break;
-            case LF:
-              settings.call_on_url(this,data,url_mark, p-url_mark);
-              url_mark = -1;
-              
-              settings.call_on_fragment(this, data, query_string_mark, p-query_string_mark);
-              fragment_mark = -1;
-              
-              http_minor = 9;
-              state = State.header_field_start;
-              break;
-            case QMARK:
-            case HASH:
-              break;
-            default:
-              settings.call_on_error(this, "unexpected char in path", data, p_err);
-              return error();
-          }
-          break;
-        /******************* URL *******************/
-
-
-
-        /******************* HTTP 1.1 *******************/
-        case req_http_start:
-          switch (ch) {
-            case H:
-              state = State.req_http_H;
-              break;
-            case SPACE:
-              break;
-            default:
-              settings.call_on_error(this, "error in req_http_H", data, p_err);
-              return error();
-          }
-          break;
-
-        case req_http_H:
-          if (strict && T != ch) {
-            settings.call_on_error(this, "unexpected char", data, p_err);
-            return error();
-          }
-          state = State.req_http_HT;
-          break;
-
-        case req_http_HT:
-          if (strict && T != ch) {
-            settings.call_on_error(this, "unexpected char", data, p_err);
-            return error();
-          }
-          state = State.req_http_HTT;
-          break;
-
-        case req_http_HTT:
-          if (strict && P != ch) {
-            settings.call_on_error(this, "unexpected char", data, p_err);
-            return error();
-          }
-          state = State.req_http_HTTP;
-          break;
-
-        case req_http_HTTP:
-          if (strict && SLASH != ch) {
-            settings.call_on_error(this, "unexpected char", data, p_err);
-            return error();
-          }
-          state = req_first_http_major;
-          break;
-
-        /* first digit of major HTTP version */
-        case req_first_http_major:
-          if (!isDigit(ch)) {
-            settings.call_on_error(this, "non digit in http major", data, p_err);
-            return error();
-          }
-          http_major = (int)ch - 0x30;
-          state = State.req_http_major;
-          break;
-
-        /* major HTTP version or dot */
-        case req_http_major:
-          if (DOT == ch) {
-            state = State.req_first_http_minor;
-            break;
-          }
-
-          if (!isDigit(ch)) {
-            settings.call_on_error(this, "non digit in http major", data, p_err);
-            return error();
-          }
-
-          http_major *= 10;
-          http_major += (int)ch - 0x30;
-
-          if (http_major > 999) {
-            settings.call_on_error(this, "ridiculous http major", data, p_err);
-            return error();
-          };
-          break;
-        
-        /* first digit of minor HTTP version */
-        case req_first_http_minor:
-          if (!isDigit(ch)) {
-            settings.call_on_error(this, "non digit in http minor", data, p_err);
-            return error();
-          }
-          http_minor = (int)ch - 0x30;
-          state = State.req_http_minor;
-          break;
-
-        case req_http_minor:
-          if (ch == CR) {
-            state = State.req_line_almost_done;
-            break;
-          }
-
-          if (ch == LF) {
-            state = State.header_field_start;
-            break;
-          }
-
-          /* XXX allow spaces after digit? */
-
-          if (!isDigit(ch)) {
-            settings.call_on_error(this, "non digit in http minor", data, p_err);
-            return error();
-          }
-
-          http_minor *= 10;
-          http_minor += (int)ch - 0x30;
-
-         
-          if (http_minor > 999) {
-            settings.call_on_error(this, "ridiculous http minor", data, p_err);
-            return error();
-          };
-   
-          break;
-
-        /* end of request line */
-        case req_line_almost_done:
-        {
-          if (ch != LF) {
-            settings.call_on_error(this, "missing LF after request line", data, p_err);
-            return error();
-          }
-          state = State.header_field_start;
-          break;
-        }
-
-        /******************* HTTP 1.1 *******************/
-
-
-
-        /******************* Header *******************/
-        case header_field_start:
-        {
-          if (ch == CR) {
-            state = State.headers_almost_done;
-            break;
-          }
-
-          if (ch == LF) {
-            /* they might be just sending \n instead of \r\n so this would be
-             * the second \n to denote the end of headers*/
-            state = State.headers_almost_done;
-            if (!headers_almost_done(ch, settings)) {
-              settings.call_on_error(this, "header not properly completed", data, p_err);
-              return error();
-            }
-            if (upgrade) {
-              return data.position() - start_position;
-            }
-            break;
-          }
-
-          c = token(ch);
-
-          if (0 == c) {
-            settings.call_on_error(this, "invalid char in header:"+c, data, p_err);
-            return error();
-          };
-
-          header_field_mark = p;
-
-          index = 0;
-          state = State.header_field;
-
-          switch (c) {
-            case C: 
-              header_state = HState.C;
-              break;
-
-            case P:
-              header_state = HState.matching_proxy_connection;
-              break;
-
-            case T:
-              header_state = HState.matching_transfer_encoding;
-              break;
-
-            case U:
-              header_state = HState.matching_upgrade;
-              break;
-
-            default:
-              header_state = HState.general;
-              break;
-          }
-          break;
-        }
-
-
-
-        case header_field:
-        {
-          c = token(ch);
-          if (0 != c) {  
-            switch (header_state) {
-              case general:
-                break;
-
-              case C:
-                index++;
-                header_state = (O == c ? HState.CO : HState.general);
-                break;
-
-              case CO:
-                index++;
-                header_state = (N == c ? HState.CON : HState.general);
-                break;
-
-              case CON:
-                index++;
-                switch (c) {
-                  case N:
-                    header_state = HState.matching_connection;
-                    break;
-                  case T:
-                    header_state = HState.matching_content_length;
-                    break;
-                  default:
-                    header_state = HState.general;
-                    break;
-                }
-                break;
-
-              /* connection */
-
-              case matching_connection:
-                index++;
-                if (index > CONNECTION.length || c != CONNECTION[index]) {
-                  header_state = HState.general;
-                } else if (index == CONNECTION.length-1) {
-                  header_state = HState.connection;
-                }
-                break;
-
-              /* proxy-connection */
-
-              case matching_proxy_connection:
-                index++;
-                if (index > PROXY_CONNECTION.length || c != PROXY_CONNECTION[index]) {
-                  header_state = HState.general;
-                } else if (index == PROXY_CONNECTION.length-1) {
-                  header_state = HState.connection;
-                }
-                break;
-
-              /* content-length */
-
-              case matching_content_length:
-                index++;
-                if (index > CONTENT_LENGTH.length || c != CONTENT_LENGTH[index]) {
-                  header_state = HState.general;
-                } else if (index == CONTENT_LENGTH.length-1) {
-                  header_state = HState.content_length;
-                }
-                break;
-
-              /* transfer-encoding */
-
-              case matching_transfer_encoding:
-                index++;
-                if (index > TRANSFER_ENCODING.length || c != TRANSFER_ENCODING[index]) {
-                  header_state = HState.general;
-                } else if (index == TRANSFER_ENCODING.length-1) {
-                  header_state = HState.transfer_encoding;
-                }
-                break;
-
-              /* upgrade */
-
-              case matching_upgrade:
-                index++;
-                if (index > UPGRADE.length || c != UPGRADE[index]) {
-                  header_state = HState.general;
-                } else if (index == UPGRADE.length-1) {
-                  header_state = HState.upgrade;
-                }
-                break;
-
-              case connection:
-              case content_length:
-              case transfer_encoding:
-              case upgrade:
-                if (SPACE != ch) header_state = HState.general;
-                break;
-
-              default:
-                settings.call_on_error(this, "Unknown Header State", data, p_err);
-                return error();
-            } // switch: header_state
-            break;
-          } // 0 != c
-
-          if (COLON == ch)  {
-            settings.call_on_header_field(this, data, header_field_mark, p-header_field_mark);
-            header_field_mark = -1;
-
-            state = State.header_value_start;
-            break;
-          }
-
-          if (CR == ch) {
-            state = State.header_almost_done;
-            settings.call_on_header_field(this, data, header_field_mark, p-header_field_mark);
-            
-            header_field_mark = -1;
-            break;
-          }
-
-          if (ch == LF) {
-            settings.call_on_header_field(this, data, header_field_mark, p-header_field_mark);
-            header_field_mark = -1;
-            
-            state = State.header_field_start;
-            break;
-          }
-
-          settings.call_on_error(this, "invalid header field", data, p_err);
-          return error();
-        }
-
-
-
-        case header_value_start:
-        {
-          if (SPACE == ch) break;
-
-          header_value_mark = p;
-
-          state = State.header_value;
-          index = 0;
-
-
-          if (CR == ch) {
-            settings.call_on_header_value(this, data, header_value_mark, p-header_value_mark);
-            header_value_mark = -1;
-
-            header_state = HState.general;
-            state = State.header_almost_done;
-            break;
-          }
-
-          if (LF == ch) {
-            settings.call_on_header_value(this, data, header_value_mark, p-header_value_mark);
-            header_value_mark = -1;
-            
-            state = State.header_field_start;
-            break;
-          }
-
-
-          c = upper(ch);
-
-          switch (header_state) {
-            case upgrade:
-              flags |= F_UPGRADE;
-              header_state = HState.general;
-              break;
-
-            case transfer_encoding:
-              /* looking for 'Transfer-Encoding: chunked' */
-              if (C == c) {
-                header_state = HState.matching_transfer_encoding_chunked;
-              } else {
-                header_state = HState.general;
-              }
-              break;
-
-            case content_length:
-              if (!isDigit(ch)) {
-                settings.call_on_error(this, "Content-Length not numeric", data, p_err);
-                return error();
-              } 
-              content_length = (int)ch - 0x30;
-              break;
-
-            case connection:
-              /* looking for 'Connection: keep-alive' */
-              if (K == c) {
-                header_state = HState.matching_connection_keep_alive;
-              /* looking for 'Connection: close' */
-              } else if (C == c) {
-                header_state = HState.matching_connection_close;
-              } else {
-                header_state = HState.general;
-              }
-              break;
-
-            default:
-              header_state = HState.general;
-              break;
-          }
-          break;
-        } // header value start
-
-
-
-        case header_value:
-        {
-
-          if (CR == ch) {
-            settings.call_on_header_value(this, data, header_value_mark, p-header_value_mark);
-            header_value_mark = -1;
-
-            state = State.header_almost_done;
-            break;
-          }
-
-          if (LF == ch) {
-            settings.call_on_header_value(this, data, header_value_mark, p-header_value_mark);
-            header_value_mark = -1;
-            
-            if (!header_almost_done(ch)) {
-              settings.call_on_error(this,"incorrect header ending, expection LF", data, p_err);
-              return error();
-            }
-            break;
-          }
-
-          c = upper(ch);
-          switch (header_state) {
-            case general:
-              break;
-
-            case connection:
-            case transfer_encoding:
-              settings.call_on_error(this, "Shouldn't be here", data, p_err);
-              return error();
-
-            case content_length:
-              if (SPACE == ch) {
-                break;
-              }
-              if (!isDigit(ch)) {
-                settings.call_on_error(this, "Content-Length not numeric", data, p_err);
-                return error();
-              } 
-
-              content_length *= 10;
-              content_length += (int)ch - 0x30;
-              break;
-
-            /* Transfer-Encoding: chunked */
-            case matching_transfer_encoding_chunked:
-              index++;
-              if (index > CHUNKED.length || c != CHUNKED[index]) {
-                header_state = HState.general;
-              } else if (index == CHUNKED.length-1) {
-                header_state = HState.transfer_encoding_chunked;
-              }
-              break;
-
-            /* looking for 'Connection: keep-alive' */
-            case matching_connection_keep_alive:
-              index++;
-              if (index > KEEP_ALIVE.length || c != KEEP_ALIVE[index]) {
-                header_state = HState.general;
-              } else if (index == KEEP_ALIVE.length-1) {
-                header_state = HState.connection_keep_alive;
-              }
-              break;
-
-            /* looking for 'Connection: close' */
-            case matching_connection_close:
-              index++;
-              if (index > CLOSE.length || c != CLOSE[index]) {
-                header_state = HState.general;
-              } else if (index == CLOSE.length-1) {
-                header_state = HState.connection_close;
-              }
-              break;
-
-            case transfer_encoding_chunked:
-            case connection_keep_alive:
-            case connection_close:
-              if (SPACE != ch) header_state = HState.general;
-              break;
-
-            default:
-              state = State.header_value;
-              header_state = HState.general;
-              break;
-          }
-          break;
-        } // header_value
-
-
-
-        case header_almost_done:
-          if (!header_almost_done(ch)) {
-            settings.call_on_error(this,"incorrect header ending, expection LF", data, p_err);
-            return error();
-          }
-          break;
-
-        case headers_almost_done:
-          if (!headers_almost_done(ch, settings)) {
-            settings.call_on_error(this, "header not properly completed", data, p_err);
-            return error();
-          }
-          if (upgrade) {
-            return data.position()-start_position ;
-          }
-          break;
-
-        /******************* Header *******************/
-
-
-
-
-        /******************* Body *******************/
-        case body_identity:
-          to_read = min(pe - p, content_length); //TODO change to use buffer? 
-
-          if (to_read > 0) {
-            settings.call_on_body(this, data, p, to_read); 
-            data.position(p+to_read);
-            content_length -= to_read;
-            if (content_length == 0) {
-              settings.call_on_message_complete(this);
-              state = new_message(); 
-            }
-          }
-          break;
-
-
-
-        case body_identity_eof:
-          to_read = pe - p;  // TODO change to use buffer ?
-          if (to_read > 0) {
-            settings.call_on_body(this, data, p, to_read); 
-            data.position(p+to_read);
-          }
-          break;
-        /******************* Body *******************/
-
-
-
-        /******************* Chunk *******************/
-        case chunk_size_start:
-          if (1 != this.nread) {
-            settings.call_on_error(this, "nread != 1 (chunking)", data, p_err);
-            return error();
-          
-          }
-          if (0 == (flags & F_CHUNKED)) {
-            settings.call_on_error(this, "not chunked", data, p_err);
-            return error();
-          }
-
-          c = UNHEX[chi];
-          if (c == -1) {
-            settings.call_on_error(this, "invalid hex char in chunk content length", data, p_err);
-            return error();
-          }
-          content_length = c;
-          state = State.chunk_size;
-          break;
-
-
-
-        case chunk_size:
-          if (0 == (flags & F_CHUNKED)) {
-            settings.call_on_error(this, "not chunked", data, p_err);
-            return error();
-          }
-
-          if (CR == ch) {
-            state = State.chunk_size_almost_done;
-            break;
-          }
-
-          c = UNHEX[chi];
-
-          if (c == -1) {
-            if (SEMI == ch || SPACE == ch) {
-              state = State.chunk_parameters;
-              break;
-            }
-            settings.call_on_error(this, "invalid hex char in chunk content length", data, p_err);
-            return error();
-          }
-
-          content_length *= 16;
-          content_length += c;
-          break;
-
-
-
-        case chunk_parameters:
-          if (0 == (flags & F_CHUNKED)) {
-            settings.call_on_error(this, "not chunked", data, p_err);
-            return error();
-          }
-          /* just ignore this shit. TODO check for overflow */
-          if (CR == ch) {
-            state = State.chunk_size_almost_done;
-            break;
-          }
-          break;
-          
-
-
-        case chunk_size_almost_done:
-          if (0 == (flags & F_CHUNKED)) {
-            settings.call_on_error(this, "not chunked", data, p_err);
-            return error();
-          }
-          if (strict && LF != ch) {
-            settings.call_on_error(this, "expected LF at end of chunk size", data, p_err);
-            return error();
-          }
-
-          this.nread = 0;
-
-          if (0 == content_length) {
-            flags |= F_TRAILING;
-            state = State.header_field_start;
-          } else {
-            state = State.chunk_data;
-          }
-          break;
-
-
-
-        case chunk_data:
-        {
-          if (0 == (flags & F_CHUNKED)) {
-            settings.call_on_error(this, "not chunked", data, p_err);
-            return error();
-          }
-
-          to_read = min(pe-p, content_length);
-          if (to_read > 0) {
-            settings.call_on_body(this, data, p, to_read);
-            data.position(p+to_read);
-          }
-
-          if (to_read == content_length) {
-            state = State.chunk_data_almost_done;
-          }
-
-          content_length -= to_read;
-          break;
-        }
-
-
-
-        case chunk_data_almost_done:
-          if (0 == (flags & F_CHUNKED)) {
-            settings.call_on_error(this, "not chunked", data, p_err);
-            return error();
-          }
-          if (strict && CR != ch) {
-            settings.call_on_error(this, "chunk data terminated incorrectly, expected CR", data, p_err);
-            return error();
-          }
-          state = State.chunk_data_done;
-          break;
-
-
-
-        case chunk_data_done:
-          if (0 == (flags & F_CHUNKED)) {
-            settings.call_on_error(this, "not chunked", data, p_err);
-            return error();
-          }
-          if (strict && LF != ch) {
-            settings.call_on_error(this, "chunk data terminated incorrectly, expected LF", data, p_err);
-            return error();
-          }
-          state = State.chunk_size_start;
-          break;
-        /******************* Chunk *******************/
-    
-        
-        
-        default:
-          settings.call_on_error(this, "unhandled state", data, p_err);
-          return error();
-          
-      } // switch
-    } // while
-
-    p = data.position();
-
-
-    /* Reaching this point assumes that we only received part of a
-     * message, inform the callbacks about the progress made so far*/
-    
-	  settings.call_on_header_field(this, data, header_field_mark, p-header_field_mark);
-    settings.call_on_header_value(this, data, header_value_mark, p-header_value_mark);
-    settings.call_on_fragment    (this, data, fragment_mark,     p-fragment_mark);
-    settings.call_on_query_string(this, data, query_string_mark, p-query_string_mark);
-    settings.call_on_path        (this, data, path_mark,         p-path_mark);
-    settings.call_on_url         (this, data, url_mark,          p-url_mark);
-    
-    return data.position()-start_position;	
-  } // execute
-
-  int error () {
-    this.state = State.dead;
-    return this.data.position()-start_position;
-  }
-
-  /* If http_should_keep_alive() in the on_headers_complete or
-   * on_message_complete callback returns true, then this will be should be
-   * the last message on the connection.
-   * If you are the server, respond with the "Connection: close" header.
-   * If you are the client, close the connection.
-   */
-  public boolean http_should_keep_alive() {
-    if (http_major > 0 && http_minor > 0) {
-      /* HTTP/1.1 */
-      if ( 0 != (flags & F_CONNECTION_CLOSE) ) {
-        return false;
-      } else {
-        return true;
-      }
-    } else {
-      /* HTTP/1.0 or earlier */
-      if ( 0 != (flags & F_CONNECTION_KEEP_ALIVE) ) {
-        return true;
-      } else {
-        return false;
-      }
-    }
-  }
-
-  boolean isDigit(byte b) {
-    if (b >= 0x30 && b <=0x39) {
-      return true;
-    }
-    return false;
-  }
-
-  boolean isAtoZ(byte b) {
-    byte c = lower(b);
-    return (c>= 0x61 /*a*/ && c <=  0x7a /*z*/);
-  }
-
-
-  byte lower (byte b) {
-    return (byte)(b|0x20);
-  }
-
-  byte upper(byte b) {
-    char c = (char)(b);
-    return (byte)Character.toUpperCase(c);
-  }
-
-  byte token(byte b) {
-    return (byte)tokens[b];
-  }
-	
-
-  HTTPMethod start_req_method_assign(byte c){
-    switch (c) {
-      case C: return HTTPMethod.HTTP_CONNECT;  /* or COPY, CHECKOUT */
-      case D: return HTTPMethod.HTTP_DELETE;  
-      case G: return HTTPMethod.HTTP_GET;     
-      case H: return HTTPMethod.HTTP_HEAD;    
-      case L: return HTTPMethod.HTTP_LOCK;    
-      case M: return HTTPMethod.HTTP_MKCOL;    /* or MOVE, MKACTIVITY, MERGE, M-SEARCH */
-      case N: return HTTPMethod.HTTP_NOTIFY; 
-      case O: return HTTPMethod.HTTP_OPTIONS; 
-      case P: return HTTPMethod.HTTP_POST;     /* or PROPFIND, PROPPATH, PUT */
-      case R: return HTTPMethod.HTTP_REPORT;
-      case S: return HTTPMethod.HTTP_SUBSCRIBE;
-      case T: return HTTPMethod.HTTP_TRACE;   
-      case U: return HTTPMethod.HTTP_UNLOCK; /* or UNSUBSCRIBE */ 
-    }
-    return null; // ugh.
-  }
-
-  boolean header_almost_done(byte ch) {
-    if (strict && LF != ch) {
-      return false;
-    }
-
-    state = State.header_field_start;
-    // TODO java enums support some sort of bitflag mechanism !?
-    switch (header_state) {
-      case connection_keep_alive:
-        flags |= F_CONNECTION_KEEP_ALIVE;
-        break;
-      case connection_close:
-        flags |= F_CONNECTION_CLOSE;
-        break;
-      case transfer_encoding_chunked:
-        flags |= F_CHUNKED;
-        break;
-      default:
-        break;
-    }
-    return true;
-  }
-
-  boolean headers_almost_done (byte ch, ParserSettings settings) {
-
-    if (LF != ch) {
-      return false;
-    }
-    if (0 != (flags & F_TRAILING)) {
-      /* End of a chunked request */
-
-      settings.call_on_headers_complete(this);
-      settings.call_on_message_complete(this);
-
-      state = new_message(); 
-
-      return true;
-    }
-
-    nread = 0;
-
-    if (0 != (flags & F_UPGRADE) || HTTPMethod.HTTP_CONNECT == method) {
-      upgrade = true;
-    }
-    
-
-    /* Here we call the headers_complete callback. This is somewhat
-     * different than other callbacks because if the user returns 1, we
-     * will interpret that as saying that this message has no body. This
-     * is needed for the annoying case of recieving a response to a HEAD
-     * request.
-     */
-
-    /* (responses to HEAD request contain a CONTENT-LENGTH header
-     * but no content)
-     *
-     * Consider what to do here: I don't like the idea of the callback
-     * interface having a different contract in the case of HEAD
-     * responses. The alternatives would be either to:
-     *
-     * a.) require the header_complete callback to implement a different
-     * interface or
-     *
-     * b.) provide an overridden execute(bla, bla, boolean
-     * parsingHeader) implementation ...
-     */
-
-    /*TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO */ 
-    if (null != settings.on_headers_complete) {
-      settings.call_on_headers_complete(this);
-      //return;
-    }
-    
-    //        if (null != settings.on_headers_complete) {
-    //          switch (settings.on_headers_complete.cb(parser)) {
-    //            case 0:
-    //              break;
-    //
-    //            case 1:
-    //              flags |= F_SKIPBODY;
-    //              break;
-    //
-    //            default:
-    //              return p - data; /* Error */ // TODO // RuntimeException ?
-    //          }
-    //        }
-
-
-    // Exit, the rest of the connect is in a different protocol.
-    if (upgrade) {
-      settings.call_on_message_complete(this);
-      state = State.body_identity_eof;
-      return true;
-    }
-
-    if (0 != (flags & F_SKIPBODY)) {
-      settings.call_on_message_complete(this);
-      state = new_message(); 
-    } else if (0 != (flags & F_CHUNKED)) {
-      /* chunked encoding - ignore Content-Length header */
-      state = State.chunk_size_start;
-    } else {
-      if (content_length == 0) {
-        /* Content-Length header given but zero: Content-Length: 0\r\n */
-        settings.call_on_message_complete(this);
-        state = new_message(); 
-      } else if (content_length > 0) {
-        /* Content-Length header given and non-zero */
-        state = State.body_identity;
-      } else {
-        if (type == ParserType.HTTP_REQUEST || http_should_keep_alive()) {
-          /* Assume content-length 0 - read the next */
-          settings.call_on_message_complete(this);
-          state = new_message(); 
-        } else {
-          /* Read body until EOF */
-          state = State.body_identity_eof;
-        }
-      }
-    }
-    return true;
-  } // headers_almost_fone
-
-
-  final int min (int a, int b) {
-    return a < b ? a : b;
-  }
-  
-  /* probably not the best place to hide this ... */
-	public boolean HTTP_PARSER_STRICT;
-  State new_message() {
-    if (HTTP_PARSER_STRICT){
-      return http_should_keep_alive() ? start_state() : State.dead;
-    } else {
-      return start_state();
-    }
-
-  }
-	
-  State start_state() {
-    return type == ParserType.HTTP_REQUEST ? State.start_req : State.start_res;
-  }
-
-
-	boolean parsing_header(State state) {
-
-		switch (state) {
-			case chunk_data :
-			case chunk_data_almost_done :
-			case chunk_data_done :
-			case body_identity :
-			case body_identity_eof :
-				return false;
-
-		}
-    return true;
-	}
-
-	/* "Dial C for Constants" */
-  static class C {
-    static final int HTTP_MAX_HEADER_SIZE = 80 * 1024;
-
-    static final int F_CHUNKED               = 1 << 0;
-    static final int F_CONNECTION_KEEP_ALIVE = 1 << 1;
-    static final int F_CONNECTION_CLOSE      = 1 << 2;
-    static final int F_TRAILING              = 1 << 3;
-    static final int F_UPGRADE               = 1 << 4;
-    static final int F_SKIPBODY              = 1 << 5;
-
-    static final byte [] UPCASE = {
-      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-      0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,
-      0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,  0x38,0x39,0x00,0x00,0x00,0x00,0x00,0x00,
-      0x00,0x41,0x42,0x43,0x44,0x45,0x46,0x47,  0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
-      0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,  0x58,0x59,0x5a,0x00,0x00,0x00,0x00,0x5f,
-      0x00,0x41,0x42,0x43,0x44,0x45,0x46,0x47,  0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
-      0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,  0x58,0x59,0x5a,0x00,0x00,0x00,0x00,0x00,
-      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-    };
-    static final byte [] CONNECTION = {
-      0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 
-    };
-    static final byte [] PROXY_CONNECTION = {
-      0x50, 0x52, 0x4f, 0x58, 0x59, 0x2d, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 
-    };
-    static final byte [] CONTENT_LENGTH = {
-      0x43, 0x4f, 0x4e, 0x54, 0x45, 0x4e, 0x54, 0x2d, 0x4c, 0x45, 0x4e, 0x47, 0x54, 0x48, 
-    };
-    static final byte [] TRANSFER_ENCODING = {
-      0x54, 0x52, 0x41, 0x4e, 0x53, 0x46, 0x45, 0x52, 0x2d, 0x45, 0x4e, 0x43, 0x4f, 0x44, 0x49, 0x4e, 0x47, 
-    };
-    static final byte [] UPGRADE = {
-      0x55, 0x50, 0x47, 0x52, 0x41, 0x44, 0x45, 
-    };
-    static final byte [] CHUNKED = {
-      0x43, 0x48, 0x55, 0x4e, 0x4b, 0x45, 0x44, 
-    };
-    static final byte [] KEEP_ALIVE = {
-      0x4b, 0x45, 0x45, 0x50, 0x2d, 0x41, 0x4c, 0x49, 0x56, 0x45, 
-    };
-    static final byte [] CLOSE = {
-      0x43, 0x4c, 0x4f, 0x53, 0x45, 
-    };
-
-    /* Tokens as defined by rfc 2616. Also lowercases them.
-     *        token       = 1*<any CHAR except CTLs or separators>
-     *     separators     = "(" | ")" | "<" | ">" | "@"
-     *                    | "," | ";" | ":" | "\" | <">
-     *                    | "/" | "[" | "]" | "?" | "="
-     *                    | "{" | "}" | SP | HT
-     */
-
-    static final char [] tokens = {
-/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */
-       ' ',     '!',     '"',     '#',     '$',     '%',     '&',    '\'',
-/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */
-        0,       0,      '*',     '+',       0,     '-',     '.',     '/' ,
-/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */
-       '0',     '1',     '2',     '3',     '4',     '5',     '6',     '7',
-/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */
-       '8',     '9',      0,       0,       0,       0,       0,       0,
-/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */
-        0,      'A',     'B',     'C',     'D',     'E',     'F',     'G',
-/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */
-       'H',     'I',     'J',     'K',     'L',     'M',     'N',     'O',
-/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */
-       'P',     'Q',     'R',     'S',     'T',     'U',     'V',     'W',
-/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */
-       'X',     'Y',     'Z',      0,       0,       0,       0,      '_',
-/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */
-        0,      'A',     'B',     'C',     'D',     'E',     'F',     'G',
-/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */
-       'H',     'I',     'J',     'K',     'L',     'M',     'N',     'O',
-/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */
-       'P',     'Q',     'R',     'S',     'T',     'U',     'V',     'W',
-/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */
-       'X',     'Y',     'Z',      0,      '|',     '}',      0,       0,
-/* hi bit set, not ascii                                                  */
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0,
-        0,       0,       0,       0,       0,       0,       0,       0, };
-
-    static final byte [] UNHEX =
-    {    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
-        ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-        ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-    };
-
-    static final boolean [] normal_url_char = {
-/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */
-    false,   false,   false,   false,   false,   false,   false,   false,
-/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */
-    false,   false,   false,   false,   false,   false,   false,   false,
-/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */
-    false,   false,   false,   false,   false,   false,   false,   false,
-/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */
-    false,   false,   false,   false,   false,   false,   false,   false,
-/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */
-    false,    true,    true,   false,    true,    true,    true,    true,
-/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */
-     true,    true,    true,    true,    true,    true,    true,    true,
-/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */
-     true,    true,    true,    true,    true,    true,    true,    true,
-/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */
-     true,    true,    true,    true,    true,    true,    true,   false,
-/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */
-     true,    true,    true,    true,    true,    true,    true,    true,
-/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */
-     true,    true,    true,    true,    true,    true,    true,    true,
-/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */
-     true,    true,    true,    true,    true,    true,    true,    true,
-/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */
-     true,    true,    true,    true,    true,    true,    true,    true,
-/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */
-     true,    true,    true,    true,    true,    true,    true,    true,
-/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */
-     true,    true,    true,    true,    true,    true,    true,    true,
-/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */
-     true,    true,    true,    true,    true,    true,    true,    true,
-/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */
-     true,    true,    true,    true,    true,    true,    true,   false,
-
-/*    hi bit set, not ascii                                                  */
-/*    Remainder of non-ASCII range are accepted as-is to support implicitly UTF-8
- *    encoded paths. This is out of spec, but clients generate this and most other
- *    HTTP servers support it. We should, too. */
-
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-     true,    true,    true,    true,    true,    true,    true,    true, 
-    
-    };
-
-    public static final byte A = 0x41;
-    public static final byte B = 0x42;
-    public static final byte C = 0x43;
-    public static final byte D = 0x44;
-    public static final byte E = 0x45;
-    public static final byte F = 0x46;
-    public static final byte G = 0x47;
-    public static final byte H = 0x48;
-    public static final byte I = 0x49;
-    public static final byte J = 0x4a;
-    public static final byte K = 0x4b;
-    public static final byte L = 0x4c;
-    public static final byte M = 0x4d;
-    public static final byte N = 0x4e;
-    public static final byte O = 0x4f;
-    public static final byte P = 0x50;
-    public static final byte Q = 0x51;
-    public static final byte R = 0x52;
-    public static final byte S = 0x53;
-    public static final byte T = 0x54;
-    public static final byte U = 0x55;
-    public static final byte V = 0x56;
-    public static final byte W = 0x57;
-    public static final byte X = 0x58;
-    public static final byte Y = 0x59;
-    public static final byte Z = 0x5a;
-    public static final byte CR = 0x0d;
-    public static final byte LF = 0x0a;
-    public static final byte DOT = 0x2e;
-    public static final byte SPACE = 0x20;
-    public static final byte SEMI = 0x3b;
-    public static final byte COLON = 0x3a;
-    public static final byte HASH = 0x23;
-    public static final byte QMARK = 0x3f;
-    public static final byte SLASH = 0x2f;
-    public static final byte DASH = 0x2d;
-    public static final byte STAR = 0x2a;
-    public static final byte NULL = 0x00;
-  }
-
-  enum State {
-
-    dead               
-
-    , start_res_or_res
-    , res_or_resp_H
-    , start_res
-    , res_H
-    , res_HT
-    , res_HTT
-    , res_HTTP
-    , res_first_http_major
-    , res_http_major
-    , res_first_http_minor
-    , res_http_minor
-    , res_first_status_code
-    , res_status_code
-    , res_status
-    , res_line_almost_done
-
-    , start_req
-
-    , req_method
-    , req_spaces_before_url
-    , req_schema
-    , req_schema_slash
-    , req_schema_slash_slash
-    , req_host
-    , req_port
-    , req_path
-    , req_query_string_start
-    , req_query_string
-    , req_fragment_start
-    , req_fragment
-    , req_http_start
-    , req_http_H
-    , req_http_HT
-    , req_http_HTT
-    , req_http_HTTP
-    , req_first_http_major
-    , req_http_major
-    , req_first_http_minor
-    , req_http_minor
-    , req_line_almost_done
-
-    , header_field_start
-    , header_field
-    , header_value_start
-    , header_value
-
-    , header_almost_done
-
-    , chunk_size_start
-    , chunk_size
-    , chunk_parameters
-    , chunk_size_almost_done
-
-    , headers_almost_done
-// This space intentionally not left blank, comment from c, for orientation...
-// the c version uses <= s_header_almost_done in java, we list the states explicitly
-// in `parsing_header()`
-/* Important: 's_headers_almost_done' must be the last 'header' state. All
- * states beyond this must be 'body' states. It is used for overflow
- * checking. See the PARSING_HEADER() macro.
- */
-    , chunk_data
-    , chunk_data_almost_done
-    , chunk_data_done
-
-    , body_identity
-    , body_identity_eof;
-
-
-  }
-  enum HState {
-      general
-    , C
-    , CO
-    , CON
-
-    , matching_connection
-    , matching_proxy_connection
-    , matching_content_length
-    , matching_transfer_encoding
-    , matching_upgrade
-
-    , connection
-    , content_length
-    , transfer_encoding
-    , upgrade
-
-    , matching_transfer_encoding_chunked
-    , matching_connection_keep_alive
-    , matching_connection_close
-
-    , transfer_encoding_chunked
-    , connection_keep_alive
-    , connection_close
-  }
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java b/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java
deleted file mode 100644
index 6690384..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package http_parser.lolevel;
-import java.nio.ByteBuffer;
-import http_parser.HTTPException;
-public class ParserSettings {
-	
-  public HTTPCallback       on_message_begin;
-  public HTTPDataCallback 	on_path;
-  public HTTPDataCallback 	on_query_string;
-  public HTTPDataCallback 	on_url;
-  public HTTPDataCallback 	on_fragment;
-  public HTTPDataCallback 	on_header_field;
-  public HTTPDataCallback 	on_header_value;
-  public HTTPCallback       on_headers_complete;
-  public HTTPDataCallback 	on_body;
-  public HTTPCallback       on_message_complete;
-  public HTTPErrorCallback  on_error;
-
-	void call_on_message_begin (HTTPParser p) {
-		call_on(on_message_begin, p);
-	}
-
-	void call_on_message_complete (HTTPParser p) {
-		call_on(on_message_complete, p);
-	}
-  
-  // this one is a little bit different:
-  // the current `position` of the buffer is the location of the
-  // error, `ini_pos` indicates where the position of
-  // the buffer when it was passed to the `execute` method of the parser, i.e.
-  // using this information and `limit` we'll know all the valid data
-  // in the buffer around the error we can use to print pretty error
-  // messages.
-  void call_on_error (HTTPParser p, String mes, ByteBuffer buf, int ini_pos) {
-    if (null != on_error) {
-      on_error.cb(p, mes, buf, ini_pos);
-      return;
-    }
-    // if on_error gets called it MUST throw an exception, else the parser 
-    // will attempt to continue parsing, which it can't because it's
-    // in an invalid state.
-    throw new HTTPException(mes);
-	}
-
-	void call_on_header_field (HTTPParser p, ByteBuffer buf, int pos, int len) {
-		call_on(on_header_field, p, buf, pos, len);
-	}
-	void call_on_query_string (HTTPParser p, ByteBuffer buf, int pos, int len) {
-		call_on(on_query_string, p, buf, pos, len);
-	}
-	void call_on_fragment (HTTPParser p, ByteBuffer buf, int pos, int len) {
-		call_on(on_fragment, p, buf, pos, len);
-	}
-	void call_on_path (HTTPParser p, ByteBuffer buf, int pos, int len) {
-		call_on(on_path, p, buf, pos, len);
-	}
-	void call_on_header_value (HTTPParser p, ByteBuffer buf, int pos, int len) {
-		call_on(on_header_value, p, buf, pos, len);
-	}
-	void call_on_url (HTTPParser p, ByteBuffer buf, int pos, int len) {
-		call_on(on_url, p, buf, pos, len);
-	}
-	void call_on_body(HTTPParser p, ByteBuffer buf, int pos, int len) {
-		call_on(on_body, p, buf, pos, len);
-	}
-	void call_on_headers_complete(HTTPParser p) {
-		call_on(on_headers_complete, p);
-	} 
-	void call_on (HTTPCallback cb, HTTPParser p) {
-		// cf. CALLBACK2 macro
-		if (null != cb) {
-			cb.cb(p);
-		}
-	}
-	void call_on (HTTPDataCallback cb, HTTPParser p, ByteBuffer buf, int pos, int len) {
-		if (null != cb && -1 != pos) {
-			cb.cb(p,buf,pos,len);
-		}
-	}
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Message.java b/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Message.java
deleted file mode 100644
index 267478d..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Message.java
+++ /dev/null
@@ -1,324 +0,0 @@
-package http_parser.lolevel;
-
-import java.nio.*;
-import java.io.*;
-import java.util.*;
-
-import http_parser.HTTPMethod;
-import http_parser.ParserType;
-import http_parser.lolevel.TestLoaderNG.TestSettings;
-import http_parser.lolevel.TestLoaderNG.Header;
-import http_parser.lolevel.TestLoaderNG.LastHeader;
-
-import static http_parser.lolevel.Util.str;
-
-public class Message {
-  String name; 
-  byte [] raw; 
-  ParserType type; 
-  HTTPMethod method;
-  int status_code;
-  String request_path; // byte [] ?
-  String request_url;
-  String fragment ;
-  String query_string;
-  byte [] body;
-  int body_size;
-  int num_headers;
-  LastHeader last_header_element;
-  Map<String,String> header;
-  List<Header> headers;
-  boolean should_keep_alive;
-
-  boolean upgrade;
-
-  int http_major;
-  int http_minor;
-
-  boolean message_begin_called;
-  boolean headers_complete_called;
-  boolean message_complete_called;
-  boolean message_complete_on_eof;
-  
-
-  Map<String,String> parsed_header;
-  String currHField;
-  String currHValue;
-  byte [] pbody;
-  int num_called;
-
-  public String toString() {
-    StringBuilder b = new StringBuilder();
-    b.append("type: "); b.append(type);b.append("\n");
-    b.append("method: "); b.append(method);b.append("\n");
-    b.append("status_code: "); b.append(status_code);b.append("\n");
-    b.append("request_path: "); b.append(request_path);b.append("\n");
-    b.append("request_url: "); b.append(request_url);b.append("\n");
-    b.append("fragment: "); b.append(fragment);b.append("\n");
-    b.append("query_string: "); b.append(query_string);b.append("\n");
-    b.append("body:\n"); b.append(new String(body));b.append("\n");
-    b.append("should_keep_alive: "); b.append(should_keep_alive);b.append("\n");
-    b.append("upgrade: "); b.append(upgrade);b.append("\n");
-    b.append("http_major: "); b.append(http_major);b.append("\n");
-    b.append("http_minor: "); b.append(http_minor);b.append("\n");
-    b.append("message_complete_called: "); b.append(message_complete_called);b.append("\n");
-    return b.toString();
-  }
-
-  Message () {
-    this.header        = new HashMap<String, String>();
-    this.headers = new LinkedList<Header>();
-    reset();
-  }
-  /*
-   *prepare this Test Instance for reuse.
-   * */
-  void reset () {
-    this.parsed_header = new HashMap<String, String>();
-    this.pbody         = null;
-    this.num_called    = 0;
-
-  }
-  void check (boolean val, String mes) {
-    if (!val) {
-      //p(name+" : "+mes);
-      throw new RuntimeException(name+" : "+mes);
-    }
-  }
-
-
-  HTTPDataCallback getCB (final String value, final String mes, final TestSettings settings) {
-    return new HTTPDataCallback() {
-      public int cb (HTTPParser p, ByteBuffer b, int pos, int len){
-        //   if ("url".equals(mes)){
-        //    p("pos"+pos);
-        //    p("len"+len);
-        //    if (8==pos && 5 == len && "connect request".equals(name)) {
-        //      //throw new RuntimeException(name);
-        //    }
-        //   }
-        String str      = str(b, pos, len);
-        String prev_val = settings.map.get(mes);
-        settings.map.put(mes, prev_val + str);
-        //check(value.equals(str), "incorrect "+mes+": "+str);
-        if (-1 == pos) {
-          throw new RuntimeException("he?");
-        }
-        return 0;
-      }
-    };
-  }
-
-  void execute () {
-    p(name);
-    ByteBuffer   buf = ByteBuffer.wrap(raw);
-    HTTPParser     p = new HTTPParser();
-    TestSettings s = settings();
-
-
-
-    p.execute(s, buf);
-    if (!s.success) {
-      throw new RuntimeException("Test: "+name+"failed");
-    }
-  } // execute
-
-  void execute_permutations() {
-    /*
-       |-|---------------|	
-       |--|--------------|	
-       |---|-------------|	
-       (...)
-       |---------------|-|	
-       |-----------------|	
-       */
-    p(name);
-    for (int i = 2; i != raw.length; ++i) {
-      //  p(i);
-      HTTPParser   p = new HTTPParser();
-      TestSettings s = settings();
-      ByteBuffer buf = ByteBuffer.wrap(raw);
-      int olimit = buf.limit();
-      buf.limit(i);
-
-      parse(p,s,buf);
-
-      buf.position(i);
-      buf.limit(olimit);
-
-      parse(p,s,buf);
-      parse(p,s,buf);
-
-      if (!s.success) {
-        p(this);
-        throw new RuntimeException("Test: "+name+" failed");
-      }
-      reset();
-    }
-    //System.exit(0);
-  } // execute_permutations
-  void parse(HTTPParser p, ParserSettings s, ByteBuffer b) {
-    //p("About to parse: "+b.position() + "->" + b.limit());
-    p.execute(s, b);
-  }
-
-  TestSettings settings() {
-    final TestSettings s = new TestSettings(); 
-    s.on_path         = getCB(request_path, "path", s);
-    s.on_query_string = getCB(query_string, "query_string", s);
-    s.on_url          = getCB(request_url,  "url", s);
-    s.on_fragment     = getCB(fragment,     "fragment", s);
-    s.on_message_begin = new HTTPCallback() {
-      public int cb (HTTPParser p) {
-        message_begin_called = true;
-        return -1;
-      }
-    };
-    s.on_header_field = new HTTPDataCallback() {
-      public int cb (HTTPParser p, ByteBuffer b, int pos, int len){
-        if (null != currHValue && null == currHField) {
-          throw new RuntimeException(name+": shouldn't happen");
-        }
-        if (null != currHField) {
-          if (null == currHValue) {
-            currHField += str(b,pos,len);
-            return 0;
-          } else {
-            parsed_header.put(currHField, currHValue);
-            currHField = null;
-            currHValue = null;
-          }
-        }
-        currHField = str(b,pos,len);
-        return 0;
-      }
-    };
-    s.on_header_value = new HTTPDataCallback() {
-      public int cb (HTTPParser p, ByteBuffer b, int pos, int len){
-        if (null == currHField) {
-          throw new RuntimeException(name+" :shouldn't happen field");
-        }
-        if (null == currHValue) {
-          currHValue = str(b,pos,len);
-        } else {
-          currHValue += str(b, pos, len);
-        }
-        return 0;
-      }
-    };
-    s.on_headers_complete = new HTTPCallback() {
-      public int cb (HTTPParser p) {
-        headers_complete_called = true;
-        String parsed_path  = s.map.get("path");
-        String parsed_query = s.map.get("query_string");
-        String parsed_url   = s.map.get("url");
-        String parsed_frag  = s.map.get("fragment");
-
-        if (!request_path.equals(parsed_path)) {
-          throw new RuntimeException(name+": invalid path: "+parsed_path+" should be: "+request_path);
-        }
-        if (!query_string.equals(parsed_query)) {
-          throw new RuntimeException(name+": invalid query: "+parsed_query+" should be: "+query_string);
-        }
-        if (!request_url.equals(parsed_url)) {
-          throw new RuntimeException(">"+name+"<: invalid url: >"+parsed_url+"< should be: >"+request_url+"<");
-        }
-        if (!fragment.equals(parsed_frag)) {
-          throw new RuntimeException(name+": invalid fragement: "+parsed_frag+" should be: "+fragment);
-        }
-        if (null != currHValue || null != currHField) {
-          if (null == currHField || null == currHValue) {
-            throw new RuntimeException("shouldn't happen");
-          }
-        }
-        if (null != currHField) {
-          //p(currHField);
-          //p(">"+currHValue+"<");
-          parsed_header.put(currHField, currHValue);
-          currHField = null;
-          currHValue = null;
-        }
-
-
-        return 0;
-      }
-    };
-    //	s.on_headers_complete = new HTTPCallback() {
-    //		public int cb (HTTPParser p) {
-    //			p("Complete:"+name);
-    //			return 0;
-    //		}
-    //	};
-
-    s.on_body = new HTTPDataCallback() {
-      public int cb (HTTPParser p, ByteBuffer b, int pos, int len){
-        int l   = pbody == null ? len : len + pbody.length;
-        int off = pbody == null ?   0 : pbody.length;
-        byte [] nbody = new byte[l];
-
-        if (null != pbody) {
-          System.arraycopy(pbody, 0, nbody, 0, pbody.length);
-        }
-
-        int saved = b.position();
-        b.position(pos);
-        b.get(nbody, off, len);
-        b.position(saved);
-        pbody = nbody;
-        return 0;
-      }
-    };
-
-    s.on_message_complete = new HTTPCallback() {
-      public int cb(HTTPParser p) {
-        message_complete_called = true;
-        num_called += 1;
-        if (   p.http_minor  != http_minor
-            || p.http_major  != http_major
-            || p.status_code != status_code ) {
-
-          throw new RuntimeException("major/minor/status_code mismatch");
-            }
-
-        //check headers
-
-        if (header.keySet().size() != parsed_header.keySet().size()) {
-          p(parsed_header);
-          throw new RuntimeException(name+": different amount of headers");
-        }
-        for (String key : header.keySet()) {
-          String pvalue = parsed_header.get(key);
-          if (!header.get(key).equals(pvalue)) {
-            throw new RuntimeException(name+" : different values for :"+key+" is >"+pvalue+"< should: >"+header.get(key)+"<");
-          }
-        }
-        //check body
-        if (null == pbody && (null == body || body.length == 0 || body.length == 1)) {
-          s.success = true;
-          return 0;
-        }
-        if (null == pbody) {
-          throw new RuntimeException(name+": no body, should be: "+new String(body));
-        }
-        if (pbody.length != body.length) {
-          p(pbody.length);
-          p(body.length);
-          p(new String(pbody));
-          p(new String(body));
-          throw new RuntimeException(name+": incorrect body length");
-        }
-        for (int i = 0 ; i!= body.length; ++i) {
-          if (pbody[i] != body[i]) {
-            throw new RuntimeException("different body");
-          }
-        }
-        s.success = true;
-        return 0;
-      }
-    };
-    return s;
-  } // settings
-  static void p(Object o) {
-    System.out.println(o);
-  }
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Requests.java b/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Requests.java
deleted file mode 100644
index 46ce1d2..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Requests.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package http_parser.lolevel;
-
-import java.nio.*;
-import java.util.*;
-
-import static http_parser.lolevel.Util.*;
-import http_parser.*;
-
-import primitive.collection.ByteList;
-
-public class Requests {
-  
-  static void test_simple(String req, boolean should_pass) {
-    HTTPParser parser = new HTTPParser(ParserType.HTTP_REQUEST);
-    ByteBuffer buf = buffer(req);
-    boolean passed = false;
-    int read = 0;
-    try {
-      parser.execute(Util.SETTINGS_NULL, buf);
-      passed = (read == req.length());
-      read = parser.execute(Util.SETTINGS_NULL, Util.empty());
-      passed &= (0 == read);
-    } catch (Throwable t) {
-      passed = false;
-    }
-    check(passed == should_pass);
-  }
-  static void simple_tests() {
-    test_simple("hello world", false);
-    test_simple("GET / HTP/1.1\r\n\r\n", false);
-
-    test_simple("ASDF / HTTP/1.1\r\n\r\n", false);
-    test_simple("PROPPATCHA / HTTP/1.1\r\n\r\n", false);
-    test_simple("GETA / HTTP/1.1\r\n\r\n", false);
-  }
-
-  public static void test () {
-    
-    simple_tests();
-    
-    List<Message> all = TestLoaderNG.load("tests.dumped");
-    List<Message> requests = new LinkedList<Message>();
-    for (Message m : all) {
-      if (ParserType.HTTP_REQUEST == m.type) {
-        requests.add(m);
-      }
-    }
-    for (Message m : requests) {
-      test_message(m);
-    }
-    
-    for (int i = 0; i!= requests.size(); ++i) {
-      if (!requests.get(i).should_keep_alive) continue;
-      for (int j = 0; j!=requests.size(); ++j) {
-        if (!requests.get(j).should_keep_alive) continue;
-        for (int k = 0; k!= requests.size(); ++k) {
-          test_multiple3(requests.get(i), requests.get(j), requests.get(k));
-        }
-      }
-    }
-    
-    // postpone test_scan
-
-  }
-
-  
-
-
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Responses.java b/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Responses.java
deleted file mode 100644
index d73b8bc..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Responses.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package http_parser.lolevel;
-
-import java.nio.*;
-import java.util.*;
-
-import static http_parser.lolevel.Util.*;
-import http_parser.*;
-
-import primitive.collection.ByteList;
-
-public class Responses {
-
-  
-
-  public static void test () {
-    List<Message> all = TestLoaderNG.load("tests.dumped");
-    List<Message> responses = new LinkedList<Message>();
-    for (Message m : all) {
-      if (ParserType.HTTP_RESPONSE == m.type) {
-        responses.add(m);
-      }
-    }
-    for (Message m : responses) {
-      test_message(m);
-    }
-    
-    for (int i = 0; i!= responses.size(); ++i) {
-      if (!responses.get(i).should_keep_alive) continue;
-      for (int j = 0; j!=responses.size(); ++j) {
-        if (!responses.get(j).should_keep_alive) continue;
-        for (int k = 0; k!= responses.size(); ++k) {
-          test_multiple3(responses.get(i), responses.get(j), responses.get(k));
-        }
-      }
-    }
-
-  // not sure what test_message_count_body does that test_message doesn't...
-  //   Message m = find(responses, "404 no headers no body");
-  //   test_message_count_body(m);
-  //           m = find(responses, "200 trailing space on chunked body");
-  //   test_message_count_body(m);
-
-  // TODO test very large chunked response  
-
-  // test_scan is more or less the same as test_permutations, will implement later...
-  }
-
-  
-
-
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Test.java b/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Test.java
deleted file mode 100644
index 4b026e1..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Test.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package http_parser.lolevel;
-
-
-public class Test {
-  public static void main (String [] args) {
-    UnitTest.test();
-    TestHeaderOverflowError.test();
-    TestNoOverflowLongBody.test();
-    Responses.test();
-    //Requests.test();
-    Upgrade.test();
-    WrongContentLength.test();
-  }
-
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestHeaderOverflowError.java b/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestHeaderOverflowError.java
deleted file mode 100644
index 321ce4d..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestHeaderOverflowError.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package http_parser.lolevel;
-
-import java.nio.*;
-
-import static http_parser.lolevel.Util.*;
-
-public class TestHeaderOverflowError {
-
-  public static void test (http_parser.ParserType type) {
-    HTTPParser parser = new HTTPParser(type);
-    ByteBuffer buf    = getBytes(type);
-    
-    int numbytes = buf.limit();
-
-    parser.execute(Util.SETTINGS_NULL, buf);
-
-    check(numbytes == buf.position());
-
-    buf      = buffer("header-key: header-value\r\n");
-    numbytes = buf.limit();
-    for (int i = 0; i!= 1000; ++i) {
-      parser.execute(Util.SETTINGS_NULL, buf);
-      check(numbytes == buf.position());
-
-      buf.rewind();
-
-    }
-  }
-
-  static ByteBuffer getBytes (http_parser.ParserType type) {
-    if (http_parser.ParserType.HTTP_BOTH == type) {
-      throw new RuntimeException("only HTTP_REQUEST and HTTP_RESPONSE");
-    }
-
-    if (http_parser.ParserType.HTTP_REQUEST == type) {
-      return buffer("GET / HTTP/1.1\r\n"); 
-    }
-    return buffer("HTTP/1.0 200 OK\r\n");
-  }
-
-  public static void test () {
-    test(http_parser.ParserType.HTTP_REQUEST);
-    test(http_parser.ParserType.HTTP_RESPONSE);
-  }
-
-
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestLoaderNG.java b/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestLoaderNG.java
deleted file mode 100644
index c934939..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestLoaderNG.java
+++ /dev/null
@@ -1,223 +0,0 @@
-package http_parser.lolevel;
-// name  : 200 trailing space on chunked body
-// raw   : "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nTransfer-Encoding: chunked\r\n\r\n25  \r\nThis is the data in the first chunk\r\n\r\n1C\r\nand this is the second one\r\n\r\n0  \r\n\r\n"
-// type  : HTTP_RESPONSE
-// method: HTTP_DELETE
-// status code :200
-// request_path:
-// request_url :
-// fragment    :
-// query_string:
-// body        :"This is the data in the first chunk\r\nand this is the second one\r\n"
-// body_size   :65
-// header_0 :{ "Content-Type": "text/plain"}
-// header_1 :{ "Transfer-Encoding": "chunked"}
-// should_keep_alive         :1
-// upgrade                   :0
-// http_major                :1
-// http_minor                :1
-
-
-import java.io.FileReader;
-import java.io.BufferedReader;
-import java.io.StringReader;
-import java.io.Reader;
-import java.io.Reader;
-import java.io.IOException;
-
-import java.util.*;
-import java.util.regex.*;
-
-import java.nio.ByteBuffer;
-
-import http_parser.HTTPMethod;
-import http_parser.ParserType;
-
-public class TestLoaderNG {
-  String fn;
-  public TestLoaderNG(String filename) {
-    this.fn = filename;
-  }
-  static void p(Object o) {
-    System.out.println(o);
-  }
-  public static List<Message> load (String fn) {
-    List<Message> list = null;
-    try {
-      BufferedReader buf = new BufferedReader(new FileReader(fn));
-      list = load(buf);
-    } catch (Throwable t) {
-      throw new RuntimeException(t);
-    }
-      return list;
-
-  }
-  public static Message parse (String message) {
-    List<Message> list = load(new BufferedReader(new StringReader(message)));  
-    if (null == list || 0 == list.size() ) {
-      return null;
-    } 
-    return list.get(0);
-  }
-
-  public static List<Message> load (BufferedReader buf) {
-    List<Message>    list = new LinkedList<Message>();
-    String        line = null;
-    Message          curr = new Message();
-    Pattern    pattern = Pattern.compile("(\\S+)\\s*:(.*)");
-    try {
-      while (null != (line = buf.readLine()) ){
-        if ("".equals(line.trim())) {
-          list.add (curr);
-          curr = new Message();
-          continue;
-        }
-        Matcher m = pattern.matcher(line);
-        if (m.matches()) {
-          // you can not be fucking serious!?
-          // this has got to be the most retarded regex 
-          // interface in the history of the world ...
-          // (though I'm sure there's worse c++ regexp libs...)
-          MatchResult r = m.toMatchResult();
-          String    key = r.group(1).trim();
-          String  value = r.group(2).trim();
-               if ("name".equals(key))         {curr.name = value;}
-          else if ("raw".equals(key))          {curr.raw = toByteArray(value);} //!
-          else if ("type".equals(key))         {curr.type = ParserType.parse(value);}
-          else if ("method".equals(key))       {curr.method = HTTPMethod.parse(value);}
-          else if ("status_code".equals(key))  {curr.status_code = Integer.parseInt(value);}
-          else if ("request_path".equals(key)) {curr.request_path = value;}
-          else if ("request_url".equals(key))  {curr.request_url = value;}
-
-          else if ("fragment".equals(key))     {curr.fragment = value;}
-          else if ("query_string".equals(key)) {curr.query_string = value;}
-          else if ("body".equals(key))         {curr.body = toByteArray(value);} //!
-          else if ("body_size".equals(key))    {curr.body_size = Integer.parseInt(value);}
-          else if (key.startsWith("header"))   {
-            String [] h = getHeader(value); 
-            curr.header.put(h[0], h[1]);
-          } 
-          else if ("should_keep_alive".equals(key)) 
-          {curr.should_keep_alive = (1 == Integer.parseInt(value));}
-          else if ("upgrade".equals(key))      {curr.upgrade           = (1 == Integer.parseInt(value));}
-          else if ("http_major".equals(key))   {curr.http_major = Integer.parseInt(value);}
-          else if ("http_minor".equals(key))   {curr.http_minor = Integer.parseInt(value);}
-        } else {
-          p("WTF?"+line);
-        }
-
-      }
-    } catch (Throwable t) {
-      throw new RuntimeException(t);
-    }
-    return list;
-  }
-
-  static String [] getHeader(String value) {
-    // { "Host": "0.0.0.0=5000"}
-    Pattern p = Pattern.compile("\\{ ?\"([^\"]*)\": ?\"(.*)\"}");
-    Matcher m = p.matcher(value);
-    if (!m.matches()) {
-      p(value);
-      throw new RuntimeException("something wrong");
-    }
-    String [] result = new String[2];
-    MatchResult r = m.toMatchResult();
-    result[0] = r.group(1).trim();
-    result[1] = r.group(2); //.trim();
-    return result;
-  }
-
-  static final byte BSLASH = 0x5c;
-  static final byte QUOT   = 0x22;
-  static final byte CR     = 0x0d;
-  static final byte LF     = 0x0a;
-  static final byte n      = 0x6e;
-  static final byte r      = 0x72;
-
-  static final Byte[] JAVA_GENERICS_ROCK_HARD = new Byte[0];
-
-
-  static byte [] toByteArray (String quotedString) {
-    ArrayList<Byte> bytes = new ArrayList<Byte>();
-    String s = quotedString.substring(1, quotedString.length()-1);
-    byte [] byts = s.getBytes(java.nio.charset.Charset.forName("UTF8"));
-    boolean escaped = false;
-    for (byte b : byts) {
-      switch (b) {
-        case BSLASH:
-          escaped = true;
-          break;
-        case n:
-          if (escaped) {
-            bytes.add(LF);
-            escaped = false;
-          } else {
-            bytes.add(b);
-          }
-          break;
-        case r:
-          if (escaped) {
-            escaped = false;
-            bytes.add(CR);
-          } else {
-            bytes.add(b);
-          }
-          break;
-        case QUOT:
-          escaped = false;
-          bytes.add(QUOT);
-          break;
-        default:
-          bytes.add(b);
-      }
-
-    }
-
-    byts = new byte[bytes.size()];
-    int i = 0;
-    for (Byte b : bytes) {
-      byts[i++]=b;
-    }
-    return byts;
-  }
-
-  public static void main(String [] args) throws Throwable {
-    //TestLoaderNG  l = new TestLoaderNG(args[0]);
-    List<Message> ts = load(args[0]);
-    for (Message t : ts) {
-//      for (int i =0; i!= t.raw.length; ++i) {
-//        p(i+":"+t.raw[i]);
-//      }
-      try {
-      t.execute_permutations();
-      } catch (Throwable th) {
-        p("failed: "+t.name);
-      }
-      //	t.execute();
-      //	System.exit(0);
-    }
-  }
-
-  class Header {
-    String field;
-    String value;
-  }
-  enum LastHeader {
-    NONE
-      ,FIELD
-      ,VALUE
-  }
-
-  static class TestSettings extends ParserSettings {
-    public boolean success;
-    Map<String, String> map;
-    TestSettings () {
-      map = new HashMap<String, String>();
-      map.put("path", "");
-      map.put("query_string", "");
-      map.put("url", "");
-      map.put("fragment", "");
-    }
-  }
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestNoOverflowLongBody.java b/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestNoOverflowLongBody.java
deleted file mode 100644
index b0aa3a3..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestNoOverflowLongBody.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package http_parser.lolevel;
-
-import java.nio.*;
-
-import static http_parser.lolevel.Util.*;
-
-public class TestNoOverflowLongBody {
-
-  public static void test (http_parser.ParserType type, int len) {
-    HTTPParser parser = new HTTPParser(type);
-    ByteBuffer buf    = getBytes(type, len);
-    
-    int buflen = buf.limit();
-
-    parser.execute(Util.SETTINGS_NULL, buf);
-
-    check(buflen == buf.position());
-
-    buf  = buffer("a");
-    buflen  = buf.limit();
-    
-    for (int i = 0; i!= len; ++i) {
-      parser.execute(Util.SETTINGS_NULL, buf);
-      check(buflen == buf.position());
-      buf.rewind();
-    }
-    
-    buf = getBytes(type, len);
-    buflen = buf.limit();
-
-    parser.execute(Util.SETTINGS_NULL, buf);
-
-    check(buflen == buf.position());
-
-  }
-
-  static ByteBuffer getBytes (http_parser.ParserType type, int length) {
-    if (http_parser.ParserType.HTTP_BOTH == type) {
-      throw new RuntimeException("only HTTP_REQUEST and HTTP_RESPONSE");
-    }
-    
-    String template = "%s\r\nConnection: Keep-Alive\r\nContent-Length: %d\r\n\r\n";
-    String str = null;
-    if (http_parser.ParserType.HTTP_REQUEST == type) {
-      str = String.format(template, "GET / HTTP/1.1", length); 
-    } else {
-      str = String.format(template, "HTTP/1.0 200 OK", length);
-    }
-    return buffer(str);
-  }
-
-  public static void test () {
-    test(http_parser.ParserType.HTTP_REQUEST, 1000);
-    test(http_parser.ParserType.HTTP_REQUEST, 100000);
-    test(http_parser.ParserType.HTTP_RESPONSE, 1000);
-    test(http_parser.ParserType.HTTP_RESPONSE, 100000);
-  }
-
-
-
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/UnitTest.java b/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/UnitTest.java
deleted file mode 100644
index 9627b2b..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/UnitTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package http_parser.lolevel;
-
-import java.nio.ByteBuffer;
-import http_parser.HTTPException;
-import http_parser.Util;
-
-public class UnitTest {
-
-	static void p(Object o) {System.out.println(o);}
-
-  public static void testErrorFormat() {
-    String bla = "This has an error in position 10 (the n in 'an')";
-    ByteBuffer buf = ByteBuffer.wrap(bla.getBytes());
-               buf.position(10); 
-      
-    String mes = 
-"This has an error in position 10 (the n in 'an')\n" +
-"..........^";
-
-    check_equals(mes, Util.error ("test error", buf, 0)); 
-   
-    
-    bla = "123456789A123456789B123456789C123456789D123456789E123456789F123456789G123456789H123456789I123456789J";
-    buf = ByteBuffer.wrap(bla.getBytes());
-    buf.position(50);
-    mes = 
-"56789B123456789C123456789D123456789E123456789F123456789G123456789H123456\n"+
-"....................................^";
-    check_equals(mes, Util.error("test trim right and left", buf, 0));
-
-
-    buf.position(5);
-    mes =
-"123456789A123456789B123456789C123456789D123456789E123456789F123456789G12\n"+
-".....^";
-    check_equals(mes, Util.error("test trim right", buf, 0));
-   
-
-    int limit = buf.limit();
-    buf.limit(10);
-    mes = 
-"123456789A\n"+
-".....^";
-    check_equals(mes,  Util.error("all before, not enough after", buf, 0));
-        
-
-
-    buf.limit(limit);
-    buf.position(90);  
-    mes = 
-"9C123456789D123456789E123456789F123456789G123456789H123456789I123456789J\n"+
-"..............................................................^";
-    check_equals(mes, Util.error("test trim left", buf, 10));       
-  }
-
-
-  // Test that the error callbacks are properly called.
-  public static void testErrorCallback () {
-      String nothttp   = "THis is certainly not valid HTTP";
-      ByteBuffer   buf = ByteBuffer.wrap(nothttp.getBytes());
-
-      ParserSettings s = new ParserSettings();
-                     s.on_error = new HTTPErrorCallback() {
-        public void cb (HTTPParser p, String mes, ByteBuffer buf, int pos) {
-          throw new HTTPException(mes);
-        }          
-                     }; // err callback
-      
-
-			HTTPParser     p = new HTTPParser();
-      try {               
-        p.execute(s, buf);
-      } catch (HTTPException e) {
-        check_equals("Invalid HTTP method", e.getMessage());
-      }
-
-      buf = ByteBuffer.wrap("GET / HTTP 1.10000".getBytes());
-			  p = new HTTPParser();
-      try {
-        p.execute(s, buf);
-      } catch (HTTPException e) {
-        check_equals("ridiculous http minor", e.getMessage());
-      }
-
-      // if no error handler is defined, behave just like the above...
-      ParserSettings s0 = new ParserSettings();
-      
-      buf = ByteBuffer.wrap("THis is certainly not valid HTTP".getBytes());
-			  p = new HTTPParser();
-      try {               
-        p.execute(s0, buf);
-      } catch (HTTPException e) {
-        check_equals("Invalid HTTP method", e.getMessage());
-      }
-
-      buf = ByteBuffer.wrap("GET / HTTP 1.10000".getBytes());
-			  p = new HTTPParser();
-      try {
-        p.execute(s0, buf);
-      } catch (HTTPException e) {
-        check_equals("ridiculous http minor", e.getMessage());
-      }
-  }
-
-  static void check_equals(Object supposed2be, Object is) {
-    if (!supposed2be.equals(is)) {
-      throw new RuntimeException(is + " is supposed to be "+supposed2be);
-    }
-  }
-
-
-  public static void test () {
-    testErrorFormat();
-    testErrorCallback();
-  }  
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Upgrade.java b/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Upgrade.java
deleted file mode 100644
index fc0f788..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Upgrade.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package http_parser.lolevel;
-
-import java.nio.*;
-import java.util.*;
-
-import http_parser.ParserType;
-
-import static http_parser.lolevel.Util.*;
-
-public class Upgrade {
-  static final String upgrade = "GET /demo HTTP/1.1\r\n" +
-                                "Connection: Upgrade\r\n" +
-                                "Upgrade: WebSocket\r\n\r\n" +
-                                "third key data";
-  static void test () {
-    HTTPParser parser = new HTTPParser(ParserType.HTTP_REQUEST);
-    ByteBuffer buf    = buffer(upgrade);
-    
-    int read = parser.execute(Util.SETTINGS_NULL, buf);
-    check (63 == read);
-    String s = str(buf);
-    check ("third key data".equals(str(buf)));
-  
-  }
-
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Util.java b/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Util.java
deleted file mode 100644
index cb70a09..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Util.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package http_parser.lolevel;
-
-import java.nio.*;
-import java.util.*;
-
-import primitive.collection.ByteList;
-
-import http_parser.*;
-
-public class Util {
-
-  static final ParserSettings SETTINGS_NULL = new ParserSettings();
-
-  static String str (ByteBuffer b, int pos, int len) {
-    byte [] by = new byte[len];
-    int saved = b.position();
-    b.position(pos);
-    b.get(by);
-    b.position(saved);
-    return new String(by);
-  }
-  static String str (ByteBuffer b) {
-    int len = b.limit() - b.position(); 
-    byte [] by = new byte[len];
-    int saved = b.position();
-    b.get(by);
-    b.position(saved);
-    return new String(by);
-  }
-
-  static ByteBuffer buffer(String str) {
-    return ByteBuffer.wrap(str.getBytes());
-  }
-
-  static ByteBuffer empty() {
-    return ByteBuffer.wrap(new byte[0]);
-  }
-
-  static void check(boolean betterBtrue) {
-    if (!betterBtrue) {
-      throw new RuntimeException("!");
-    }
-  }
-
-  static void test_message(Message mes) {
-    int raw_len = mes.raw.length;
-    for (int msg1len = 0; msg1len != raw_len; ++msg1len) {
-      mes.reset();
-      ByteBuffer msg1 = ByteBuffer.wrap(mes.raw, 0, msg1len);
-      ByteBuffer msg2 = ByteBuffer.wrap(mes.raw, msg1len, mes.raw.length - msg1len);
-
-      HTTPParser parser = new HTTPParser(mes.type);
-      ParserSettings settings = mes.settings();
-      
-      int read = 0;
-      if (msg1len !=0) {
-        read = parser.execute(settings, msg1);
-        if (mes.upgrade && parser.upgrade) {
-          // Messages have a settings() that checks itself...
-          check(1 == mes.num_called);
-          continue; 
-        }
-        check(read == msg1len);
-      }
-
-      read = parser.execute(settings, msg2);
-      if (mes.upgrade && parser.upgrade) {
-        check(1 == mes.num_called);
-        continue; 
-      }
-
-      check(read == mes.raw.length - msg1len);
-      
-      ByteBuffer empty = Util.empty();
-      read = parser.execute(settings, empty);
-      
-      if (mes.upgrade && parser.upgrade) {
-        check(1 == mes.num_called);
-        continue;
-      }
-      check(empty.position() == empty.limit());
-      check(0 == read);
-      check(1 == mes.num_called);
-
-    }
-  }
-
-  static void test_multiple3(Message r1, Message r2, Message r3) {
-    int message_count = 1;
-    if (!r1.upgrade) {
-      message_count++;
-      if (!r2.upgrade) {
-        message_count++;
-      }
-    }
-    boolean has_upgrade = (message_count < 3 || r3.upgrade);
-
-    ByteList blist = new ByteList();
-    blist.addAll(r1.raw);
-    blist.addAll(r2.raw);
-    blist.addAll(r3.raw);
-
-    byte [] raw = blist.toArray();
-    ByteBuffer buf   = ByteBuffer.wrap(raw);
-
-    Util.Settings settings = Util.settings(); 
-    HTTPParser parser = new HTTPParser(r1.type);
-    
-    int read = parser.execute(settings, buf);
-    if (has_upgrade && parser.upgrade) {
-      check(settings.numCalled == message_count); 
-      return;
-    }
-
-    check(read == raw.length);
-
-    buf = Util.empty();    
-    read = parser.execute(settings, buf);
-    if (has_upgrade && parser.upgrade) {
-      check(settings.numCalled == message_count); 
-      return;
-    }
-
-    check(0 == read);
-    check(settings.numCalled == message_count); 
-  }  
-  static void p (Object o) {
-    System.out.println(o);
-  }
-
-  static Settings settings() {
-    return new Settings();
-  }
-  static Message find(List<Message> list, String name) {
-    for (Message m : list) {
-      if (name.equals(m.name)) {
-        return m;
-      }
-    }
-    return null;
-  }
-
-  static class Settings extends ParserSettings {
-    public int numCalled;
-    public int bodyCount;
-    Settings() {
-      this.on_message_complete = new HTTPCallback() {
-        public int cb (HTTPParser parser) {
-          numCalled++;
-          return 0;
-        }
-      };
-      this.on_body = new HTTPDataCallback() {
-        public int cb (HTTPParser p, ByteBuffer b, int pos, int len) {
-          bodyCount += len;
-          return 0;
-        }
-      }; 
-    }
-    
-    int numCalled () {
-      return this.numCalled;
-    }
-  }
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/WrongContentLength.java b/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/WrongContentLength.java
deleted file mode 100644
index b89098c..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/WrongContentLength.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package http_parser.lolevel;
-
-import java.nio.*;
-import java.util.*;
-
-import http_parser.ParserType;
-
-import static http_parser.lolevel.Util.*;
-
-public class WrongContentLength {
-  static final String contentLength = "GET / HTTP/1.0\r\n" +
-                                      "Content-Length: 5\r\n" +
-                                      "\r\n" +
-                                      "hello" +
-                                      "hello_again";
-  static void test () {
-    HTTPParser parser = new HTTPParser(ParserType.HTTP_REQUEST);
-    ByteBuffer buf    = buffer(contentLength);
-    
-    Settings settings = new Settings();
-
-    int read = parser.execute(settings, buf);
-    check (settings.msg_cmplt_called);
-    check ("invalid method".equals(settings.err));
-  
-  }
-  public static void main(String [] args) {
-    test();
-  }
-
-  static class Settings extends ParserSettings {
-    public int bodyCount;
-    public boolean msg_cmplt_called;
-    public String err;
-    Settings () {
-      this.on_message_complete = new HTTPCallback () {
-        public int cb (HTTPParser p) {
-          check (5 == bodyCount);
-          msg_cmplt_called = true;
-          return 0;
-        }
-      };
-      this.on_body = new HTTPDataCallback() {
-        public int cb (HTTPParser p, ByteBuffer b, int pos, int len) {
-          bodyCount += len;
-          p(str(b, pos, len));
-          return 0;
-        }
-      }; 
-      this.on_error = new HTTPErrorCallback() {
-        public void cb (HTTPParser p, String mes, ByteBuffer b, int i) {
-          err = mes;
-        }
-      };
-    }
-  }
-
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/test.c b/ext/ruby_http_parser/vendor/http-parser-java/test.c
deleted file mode 100644
index e5bebd0..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/test.c
+++ /dev/null
@@ -1,2068 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include "http_parser.h"
-#include <stdlib.h>
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h> /* rand */
-#include <string.h>
-#include <stdarg.h>
-
-#undef TRUE
-#define TRUE 1
-#undef FALSE
-#define FALSE 0
-
-#define MAX_HEADERS 13
-#define MAX_ELEMENT_SIZE 500
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
-static http_parser *parser;
-
-struct message {
-  const char *name; // for debugging purposes
-  const char *raw;
-  enum http_parser_type type;
-  enum http_method method;
-  int status_code;
-  char request_path[MAX_ELEMENT_SIZE];
-  char request_url[MAX_ELEMENT_SIZE];
-  char fragment[MAX_ELEMENT_SIZE];
-  char query_string[MAX_ELEMENT_SIZE];
-  char body[MAX_ELEMENT_SIZE];
-  size_t body_size;
-  int num_headers;
-  enum { NONE=0, FIELD, VALUE } last_header_element;
-  char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE];
-  int should_keep_alive;
-
-  int upgrade;
-
-  unsigned short http_major;
-  unsigned short http_minor;
-
-  int message_begin_cb_called;
-  int headers_complete_cb_called;
-  int message_complete_cb_called;
-  int message_complete_on_eof;
-};
-
-static int currently_parsing_eof;
-
-static struct message messages[5];
-static int num_messages;
-
-/* * R E Q U E S T S * */
-const struct message requests[] =
-#define CURL_GET 0
-{ {.name= "curl get"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /test HTTP/1.1\r\n"
-         "User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n"
-         "Host: 0.0.0.0=5000\r\n"
-         "Accept: */*\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/test"
-  ,.request_url= "/test"
-  ,.num_headers= 3
-  ,.headers=
-    { { "User-Agent", "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1" }
-    , { "Host", "0.0.0.0=5000" }
-    , { "Accept", "*/*" }
-    }
-  ,.body= ""
-  }
-
-#define FIREFOX_GET 1
-, {.name= "firefox get"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /favicon.ico HTTP/1.1\r\n"
-         "Host: 0.0.0.0=5000\r\n"
-         "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n"
-         "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
-         "Accept-Language: en-us,en;q=0.5\r\n"
-         "Accept-Encoding: gzip,deflate\r\n"
-         "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
-         "Keep-Alive: 300\r\n"
-         "Connection: keep-alive\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/favicon.ico"
-  ,.request_url= "/favicon.ico"
-  ,.num_headers= 8
-  ,.headers=
-    { { "Host", "0.0.0.0=5000" }
-    , { "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0" }
-    , { "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" }
-    , { "Accept-Language", "en-us,en;q=0.5" }
-    , { "Accept-Encoding", "gzip,deflate" }
-    , { "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7" }
-    , { "Keep-Alive", "300" }
-    , { "Connection", "keep-alive" }
-    }
-  ,.body= ""
-  }
-
-#define DUMBFUCK 2
-, {.name= "dumbfuck"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /dumbfuck HTTP/1.1\r\n"
-         "aaaaaaaaaaaaa:++++++++++\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/dumbfuck"
-  ,.request_url= "/dumbfuck"
-  ,.num_headers= 1
-  ,.headers=
-    { { "aaaaaaaaaaaaa",  "++++++++++" }
-    }
-  ,.body= ""
-  }
-
-#define FRAGMENT_IN_URI 3
-, {.name= "fragment in url"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= "page=1"
-  ,.fragment= "posts-17408"
-  ,.request_path= "/forums/1/topics/2375"
-  /* XXX request url does include fragment? */
-  ,.request_url= "/forums/1/topics/2375?page=1#posts-17408"
-  ,.num_headers= 0
-  ,.body= ""
-  }
-
-#define GET_NO_HEADERS_NO_BODY 4
-, {.name= "get no headers no body"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /get_no_headers_no_body/world HTTP/1.1\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE /* would need Connection: close */
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/get_no_headers_no_body/world"
-  ,.request_url= "/get_no_headers_no_body/world"
-  ,.num_headers= 0
-  ,.body= ""
-  }
-
-#define GET_ONE_HEADER_NO_BODY 5
-, {.name= "get one header no body"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /get_one_header_no_body HTTP/1.1\r\n"
-         "Accept: */*\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE /* would need Connection: close */
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/get_one_header_no_body"
-  ,.request_url= "/get_one_header_no_body"
-  ,.num_headers= 1
-  ,.headers=
-    { { "Accept" , "*/*" }
-    }
-  ,.body= ""
-  }
-
-#define GET_FUNKY_CONTENT_LENGTH 6
-, {.name= "get funky content length body hello"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /get_funky_content_length_body_hello HTTP/1.0\r\n"
-         "conTENT-Length: 5\r\n"
-         "\r\n"
-         "HELLO"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 0
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/get_funky_content_length_body_hello"
-  ,.request_url= "/get_funky_content_length_body_hello"
-  ,.num_headers= 1
-  ,.headers=
-    { { "conTENT-Length" , "5" }
-    }
-  ,.body= "HELLO"
-  }
-
-#define POST_IDENTITY_BODY_WORLD 7
-, {.name= "post identity body world"
-  ,.type= HTTP_REQUEST
-  ,.raw= "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n"
-         "Accept: */*\r\n"
-         "Transfer-Encoding: identity\r\n"
-         "Content-Length: 5\r\n"
-         "\r\n"
-         "World"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_POST
-  ,.query_string= "q=search"
-  ,.fragment= "hey"
-  ,.request_path= "/post_identity_body_world"
-  ,.request_url= "/post_identity_body_world?q=search#hey"
-  ,.num_headers= 3
-  ,.headers=
-    { { "Accept", "*/*" }
-    , { "Transfer-Encoding", "identity" }
-    , { "Content-Length", "5" }
-    }
-  ,.body= "World"
-  }
-
-#define POST_CHUNKED_ALL_YOUR_BASE 8
-, {.name= "post - chunked body: all your base are belong to us"
-  ,.type= HTTP_REQUEST
-  ,.raw= "POST /post_chunked_all_your_base HTTP/1.1\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "1e\r\nall your base are belong to us\r\n"
-         "0\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_POST
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/post_chunked_all_your_base"
-  ,.request_url= "/post_chunked_all_your_base"
-  ,.num_headers= 1
-  ,.headers=
-    { { "Transfer-Encoding" , "chunked" }
-    }
-  ,.body= "all your base are belong to us"
-  }
-
-#define TWO_CHUNKS_MULT_ZERO_END 9
-, {.name= "two chunks ; triple zero ending"
-  ,.type= HTTP_REQUEST
-  ,.raw= "POST /two_chunks_mult_zero_end HTTP/1.1\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "5\r\nhello\r\n"
-         "6\r\n world\r\n"
-         "000\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_POST
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/two_chunks_mult_zero_end"
-  ,.request_url= "/two_chunks_mult_zero_end"
-  ,.num_headers= 1
-  ,.headers=
-    { { "Transfer-Encoding", "chunked" }
-    }
-  ,.body= "hello world"
-  }
-
-#define CHUNKED_W_TRAILING_HEADERS 10
-, {.name= "chunked with trailing headers. blech."
-  ,.type= HTTP_REQUEST
-  ,.raw= "POST /chunked_w_trailing_headers HTTP/1.1\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "5\r\nhello\r\n"
-         "6\r\n world\r\n"
-         "0\r\n"
-         "Vary: *\r\n"
-         "Content-Type: text/plain\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_POST
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/chunked_w_trailing_headers"
-  ,.request_url= "/chunked_w_trailing_headers"
-  ,.num_headers= 3
-  ,.headers=
-    { { "Transfer-Encoding",  "chunked" }
-    , { "Vary", "*" }
-    , { "Content-Type", "text/plain" }
-    }
-  ,.body= "hello world"
-  }
-
-#define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11
-, {.name= "with bullshit after the length"
-  ,.type= HTTP_REQUEST
-  ,.raw= "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "5; ihatew3;whatthefuck=aretheseparametersfor\r\nhello\r\n"
-         "6; blahblah; blah\r\n world\r\n"
-         "0\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_POST
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/chunked_w_bullshit_after_length"
-  ,.request_url= "/chunked_w_bullshit_after_length"
-  ,.num_headers= 1
-  ,.headers=
-    { { "Transfer-Encoding", "chunked" }
-    }
-  ,.body= "hello world"
-  }
-
-#define WITH_QUOTES 12
-, {.name= "with quotes"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /with_\"stupid\"_quotes?foo=\"bar\" HTTP/1.1\r\n\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= "foo=\"bar\""
-  ,.fragment= ""
-  ,.request_path= "/with_\"stupid\"_quotes"
-  ,.request_url= "/with_\"stupid\"_quotes?foo=\"bar\""
-  ,.num_headers= 0
-  ,.headers= { }
-  ,.body= ""
-  }
-
-#define APACHEBENCH_GET 13
-/* The server receiving this request SHOULD NOT wait for EOF
- * to know that content-length == 0.
- * How to represent this in a unit test? message_complete_on_eof
- * Compare with NO_CONTENT_LENGTH_RESPONSE.
- */
-, {.name = "apachebench get"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /test HTTP/1.0\r\n"
-         "Host: 0.0.0.0:5000\r\n"
-         "User-Agent: ApacheBench/2.3\r\n"
-         "Accept: */*\r\n\r\n"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 0
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/test"
-  ,.request_url= "/test"
-  ,.num_headers= 3
-  ,.headers= { { "Host", "0.0.0.0:5000" }
-             , { "User-Agent", "ApacheBench/2.3" }
-             , { "Accept", "*/*" }
-             }
-  ,.body= ""
-  }
-
-#define QUERY_URL_WITH_QUESTION_MARK_GET 14
-/* Some clients include '?' characters in query strings.
- */
-, {.name = "query url with question mark"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /test.cgi?foo=bar?baz HTTP/1.1\r\n\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= "foo=bar?baz"
-  ,.fragment= ""
-  ,.request_path= "/test.cgi"
-  ,.request_url= "/test.cgi?foo=bar?baz"
-  ,.num_headers= 0
-  ,.headers= {}
-  ,.body= ""
-  }
-
-#define PREFIX_NEWLINE_GET 15
-/* Some clients, especially after a POST in a keep-alive connection,
- * will send an extra CRLF before the next request
- */
-, {.name = "newline prefix get"
-  ,.type= HTTP_REQUEST
-  ,.raw= "\r\nGET /test HTTP/1.1\r\n\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/test"
-  ,.request_url= "/test"
-  ,.num_headers= 0
-  ,.headers= { }
-  ,.body= ""
-  }
-
-#define UPGRADE_REQUEST 16
-, {.name = "upgrade request"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /demo HTTP/1.1\r\n"
-         "Host: example.com\r\n"
-         "Connection: Upgrade\r\n"
-         "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
-         "Sec-WebSocket-Protocol: sample\r\n"
-         "Upgrade: WebSocket\r\n"
-         "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
-         "Origin: http://example.com\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/demo"
-  ,.request_url= "/demo"
-  ,.num_headers= 7
-  ,.upgrade=1
-  ,.headers= { { "Host", "example.com" }
-             , { "Connection", "Upgrade" }
-             , { "Sec-WebSocket-Key2", "12998 5 Y3 1  .P00" }
-             , { "Sec-WebSocket-Protocol", "sample" }
-             , { "Upgrade", "WebSocket" }
-             , { "Sec-WebSocket-Key1", "4 @1  46546xW%0l 1 5" }
-             , { "Origin", "http://example.com" }
-             }
-  ,.body= ""
-  }
-
-#define CONNECT_REQUEST 17
-, {.name = "connect request"
-  ,.type= HTTP_REQUEST
-  ,.raw= "CONNECT home0.netscape.com:443 HTTP/1.0\r\n"
-         "User-agent: Mozilla/1.1N\r\n"
-         "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"
-         "\r\n"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 0
-  ,.method= HTTP_CONNECT
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= ""
-  ,.request_url= "home0.netscape.com:443"
-  ,.num_headers= 2
-  ,.upgrade=1
-  ,.headers= { { "User-agent", "Mozilla/1.1N" }
-             , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }
-             }
-  ,.body= ""
-  }
-
-#define REPORT_REQ 18
-, {.name= "report request"
-  ,.type= HTTP_REQUEST
-  ,.raw= "REPORT /test HTTP/1.1\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_REPORT
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/test"
-  ,.request_url= "/test"
-  ,.num_headers= 0
-  ,.headers= {}
-  ,.body= ""
-  }
-
-#define NO_HTTP_VERSION 19
-, {.name= "request with no http version"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /\r\n"
-         "\r\n"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 0
-  ,.http_minor= 9
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/"
-  ,.request_url= "/"
-  ,.num_headers= 0
-  ,.headers= {}
-  ,.body= ""
-  }
-
-#define MSEARCH_REQ 20
-, {.name= "m-search request"
-  ,.type= HTTP_REQUEST
-  ,.raw= "M-SEARCH * HTTP/1.1\r\n"
-         "HOST: 239.255.255.250:1900\r\n"
-         "MAN: \"ssdp:discover\"\r\n"
-         "ST: \"ssdp:all\"\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_MSEARCH
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "*"
-  ,.request_url= "*"
-  ,.num_headers= 3
-  ,.headers= { { "HOST", "239.255.255.250:1900" }
-             , { "MAN", "\"ssdp:discover\"" }
-             , { "ST", "\"ssdp:all\"" }
-             }
-  ,.body= ""
-  }
-
-#define UTF8_PATH_REQ 21
-, {.name= "utf-8 path request"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n"
-         "Host: github.com\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= "q=1"
-  ,.fragment= "narf"
-  ,.request_path= "/δ¶/δt/pope"
-  ,.request_url= "/δ¶/δt/pope?q=1#narf"
-  ,.num_headers= 1
-  ,.headers= { {"Host", "github.com" }
-             }
-  ,.body= ""
-  }
-
-#define QUERY_TERMINATED_HOST 22
-, {.name= "host terminated by a query string"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= "hail=all"
-  ,.fragment= ""
-  ,.request_path= ""
-  ,.request_url= "http://hypnotoad.org?hail=all"
-  ,.num_headers= 0
-  ,.headers= { }
-  ,.body= ""
-  }
-
-#define QUERY_TERMINATED_HOSTPORT 23
-, {.name= "host:port terminated by a query string"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= "hail=all"
-  ,.fragment= ""
-  ,.request_path= ""
-  ,.request_url= "http://hypnotoad.org:1234?hail=all"
-  ,.num_headers= 0
-  ,.headers= { }
-  ,.body= ""
-  }
-
-#define SPACE_TERMINATED_HOSTPORT 24
-, {.name= "host:port terminated by a space"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET http://hypnotoad.org:1234 HTTP/1.1\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= ""
-  ,.request_url= "http://hypnotoad.org:1234"
-  ,.num_headers= 0
-  ,.headers= { }
-  ,.body= ""
-  }
-
-, {.name= NULL } /* sentinel */
-};
-
-/* * R E S P O N S E S * */
-const struct message responses[] =
-#define GOOGLE_301 0
-{ {.name= "google 301"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 301 Moved Permanently\r\n"
-         "Location: http://www.google.com/\r\n"
-         "Content-Type: text/html; charset=UTF-8\r\n"
-         "Date: Sun, 26 Apr 2009 11:11:49 GMT\r\n"
-         "Expires: Tue, 26 May 2009 11:11:49 GMT\r\n"
-         "X-$PrototypeBI-Version: 1.6.0.3\r\n" /* $ char in header field */
-         "Cache-Control: public, max-age=2592000\r\n"
-         "Server: gws\r\n"
-         "Content-Length:  219  \r\n"
-         "\r\n"
-         "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n"
-         "<TITLE>301 Moved</TITLE></HEAD><BODY>\n"
-         "<H1>301 Moved</H1>\n"
-         "The document has moved\n"
-         "<A HREF=\"http://www.google.com/\">here</A>.\r\n"
-         "</BODY></HTML>\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 301
-  ,.num_headers= 8
-  ,.headers=
-    { { "Location", "http://www.google.com/" }
-    , { "Content-Type", "text/html; charset=UTF-8" }
-    , { "Date", "Sun, 26 Apr 2009 11:11:49 GMT" }
-    , { "Expires", "Tue, 26 May 2009 11:11:49 GMT" }
-    , { "X-$PrototypeBI-Version", "1.6.0.3" }
-    , { "Cache-Control", "public, max-age=2592000" }
-    , { "Server", "gws" }
-    , { "Content-Length", "219  " }
-    }
-  ,.body= "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n"
-          "<TITLE>301 Moved</TITLE></HEAD><BODY>\n"
-          "<H1>301 Moved</H1>\n"
-          "The document has moved\n"
-          "<A HREF=\"http://www.google.com/\">here</A>.\r\n"
-          "</BODY></HTML>\r\n"
-  }
-
-#define NO_CONTENT_LENGTH_RESPONSE 1
-/* The client should wait for the server's EOF. That is, when content-length
- * is not specified, and "Connection: close", the end of body is specified
- * by the EOF.
- * Compare with APACHEBENCH_GET
- */
-, {.name= "no content-length response"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\r\n"
-         "Date: Tue, 04 Aug 2009 07:59:32 GMT\r\n"
-         "Server: Apache\r\n"
-         "X-Powered-By: Servlet/2.5 JSP/2.1\r\n"
-         "Content-Type: text/xml; charset=utf-8\r\n"
-         "Connection: close\r\n"
-         "\r\n"
-         "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-         "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
-         "  <SOAP-ENV:Body>\n"
-         "    <SOAP-ENV:Fault>\n"
-         "       <faultcode>SOAP-ENV:Client</faultcode>\n"
-         "       <faultstring>Client Error</faultstring>\n"
-         "    </SOAP-ENV:Fault>\n"
-         "  </SOAP-ENV:Body>\n"
-         "</SOAP-ENV:Envelope>"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= TRUE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 5
-  ,.headers=
-    { { "Date", "Tue, 04 Aug 2009 07:59:32 GMT" }
-    , { "Server", "Apache" }
-    , { "X-Powered-By", "Servlet/2.5 JSP/2.1" }
-    , { "Content-Type", "text/xml; charset=utf-8" }
-    , { "Connection", "close" }
-    }
-  ,.body= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-          "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
-          "  <SOAP-ENV:Body>\n"
-          "    <SOAP-ENV:Fault>\n"
-          "       <faultcode>SOAP-ENV:Client</faultcode>\n"
-          "       <faultstring>Client Error</faultstring>\n"
-          "    </SOAP-ENV:Fault>\n"
-          "  </SOAP-ENV:Body>\n"
-          "</SOAP-ENV:Envelope>"
-  }
-
-#define NO_HEADERS_NO_BODY_404 2
-, {.name= "404 no headers no body"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 404 Not Found\r\n\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 404
-  ,.num_headers= 0
-  ,.headers= {}
-  ,.body_size= 0
-  ,.body= ""
-  }
-
-#define NO_REASON_PHRASE 3
-, {.name= "301 no response phrase"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 301\r\n\r\n"
-  ,.should_keep_alive = TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 301
-  ,.num_headers= 0
-  ,.headers= {}
-  ,.body= ""
-  }
-
-#define TRAILING_SPACE_ON_CHUNKED_BODY 4
-, {.name="200 trailing space on chunked body"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\r\n"
-         "Content-Type: text/plain\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "25  \r\n"
-         "This is the data in the first chunk\r\n"
-         "\r\n"
-         "1C\r\n"
-         "and this is the second one\r\n"
-         "\r\n"
-         "0  \r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 2
-  ,.headers=
-    { {"Content-Type", "text/plain" }
-    , {"Transfer-Encoding", "chunked" }
-    }
-  ,.body_size = 37+28
-  ,.body =
-         "This is the data in the first chunk\r\n"
-         "and this is the second one\r\n"
-
-  }
-
-#define NO_CARRIAGE_RET 5
-, {.name="no carriage ret"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\n"
-         "Content-Type: text/html; charset=utf-8\n"
-         "Connection: close\n"
-         "\n"
-         "these headers are from http://news.ycombinator.com/"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= TRUE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 2
-  ,.headers=
-    { {"Content-Type", "text/html; charset=utf-8" }
-    , {"Connection", "close" }
-    }
-  ,.body= "these headers are from http://news.ycombinator.com/"
-  }
-
-#define PROXY_CONNECTION 6
-, {.name="proxy connection"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\r\n"
-         "Content-Type: text/html; charset=UTF-8\r\n"
-         "Content-Length: 11\r\n"
-         "Proxy-Connection: close\r\n"
-         "Date: Thu, 31 Dec 2009 20:55:48 +0000\r\n"
-         "\r\n"
-         "hello world"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 4
-  ,.headers=
-    { {"Content-Type", "text/html; charset=UTF-8" }
-    , {"Content-Length", "11" }
-    , {"Proxy-Connection", "close" }
-    , {"Date", "Thu, 31 Dec 2009 20:55:48 +0000"}
-    }
-  ,.body= "hello world"
-  }
-
-#define UNDERSTORE_HEADER_KEY 7
-  // shown by
-  // curl -o /dev/null -v "http://ad.doubleclick.net/pfadx/DARTSHELLCONFIGXML;dcmt=text/xml;"
-, {.name="underscore header key"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\r\n"
-         "Server: DCLK-AdSvr\r\n"
-         "Content-Type: text/xml\r\n"
-         "Content-Length: 0\r\n"
-         "DCLK_imp: v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o\r\n\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 4
-  ,.headers=
-    { {"Server", "DCLK-AdSvr" }
-    , {"Content-Type", "text/xml" }
-    , {"Content-Length", "0" }
-    , {"DCLK_imp", "v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o" }
-    }
-  ,.body= ""
-  }
-
-#define BONJOUR_MADAME_FR 8
-/* The client should not merge two headers fields when the first one doesn't
- * have a value.
- */
-, {.name= "bonjourmadame.fr"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.0 301 Moved Permanently\r\n"
-         "Date: Thu, 03 Jun 2010 09:56:32 GMT\r\n"
-         "Server: Apache/2.2.3 (Red Hat)\r\n"
-         "Cache-Control: public\r\n"
-         "Pragma: \r\n"
-         "Location: http://www.bonjourmadame.fr/\r\n"
-         "Vary: Accept-Encoding\r\n"
-         "Content-Length: 0\r\n"
-         "Content-Type: text/html; charset=UTF-8\r\n"
-         "Connection: keep-alive\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 0
-  ,.status_code= 301
-  ,.num_headers= 9
-  ,.headers=
-    { { "Date", "Thu, 03 Jun 2010 09:56:32 GMT" }
-    , { "Server", "Apache/2.2.3 (Red Hat)" }
-    , { "Cache-Control", "public" }
-    , { "Pragma", "" }
-    , { "Location", "http://www.bonjourmadame.fr/" }
-    , { "Vary",  "Accept-Encoding" }
-    , { "Content-Length", "0" }
-    , { "Content-Type", "text/html; charset=UTF-8" }
-    , { "Connection", "keep-alive" }
-    }
-  ,.body= ""
-  }
-
-#define SPACE_IN_FIELD_RES 9
-/* Should handle spaces in header fields */
-, {.name= "field space"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\r\n"
-         "Server: Microsoft-IIS/6.0\r\n"
-         "X-Powered-By: ASP.NET\r\n"
-         "en-US Content-Type: text/xml\r\n" /* this is the problem */
-         "Content-Type: text/xml\r\n"
-         "Content-Length: 16\r\n"
-         "Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n"
-         "Connection: keep-alive\r\n"
-         "\r\n"
-         "<xml>hello</xml>" /* fake body */
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 7
-  ,.headers=
-    { { "Server",  "Microsoft-IIS/6.0" }
-    , { "X-Powered-By", "ASP.NET" }
-    , { "en-US Content-Type", "text/xml" }
-    , { "Content-Type", "text/xml" }
-    , { "Content-Length", "16" }
-    , { "Date", "Fri, 23 Jul 2010 18:45:38 GMT" }
-    , { "Connection", "keep-alive" }
-    }
-  ,.body= "<xml>hello</xml>"
-  }
-
-
-#define RES_FIELD_UNDERSCORE 10
-/* Should handle spaces in header fields */
-, {.name= "field underscore"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\r\n"
-         "Date: Tue, 28 Sep 2010 01:14:13 GMT\r\n"
-         "Server: Apache\r\n"
-         "Cache-Control: no-cache, must-revalidate\r\n"
-         "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"
-         ".et-Cookie: PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com\r\n"
-         "Vary: Accept-Encoding\r\n"
-         "_eep-Alive: timeout=45\r\n" /* semantic value ignored */
-         "_onnection: Keep-Alive\r\n" /* semantic value ignored */
-         "Transfer-Encoding: chunked\r\n"
-         "Content-Type: text/html\r\n"
-         "Connection: close\r\n"
-         "\r\n"
-         "0\r\n\r\n"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 11
-  ,.headers=
-    { { "Date", "Tue, 28 Sep 2010 01:14:13 GMT" }
-    , { "Server", "Apache" }
-    , { "Cache-Control", "no-cache, must-revalidate" }
-    , { "Expires", "Mon, 26 Jul 1997 05:00:00 GMT" }
-    , { ".et-Cookie", "PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com" }
-    , { "Vary", "Accept-Encoding" }
-    , { "_eep-Alive", "timeout=45" }
-    , { "_onnection", "Keep-Alive" }
-    , { "Transfer-Encoding", "chunked" }
-    , { "Content-Type", "text/html" }
-    , { "Connection", "close" }
-    }
-  ,.body= ""
-  }
-
-#define NON_ASCII_IN_STATUS_LINE 11
-/* Should handle non-ASCII in status line */
-, {.name= "non-ASCII in status line"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 500 Oriëntatieprobleem\r\n"
-         "Date: Fri, 5 Nov 2010 23:07:12 GMT+2\r\n"
-         "Content-Length: 0\r\n"
-         "Connection: close\r\n"
-         "\r\n"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 500
-  ,.num_headers= 3
-  ,.headers=
-    { { "Date", "Fri, 5 Nov 2010 23:07:12 GMT+2" }
-    , { "Content-Length", "0" }
-    , { "Connection", "close" }
-    }
-  ,.body= ""
-  }
-
-
-, {.name= NULL } /* sentinel */
-};
-
-int
-request_path_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  strncat(messages[num_messages].request_path, buf, len);
-  return 0;
-}
-
-int
-request_url_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  strncat(messages[num_messages].request_url, buf, len);
-  return 0;
-}
-
-int
-query_string_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  strncat(messages[num_messages].query_string, buf, len);
-  return 0;
-}
-
-int
-fragment_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  strncat(messages[num_messages].fragment, buf, len);
-  return 0;
-}
-
-int
-header_field_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  struct message *m = &messages[num_messages];
-
-  if (m->last_header_element != FIELD)
-    m->num_headers++;
-
-  strncat(m->headers[m->num_headers-1][0], buf, len);
-
-  m->last_header_element = FIELD;
-
-  return 0;
-}
-
-int
-header_value_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  struct message *m = &messages[num_messages];
-
-  strncat(m->headers[m->num_headers-1][1], buf, len);
-
-  m->last_header_element = VALUE;
-
-  return 0;
-}
-
-int
-body_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  strncat(messages[num_messages].body, buf, len);
-  messages[num_messages].body_size += len;
- // printf("body_cb: '%s'\n", requests[num_messages].body);
-  return 0;
-}
-
-int
-count_body_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  assert(buf);
-  messages[num_messages].body_size += len;
-  return 0;
-}
-
-int
-message_begin_cb (http_parser *p)
-{
-  assert(p == parser);
-  messages[num_messages].message_begin_cb_called = TRUE;
-  return 0;
-}
-
-int
-headers_complete_cb (http_parser *p)
-{
-  assert(p == parser);
-  messages[num_messages].method = parser->method;
-  messages[num_messages].status_code = parser->status_code;
-  messages[num_messages].http_major = parser->http_major;
-  messages[num_messages].http_minor = parser->http_minor;
-  messages[num_messages].headers_complete_cb_called = TRUE;
-  messages[num_messages].should_keep_alive = http_should_keep_alive(parser);
-  return 0;
-}
-
-int
-message_complete_cb (http_parser *p)
-{
-  assert(p == parser);
-  if (messages[num_messages].should_keep_alive != http_should_keep_alive(parser))
-  {
-    fprintf(stderr, "\n\n *** Error http_should_keep_alive() should have same "
-                    "value in both on_message_complete and on_headers_complete "
-                    "but it doesn't! ***\n\n");
-    assert(0);
-    exit(1);
-  }
-  messages[num_messages].message_complete_cb_called = TRUE;
-
-  messages[num_messages].message_complete_on_eof = currently_parsing_eof;
-
-  num_messages++;
-  return 0;
-}
-
-static http_parser_settings settings =
-  {.on_message_begin = message_begin_cb
-  ,.on_header_field = header_field_cb
-  ,.on_header_value = header_value_cb
-  ,.on_path = request_path_cb
-  ,.on_url = request_url_cb
-  ,.on_fragment = fragment_cb
-  ,.on_query_string = query_string_cb
-  ,.on_body = body_cb
-  ,.on_headers_complete = headers_complete_cb
-  ,.on_message_complete = message_complete_cb
-  };
-
-static http_parser_settings settings_count_body =
-  {.on_message_begin = message_begin_cb
-  ,.on_header_field = header_field_cb
-  ,.on_header_value = header_value_cb
-  ,.on_path = request_path_cb
-  ,.on_url = request_url_cb
-  ,.on_fragment = fragment_cb
-  ,.on_query_string = query_string_cb
-  ,.on_body = count_body_cb
-  ,.on_headers_complete = headers_complete_cb
-  ,.on_message_complete = message_complete_cb
-  };
-
-static http_parser_settings settings_null =
-  {.on_message_begin = 0
-  ,.on_header_field = 0
-  ,.on_header_value = 0
-  ,.on_path = 0
-  ,.on_url = 0
-  ,.on_fragment = 0
-  ,.on_query_string = 0
-  ,.on_body = 0
-  ,.on_headers_complete = 0
-  ,.on_message_complete = 0
-  };
-
-void
-parser_init (enum http_parser_type type)
-{
-  num_messages = 0;
-
-  assert(parser == NULL);
-
-  parser = malloc(sizeof(http_parser));
-
-  http_parser_init(parser, type);
-
-  memset(&messages, 0, sizeof messages);
-
-}
-
-void
-parser_free ()
-{
-  assert(parser);
-  free(parser);
-  parser = NULL;
-}
-
-size_t parse (const char *buf, size_t len)
-{
-  size_t nparsed;
-  currently_parsing_eof = (len == 0);
-  nparsed = http_parser_execute(parser, &settings, buf, len);
-  return nparsed;
-}
-
-size_t parse_count_body (const char *buf, size_t len)
-{
-  size_t nparsed;
-  currently_parsing_eof = (len == 0);
-  nparsed = http_parser_execute(parser, &settings_count_body, buf, len);
-  return nparsed;
-}
-
-static inline int
-check_str_eq (const struct message *m,
-              const char *prop,
-              const char *expected,
-              const char *found) {
-  if (0 != strcmp(expected, found)) {
-    printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name);
-    printf("expected '%s'\n", expected);
-    printf("   found '%s'\n", found);
-    return 0;
-  }
-  return 1;
-}
-
-static inline int
-check_num_eq (const struct message *m,
-              const char *prop,
-              int expected,
-              int found) {
-  if (expected != found) {
-    printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name);
-    printf("expected %d\n", expected);
-    printf("   found %d\n", found);
-    return 0;
-  }
-  return 1;
-}
-
-#define MESSAGE_CHECK_STR_EQ(expected, found, prop) \
-  if (!check_str_eq(expected, #prop, expected->prop, found->prop)) return 0
-
-#define MESSAGE_CHECK_NUM_EQ(expected, found, prop) \
-  if (!check_num_eq(expected, #prop, expected->prop, found->prop)) return 0
-
-
-int
-message_eq (int index, const struct message *expected)
-{
-  int i;
-  struct message *m = &messages[index];
-
-  MESSAGE_CHECK_NUM_EQ(expected, m, http_major);
-  MESSAGE_CHECK_NUM_EQ(expected, m, http_minor);
-
-  if (expected->type == HTTP_REQUEST) {
-    MESSAGE_CHECK_NUM_EQ(expected, m, method);
-  } else {
-    MESSAGE_CHECK_NUM_EQ(expected, m, status_code);
-  }
-
-  MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive);
-  MESSAGE_CHECK_NUM_EQ(expected, m, message_complete_on_eof);
-
-  assert(m->message_begin_cb_called);
-  assert(m->headers_complete_cb_called);
-  assert(m->message_complete_cb_called);
-
-
-  MESSAGE_CHECK_STR_EQ(expected, m, request_path);
-  MESSAGE_CHECK_STR_EQ(expected, m, query_string);
-  MESSAGE_CHECK_STR_EQ(expected, m, fragment);
-  MESSAGE_CHECK_STR_EQ(expected, m, request_url);
-  if (expected->body_size) {
-    MESSAGE_CHECK_NUM_EQ(expected, m, body_size);
-  } else {
-    MESSAGE_CHECK_STR_EQ(expected, m, body);
-  }
-
-  MESSAGE_CHECK_NUM_EQ(expected, m, num_headers);
-
-  int r;
-  for (i = 0; i < m->num_headers; i++) {
-    r = check_str_eq(expected, "header field", expected->headers[i][0], m->headers[i][0]);
-    if (!r) return 0;
-    r = check_str_eq(expected, "header value", expected->headers[i][1], m->headers[i][1]);
-    if (!r) return 0;
-  }
-
-  return 1;
-}
-
-static void
-print_error (const char *raw, size_t error_location)
-{
-  fprintf(stderr, "\n*** parse error ***\n\n");
-
-  int this_line = 0, char_len = 0;
-  size_t i, j, len = strlen(raw), error_location_line = 0;
-  for (i = 0; i < len; i++) {
-    if (i == error_location) this_line = 1;
-    switch (raw[i]) {
-      case '\r':
-        char_len = 2;
-        fprintf(stderr, "\\r");
-        break;
-
-      case '\n':
-        char_len = 2;
-        fprintf(stderr, "\\n\n");
-
-        if (this_line) goto print;
-
-        error_location_line = 0;
-        continue;
-
-      default:
-        char_len = 1;
-        fputc(raw[i], stderr);
-        break;
-    }
-    if (!this_line) error_location_line += char_len;
-  }
-
-  fprintf(stderr, "[eof]\n");
-
- print:
-  for (j = 0; j < error_location_line; j++) {
-    fputc(' ', stderr);
-  }
-  fprintf(stderr, "^\n\nerror location: %u\n", (unsigned int)error_location);
-}
-
-
-void
-test_message (const struct message *message)
-{
-  size_t raw_len = strlen(message->raw);
-  size_t msg1len;
-  for (msg1len = 0; msg1len < raw_len; msg1len++) {
-    parser_init(message->type);
-
-    size_t read;
-    const char *msg1 = message->raw;
-    const char *msg2 = msg1 + msg1len;
-    size_t msg2len = raw_len - msg1len;
-
-    if (msg1len) {
-      read = parse(msg1, msg1len);
-
-      if (message->upgrade && parser->upgrade) goto test;
-
-      if (read != msg1len) {
-        print_error(msg1, read);
-        exit(1);
-      }
-    }
-
-
-    read = parse(msg2, msg2len);
-
-    if (message->upgrade && parser->upgrade) goto test;
-
-    if (read != msg2len) {
-      print_error(msg2, read);
-      exit(1);
-    }
-
-    read = parse(NULL, 0);
-
-    if (message->upgrade && parser->upgrade) goto test;
-
-    if (read != 0) {
-      print_error(message->raw, read);
-      exit(1);
-    }
-
-  test:
-
-    if (num_messages != 1) {
-      printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name);
-      exit(1);
-    }
-
-    if(!message_eq(0, message)) exit(1);
-
-    parser_free();
-  }
-}
-
-void
-test_message_count_body (const struct message *message)
-{
-  parser_init(message->type);
-
-  size_t read;
-  size_t l = strlen(message->raw);
-  size_t i, toread;
-  size_t chunk = 4024;
-
-  for (i = 0; i < l; i+= chunk) {
-    toread = MIN(l-i, chunk);
-    read = parse_count_body(message->raw + i, toread);
-    if (read != toread) {
-      print_error(message->raw, read);
-      exit(1);
-    }
-  }
-
-
-  read = parse_count_body(NULL, 0);
-  if (read != 0) {
-    print_error(message->raw, read);
-    exit(1);
-  }
-
-  if (num_messages != 1) {
-    printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name);
-    exit(1);
-  }
-
-  if(!message_eq(0, message)) exit(1);
-
-  parser_free();
-}
-
-void
-test_simple (const char *buf, int should_pass)
-{
-  parser_init(HTTP_REQUEST);
-
-  size_t parsed;
-  int pass;
-  parsed = parse(buf, strlen(buf));
-  pass = (parsed == strlen(buf));
-  parsed = parse(NULL, 0);
-  pass &= (parsed == 0);
-
-  parser_free();
-
-  if (pass != should_pass) {
-    fprintf(stderr, "\n*** test_simple expected %s ***\n\n%s", should_pass ? "success" : "error", buf);
-    exit(1);
-  }
-}
-
-void
-test_header_overflow_error (int req)
-{
-  http_parser parser;
-  http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
-  size_t parsed;
-  const char *buf;
-  buf = req ? "GET / HTTP/1.1\r\n" : "HTTP/1.0 200 OK\r\n";
-  parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
-  assert(parsed == strlen(buf));
-
-  buf = "header-key: header-value\r\n";
-  int i;
-  for (i = 0; i < 10000; i++) {
-    if (http_parser_execute(&parser, &settings_null, buf, strlen(buf)) != strlen(buf)) {
-      //fprintf(stderr, "error found on iter %d\n", i);
-      return;
-    }
-  }
-
-  fprintf(stderr, "\n*** Error expected but none in header overflow test ***\n");
-  exit(1);
-}
-
-void
-test_no_overflow_long_body (int req, size_t length)
-{
-  http_parser parser;
-  http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
-  size_t parsed;
-  size_t i;
-  char buf1[3000];
-  size_t buf1len = sprintf(buf1, "%s\r\nConnection: Keep-Alive\r\nContent-Length: %zu\r\n\r\n",
-      req ? "POST / HTTP/1.0" : "HTTP/1.0 200 OK", length);
-  parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len);
-  if (parsed != buf1len)
-    goto err;
-
-  for (i = 0; i < length; i++) {
-    char foo = 'a';
-    parsed = http_parser_execute(&parser, &settings_null, &foo, 1);
-    if (parsed != 1)
-      goto err;
-  }
-
-  parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len);
-  if (parsed != buf1len) goto err;
-  return;
-
- err:
-  fprintf(stderr,
-          "\n*** error in test_no_overflow_long_body %s of length %zu ***\n",
-          req ? "REQUEST" : "RESPONSE",
-          length);
-  exit(1);
-}
-
-void
-test_multiple3 (const struct message *r1, const struct message *r2, const struct message *r3)
-{
-  int message_count = 1;
-  if (!r1->upgrade) {
-    message_count++;
-    if (!r2->upgrade) message_count++;
-  }
-  int has_upgrade = (message_count < 3 || r3->upgrade);
-
-  char total[ strlen(r1->raw)
-            + strlen(r2->raw)
-            + strlen(r3->raw)
-            + 1
-            ];
-  total[0] = '\0';
-
-  strcat(total, r1->raw);
-  strcat(total, r2->raw);
-  strcat(total, r3->raw);
-
-  parser_init(r1->type);
-
-  size_t read;
-
-  read = parse(total, strlen(total));
-
-  if (has_upgrade && parser->upgrade) goto test;
-
-  if (read != strlen(total)) {
-    print_error(total, read);
-    exit(1);
-  }
-
-  read = parse(NULL, 0);
-
-  if (has_upgrade && parser->upgrade) goto test;
-
-  if (read != 0) {
-    print_error(total, read);
-    exit(1);
-  }
-
-test:
-
-  if (message_count != num_messages) {
-    fprintf(stderr, "\n\n*** Parser didn't see 3 messages only %d *** \n", num_messages);
-    exit(1);
-  }
-
-  if (!message_eq(0, r1)) exit(1);
-  if (message_count > 1) {
-    if (!message_eq(1, r2)) exit(1);
-    if (message_count > 2) {
-      if (!message_eq(2, r3)) exit(1);
-    }
-  }
-
-  parser_free();
-}
-
-/* SCAN through every possible breaking to make sure the
- * parser can handle getting the content in any chunks that
- * might come from the socket
- */
-void
-test_scan (const struct message *r1, const struct message *r2, const struct message *r3)
-{
-  char total[80*1024] = "\0";
-  char buf1[80*1024] = "\0";
-  char buf2[80*1024] = "\0";
-  char buf3[80*1024] = "\0";
-
-  strcat(total, r1->raw);
-  strcat(total, r2->raw);
-  strcat(total, r3->raw);
-
-  size_t read;
-
-  int total_len = strlen(total);
-
-  int total_ops = 2 * (total_len - 1) * (total_len - 2) / 2;
-  int ops = 0 ;
-
-  size_t buf1_len, buf2_len, buf3_len;
-
-  int i,j,type_both;
-  for (type_both = 0; type_both < 2; type_both ++ ) {
-    for (j = 2; j < total_len; j ++ ) {
-      for (i = 1; i < j; i ++ ) {
-
-        if (ops % 1000 == 0)  {
-          printf("\b\b\b\b%3.0f%%", 100 * (float)ops /(float)total_ops);
-          fflush(stdout);
-        }
-        ops += 1;
-
-        parser_init(type_both ? HTTP_BOTH : r1->type);
-
-        buf1_len = i;
-        strncpy(buf1, total, buf1_len);
-        buf1[buf1_len] = 0;
-
-        buf2_len = j - i;
-        strncpy(buf2, total+i, buf2_len);
-        buf2[buf2_len] = 0;
-
-        buf3_len = total_len - j;
-        strncpy(buf3, total+j, buf3_len);
-        buf3[buf3_len] = 0;
-
-        read = parse(buf1, buf1_len);
-
-        if (r3->upgrade && parser->upgrade) goto test;
-
-        if (read != buf1_len) {
-          print_error(buf1, read);
-          goto error;
-        }
-
-        read = parse(buf2, buf2_len);
-
-        if (r3->upgrade && parser->upgrade) goto test;
-
-        if (read != buf2_len) {
-          print_error(buf2, read);
-          goto error;
-        }
-
-        read = parse(buf3, buf3_len);
-
-        if (r3->upgrade && parser->upgrade) goto test;
-
-        if (read != buf3_len) {
-          print_error(buf3, read);
-          goto error;
-        }
-
-        parse(NULL, 0);
-
-test:
-
-        if (3 != num_messages) {
-          fprintf(stderr, "\n\nParser didn't see 3 messages only %d\n", num_messages);
-          goto error;
-        }
-
-        if (!message_eq(0, r1)) {
-          fprintf(stderr, "\n\nError matching messages[0] in test_scan.\n");
-          goto error;
-        }
-
-        if (!message_eq(1, r2)) {
-          fprintf(stderr, "\n\nError matching messages[1] in test_scan.\n");
-          goto error;
-        }
-
-        if (!message_eq(2, r3)) {
-          fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n");
-          goto error;
-        }
-
-        parser_free();
-      }
-    }
-  }
-  puts("\b\b\b\b100%");
-  return;
-
- error:
-  fprintf(stderr, "i=%d  j=%d\n", i, j);
-  fprintf(stderr, "buf1 (%u) %s\n\n", (unsigned int)buf1_len, buf1);
-  fprintf(stderr, "buf2 (%u) %s\n\n", (unsigned int)buf2_len , buf2);
-  fprintf(stderr, "buf3 (%u) %s\n", (unsigned int)buf3_len, buf3);
-  exit(1);
-}
-
-// user required to free the result
-// string terminated by \0
-char *
-create_large_chunked_message (int body_size_in_kb, const char* headers)
-{
-  int i;
-  size_t wrote = 0;
-  size_t headers_len = strlen(headers);
-  size_t bufsize = headers_len + (5+1024+2)*body_size_in_kb + 6;
-  char * buf = malloc(bufsize);
-
-  memcpy(buf, headers, headers_len);
-  wrote += headers_len;
-
-  for (i = 0; i < body_size_in_kb; i++) {
-    // write 1kb chunk into the body.
-    memcpy(buf + wrote, "400\r\n", 5);
-    wrote += 5;
-    memset(buf + wrote, 'C', 1024);
-    wrote += 1024;
-    strcpy(buf + wrote, "\r\n");
-    wrote += 2;
-  }
-
-  memcpy(buf + wrote, "0\r\n\r\n", 6);
-  wrote += 6;
-  assert(wrote == bufsize);
-
-  return buf;
-}
-
-char * 
-quote(const char * orig) {
-	size_t j, i, len = strlen(orig);
-	char * quoted = malloc(len == 0 ? 1 : len*2); // hm..
-	bzero(quoted, len == 0 ? 1 : len*2);
-	for (i=0, j=0; i!=len; ++i) {
-		switch (orig[i]){
-			case '\n':
-				quoted[j++] = '\\';
-				quoted[j++] = 'n';
-				break;
-			case '\r':
-				quoted[j++] = '\\';
-				quoted[j++] = 'r';
-				break;
-			case '"':
-				quoted[j++] = '\\';
-				quoted[j++] = '"';
-				break;
-			default  :
-				quoted[j++] = orig[i];
-		}
-	}
-	return quoted;
-}
-
-void 
-dump_message(const struct message * m)
-{
-	int i;
-	printf("name  :%s\n", m->name);	
-	char * bla = quote(m->raw);
-	printf("raw   :\"%s\"\n", bla);
-	free(bla);
-	switch (m->type){
-		case HTTP_REQUEST:
-			printf("type  :HTTP_REQUEST\n");break;
-		case HTTP_RESPONSE:
-			printf("type  :HTTP_RESPONSE\n"); break;
-		case HTTP_BOTH:
-			printf("type  :HTTP_BOTH\n");
-	}
-	switch (m->method) {
-    case HTTP_DELETE:      printf("method: HTTP_DELETE\n");break;
-    case HTTP_GET:         printf("method: HTTP_GET\n");break;
-    case HTTP_HEAD:        printf("method: HTTP_HEAD\n");break;
-    case HTTP_POST:        printf("method: HTTP_POST\n");break;
-    case HTTP_PUT:         printf("method: HTTP_PUT\n");break;
-    case HTTP_CONNECT:     printf("method: HTTP_CONNECT\n");break;
-    case HTTP_OPTIONS:     printf("method: HTTP_OPTIONS\n");break;
-    case HTTP_TRACE:       printf("method: HTTP_TRACE\n");break;
-    case HTTP_COPY:        printf("method: HTTP_COPY\n");break;
-    case HTTP_LOCK:        printf("method: HTTP_LOCK\n");break;
-    case HTTP_MKCOL:       printf("method: HTTP_MKCOL\n");break;
-    case HTTP_MOVE:        printf("method: HTTP_MOVE\n");break;
-    case HTTP_PROPFIND:    printf("method: HTTP_PROPFIND\n");break;
-    case HTTP_PROPPATCH:   printf("method: HTTP_PROPPATCH\n");break;
-    case HTTP_UNLOCK:      printf("method: HTTP_UNLOCK\n");break;
-    /* subversion */
-    case HTTP_REPORT:      printf("method: HTTP_REPORT\n"); break;
-    case HTTP_MKACTIVITY:  printf("method: HTTP_MKACTIVITY\n"); break;
-    case HTTP_CHECKOUT:    printf("method: HTTP_CHECKOUT\n"); break;
-    case HTTP_MERGE:       printf("method: HTTP_MERGE\n"); break;
-
-    case HTTP_MSEARCH:     printf("method: HTTP_MSEARCH\n"); break;
-    case HTTP_NOTIFY:      printf("method: HTTP_NOTIFY\n"); break;
-    case HTTP_SUBSCRIBE:   printf("method: HTTP_SUBSCRIBE\n"); break;
-    case HTTP_UNSUBSCRIBE: printf("method: HTTP_UNSUBSCRIBE\n"); break;
-		default:
-      printf("method: UNKNOWN\n"); break;
-			break;
-	}
-	printf("status_code :%d\n", m->status_code);
-  printf("request_path:%s\n", m->request_path);
-  printf("request_url :%s\n", m->request_url);
-  printf("fragment    :%s\n", m->fragment);
-  printf("query_string:%s\n", m->query_string);
-
-	bla = quote(m->body);
-  printf("body        :\"%s\"\n", bla);
-	free(bla);
-  printf("body_size   :%zu\n", m->body_size);
-
-	for (i=0; i!=m->num_headers; ++i){
-		printf("header_%d :{ \"%s\": \"%s\"}\n", i, m->headers[i][0], m->headers[i][1]);
-	}
-
-  printf("should_keep_alive         :%d\n", m->should_keep_alive);
-  printf("upgrade                   :%d\n", m->upgrade);
-  printf("http_major                :%d\n", m->http_major);
-  printf("http_minor                :%d\n", m->http_minor);
-//  printf("message_begin_cb_called   :%d\n", m->message_begin_cb_called);
-//  printf("headers_complete_cb_called:%d\n", m->headers_complete_cb_called);
-//  printf("message_complete_cb_called:%d\n", m->message_complete_cb_called);
-//  printf("message_complete_on_eof   :%d\n", m->message_complete_on_eof);
-	printf("\n");
-}
-
-void 
-dump_messages(void) 
-{
-  int request_count;
-  for (request_count = 0; requests[request_count].name; request_count++){
-    dump_message(&requests[request_count]);
-  }
-  for (request_count = 0; responses[request_count].name; request_count++){
-    dump_message(&responses[request_count]);
-  }
-}
-
-int
-main (int argc, char * argv[])
-{
-  parser = NULL;
-  int i, j, k;
-  int request_count;
-  int response_count;
-  
-  if (1 != argc) {
-    if (0 == (strncmp("-dump", argv[1], sizeof("-dump")))) {
-      dump_messages();
-      exit(0);
-    }
-  }
-
-  printf("sizeof(http_parser) = %u\n", (unsigned int)sizeof(http_parser));
-
-  for (request_count = 0; requests[request_count].name; request_count++);
-  for (response_count = 0; responses[response_count].name; response_count++);
-
-  //// OVERFLOW CONDITIONS
-
-  test_header_overflow_error(HTTP_REQUEST);
-  test_no_overflow_long_body(HTTP_REQUEST, 1000);
-  test_no_overflow_long_body(HTTP_REQUEST, 100000);
-
-  test_header_overflow_error(HTTP_RESPONSE);
-  test_no_overflow_long_body(HTTP_RESPONSE, 1000);
-  test_no_overflow_long_body(HTTP_RESPONSE, 100000);
-
-  //// RESPONSES
-
-  for (i = 0; i < response_count; i++) {
-    test_message(&responses[i]);
-  }
-
-  for (i = 0; i < response_count; i++) {
-    if (!responses[i].should_keep_alive) continue;
-    for (j = 0; j < response_count; j++) {
-      if (!responses[j].should_keep_alive) continue;
-      for (k = 0; k < response_count; k++) {
-        test_multiple3(&responses[i], &responses[j], &responses[k]);
-      }
-    }
-  }
-
-  test_message_count_body(&responses[NO_HEADERS_NO_BODY_404]);
-  test_message_count_body(&responses[TRAILING_SPACE_ON_CHUNKED_BODY]);
-
-  // test very large chunked response
-  {
-    char * msg = create_large_chunked_message(31337,
-      "HTTP/1.0 200 OK\r\n"
-      "Transfer-Encoding: chunked\r\n"
-      "Content-Type: text/plain\r\n"
-      "\r\n");
-    struct message large_chunked =
-      {.name= "large chunked"
-      ,.type= HTTP_RESPONSE
-      ,.raw= msg
-      ,.should_keep_alive= FALSE
-      ,.message_complete_on_eof= FALSE
-      ,.http_major= 1
-      ,.http_minor= 0
-      ,.status_code= 200
-      ,.num_headers= 2
-      ,.headers=
-        { { "Transfer-Encoding", "chunked" }
-        , { "Content-Type", "text/plain" }
-        }
-      ,.body_size= 31337*1024
-      };
-    test_message_count_body(&large_chunked);
-    free(msg);
-  }
-
-
-
-  printf("response scan 1/2      ");
-  test_scan( &responses[TRAILING_SPACE_ON_CHUNKED_BODY]
-           , &responses[NO_HEADERS_NO_BODY_404]
-           , &responses[NO_REASON_PHRASE]
-           );
-
-  printf("response scan 2/2      ");
-  test_scan( &responses[BONJOUR_MADAME_FR]
-           , &responses[UNDERSTORE_HEADER_KEY]
-           , &responses[NO_CARRIAGE_RET]
-           );
-
-  puts("responses okay");
-
-
-  /// REQUESTS
-
-  test_simple("hello world", 0);
-  test_simple("GET / HTP/1.1\r\n\r\n", 0);
-
-
-  test_simple("ASDF / HTTP/1.1\r\n\r\n", 0);
-  test_simple("PROPPATCHA / HTTP/1.1\r\n\r\n", 0);
-  test_simple("GETA / HTTP/1.1\r\n\r\n", 0);
-
-  // Well-formed but incomplete
-  test_simple("GET / HTTP/1.1\r\n"
-              "Content-Type: text/plain\r\n"
-              "Content-Length: 6\r\n"
-              "\r\n"
-              "fooba",
-              0);
-
-  static const char *all_methods[] = {
-    "DELETE",
-    "GET",
-    "HEAD",
-    "POST",
-    "PUT",
-    //"CONNECT", //CONNECT can't be tested like other methods, it's a tunnel
-    "OPTIONS",
-    "TRACE",
-    "COPY",
-    "LOCK",
-    "MKCOL",
-    "MOVE",
-    "PROPFIND",
-    "PROPPATCH",
-    "UNLOCK",
-    0 };
-  const char **this_method;
-  for (this_method = all_methods; *this_method; this_method++) {
-    char buf[200];
-    sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method);
-    test_simple(buf, 1);
-  }
-
-  const char *dumbfuck2 =
-    "GET / HTTP/1.1\r\n"
-    "X-SSL-Bullshit:   -----BEGIN CERTIFICATE-----\r\n"
-    "\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n"
-    "\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n"
-    "\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n"
-    "\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n"
-    "\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n"
-    "\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n"
-    "\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n"
-    "\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n"
-    "\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n"
-    "\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n"
-    "\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n"
-    "\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n"
-    "\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgHTTPAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n"
-    "\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n"
-    "\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n"
-    "\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n"
-    "\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n"
-    "\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n"
-    "\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n"
-    "\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n"
-    "\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n"
-    "\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n"
-    "\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n"
-    "\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n"
-    "\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n"
-    "\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n"
-    "\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n"
-    "\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n"
-    "\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n"
-    "\tRA==\r\n"
-    "\t-----END CERTIFICATE-----\r\n"
-    "\r\n";
-  test_simple(dumbfuck2, 0);
-
-#if 0
-  // NOTE(Wed Nov 18 11:57:27 CET 2009) this seems okay. we just read body
-  // until EOF.
-  //
-  // no content-length
-  // error if there is a body without content length
-  const char *bad_get_no_headers_no_body = "GET /bad_get_no_headers_no_body/world HTTP/1.1\r\n"
-                                           "Accept: */*\r\n"
-                                           "\r\n"
-                                           "HELLO";
-  test_simple(bad_get_no_headers_no_body, 0);
-#endif
-  /* TODO sending junk and large headers gets rejected */
-
-
-  /* check to make sure our predefined requests are okay */
-  for (i = 0; requests[i].name; i++) {
-    test_message(&requests[i]);
-  }
-
-
-
-  for (i = 0; i < request_count; i++) {
-    if (!requests[i].should_keep_alive) continue;
-    for (j = 0; j < request_count; j++) {
-      if (!requests[j].should_keep_alive) continue;
-      for (k = 0; k < request_count; k++) {
-        test_multiple3(&requests[i], &requests[j], &requests[k]);
-      }
-    }
-  }
-
-  printf("request scan 1/4      ");
-  test_scan( &requests[GET_NO_HEADERS_NO_BODY]
-           , &requests[GET_ONE_HEADER_NO_BODY]
-           , &requests[GET_NO_HEADERS_NO_BODY]
-           );
-
-  printf("request scan 2/4      ");
-  test_scan( &requests[POST_CHUNKED_ALL_YOUR_BASE]
-           , &requests[POST_IDENTITY_BODY_WORLD]
-           , &requests[GET_FUNKY_CONTENT_LENGTH]
-           );
-
-  printf("request scan 3/4      ");
-  test_scan( &requests[TWO_CHUNKS_MULT_ZERO_END]
-           , &requests[CHUNKED_W_TRAILING_HEADERS]
-           , &requests[CHUNKED_W_BULLSHIT_AFTER_LENGTH]
-           );
-
-  printf("request scan 4/4      ");
-  test_scan( &requests[QUERY_URL_WITH_QUESTION_MARK_GET]
-           , &requests[PREFIX_NEWLINE_GET ]
-           , &requests[CONNECT_REQUEST]
-           );
-
-  puts("requests okay");
-
-  return 0;
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/test_permutations b/ext/ruby_http_parser/vendor/http-parser-java/test_permutations
deleted file mode 100644
index 2ec67b5..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/test_permutations
+++ /dev/null
@@ -1 +0,0 @@
-javac -cp ext/primitives.jar -d classes/ `find src -name '*.java'`  && java -cp classes:ext/primitives.jar http_parser.lolevel.TestLoaderNG tests.dumped
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/test_unit b/ext/ruby_http_parser/vendor/http-parser-java/test_unit
deleted file mode 100644
index 7bcc9e8..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/test_unit
+++ /dev/null
@@ -1 +0,0 @@
-javac -cp ext/primitives.jar -d classes/ `find src -name '*.java'`  && java -cp classes:ext/primitives.jar http_parser.lolevel.UnitTest
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/test_utf8 b/ext/ruby_http_parser/vendor/http-parser-java/test_utf8
deleted file mode 100644
index 921c74f..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/test_utf8
+++ /dev/null
@@ -1 +0,0 @@
-javac -cp ext/primitives.jar -d classes/ `find src -name '*.java'`  && java -cp classes:ext/primitives.jar http_parser.lolevel.TestLoaderNG tests.utf8
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/tests.dumped b/ext/ruby_http_parser/vendor/http-parser-java/tests.dumped
deleted file mode 100644
index 07f7b23..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/tests.dumped
+++ /dev/null
@@ -1,686 +0,0 @@
-name  :curl get
-raw   :"GET /test HTTP/1.1\r\nUser-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\nHost: 0.0.0.0=5000\r\nAccept: */*\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/test
-request_url :/test
-fragment    :
-query_string:
-body        :""
-body_size   :0
-header_0 :{ "User-Agent": "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1"}
-header_1 :{ "Host": "0.0.0.0=5000"}
-header_2 :{ "Accept": "*/*"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :firefox get
-raw   :"GET /favicon.ico HTTP/1.1\r\nHost: 0.0.0.0=5000\r\nUser-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-us,en;q=0.5\r\nAccept-Encoding: gzip,deflate\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\nKeep-Alive: 300\r\nConnection: keep-alive\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/favicon.ico
-request_url :/favicon.ico
-fragment    :
-query_string:
-body        :""
-body_size   :0
-header_0 :{ "Host": "0.0.0.0=5000"}
-header_1 :{ "User-Agent": "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0"}
-header_2 :{ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}
-header_3 :{ "Accept-Language": "en-us,en;q=0.5"}
-header_4 :{ "Accept-Encoding": "gzip,deflate"}
-header_5 :{ "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7"}
-header_6 :{ "Keep-Alive": "300"}
-header_7 :{ "Connection": "keep-alive"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :dumbfuck
-raw   :"GET /dumbfuck HTTP/1.1\r\naaaaaaaaaaaaa:++++++++++\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/dumbfuck
-request_url :/dumbfuck
-fragment    :
-query_string:
-body        :""
-body_size   :0
-header_0 :{ "aaaaaaaaaaaaa": "++++++++++"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :fragment in url
-raw   :"GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/forums/1/topics/2375
-request_url :/forums/1/topics/2375?page=1#posts-17408
-fragment    :posts-17408
-query_string:page=1
-body        :""
-body_size   :0
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :get no headers no body
-raw   :"GET /get_no_headers_no_body/world HTTP/1.1\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/get_no_headers_no_body/world
-request_url :/get_no_headers_no_body/world
-fragment    :
-query_string:
-body        :""
-body_size   :0
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :get one header no body
-raw   :"GET /get_one_header_no_body HTTP/1.1\r\nAccept: */*\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/get_one_header_no_body
-request_url :/get_one_header_no_body
-fragment    :
-query_string:
-body        :""
-body_size   :0
-header_0 :{ "Accept": "*/*"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :get funky content length body hello
-raw   :"GET /get_funky_content_length_body_hello HTTP/1.0\r\nconTENT-Length: 5\r\n\r\nHELLO"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/get_funky_content_length_body_hello
-request_url :/get_funky_content_length_body_hello
-fragment    :
-query_string:
-body        :"HELLO"
-body_size   :0
-header_0 :{ "conTENT-Length": "5"}
-should_keep_alive         :0
-upgrade                   :0
-http_major                :1
-http_minor                :0
-
-name  :post identity body world
-raw   :"POST /post_identity_body_world?q=search#hey HTTP/1.1\r\nAccept: */*\r\nTransfer-Encoding: identity\r\nContent-Length: 5\r\n\r\nWorld"
-type  :HTTP_REQUEST
-method: HTTP_POST
-status_code :0
-request_path:/post_identity_body_world
-request_url :/post_identity_body_world?q=search#hey
-fragment    :hey
-query_string:q=search
-body        :"World"
-body_size   :0
-header_0 :{ "Accept": "*/*"}
-header_1 :{ "Transfer-Encoding": "identity"}
-header_2 :{ "Content-Length": "5"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :post - chunked body: all your base are belong to us
-raw   :"POST /post_chunked_all_your_base HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n1e\r\nall your base are belong to us\r\n0\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_POST
-status_code :0
-request_path:/post_chunked_all_your_base
-request_url :/post_chunked_all_your_base
-fragment    :
-query_string:
-body        :"all your base are belong to us"
-body_size   :0
-header_0 :{ "Transfer-Encoding": "chunked"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :two chunks ; triple zero ending
-raw   :"POST /two_chunks_mult_zero_end HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhello\r\n6\r\n world\r\n000\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_POST
-status_code :0
-request_path:/two_chunks_mult_zero_end
-request_url :/two_chunks_mult_zero_end
-fragment    :
-query_string:
-body        :"hello world"
-body_size   :0
-header_0 :{ "Transfer-Encoding": "chunked"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :chunked with trailing headers. blech.
-raw   :"POST /chunked_w_trailing_headers HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhello\r\n6\r\n world\r\n0\r\nVary: *\r\nContent-Type: text/plain\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_POST
-status_code :0
-request_path:/chunked_w_trailing_headers
-request_url :/chunked_w_trailing_headers
-fragment    :
-query_string:
-body        :"hello world"
-body_size   :0
-header_0 :{ "Transfer-Encoding": "chunked"}
-header_1 :{ "Vary": "*"}
-header_2 :{ "Content-Type": "text/plain"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :with bullshit after the length
-raw   :"POST /chunked_w_bullshit_after_length HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n5; ihatew3;whatthefuck=aretheseparametersfor\r\nhello\r\n6; blahblah; blah\r\n world\r\n0\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_POST
-status_code :0
-request_path:/chunked_w_bullshit_after_length
-request_url :/chunked_w_bullshit_after_length
-fragment    :
-query_string:
-body        :"hello world"
-body_size   :0
-header_0 :{ "Transfer-Encoding": "chunked"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :with quotes
-raw   :"GET /with_\"stupid\"_quotes?foo=\"bar\" HTTP/1.1\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/with_"stupid"_quotes
-request_url :/with_"stupid"_quotes?foo="bar"
-fragment    :
-query_string:foo="bar"
-body        :""
-body_size   :0
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :apachebench get
-raw   :"GET /test HTTP/1.0\r\nHost: 0.0.0.0:5000\r\nUser-Agent: ApacheBench/2.3\r\nAccept: */*\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/test
-request_url :/test
-fragment    :
-query_string:
-body        :""
-body_size   :0
-header_0 :{ "Host": "0.0.0.0:5000"}
-header_1 :{ "User-Agent": "ApacheBench/2.3"}
-header_2 :{ "Accept": "*/*"}
-should_keep_alive         :0
-upgrade                   :0
-http_major                :1
-http_minor                :0
-
-name  :query url with question mark
-raw   :"GET /test.cgi?foo=bar?baz HTTP/1.1\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/test.cgi
-request_url :/test.cgi?foo=bar?baz
-fragment    :
-query_string:foo=bar?baz
-body        :""
-body_size   :0
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :newline prefix get
-raw   :"\r\nGET /test HTTP/1.1\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/test
-request_url :/test
-fragment    :
-query_string:
-body        :""
-body_size   :0
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :upgrade request
-raw   :"GET /demo HTTP/1.1\r\nHost: example.com\r\nConnection: Upgrade\r\nSec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\nSec-WebSocket-Protocol: sample\r\nUpgrade: WebSocket\r\nSec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\nOrigin: http://example.com\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/demo
-request_url :/demo
-fragment    :
-query_string:
-body        :""
-body_size   :0
-header_0 :{ "Host": "example.com"}
-header_1 :{ "Connection": "Upgrade"}
-header_2 :{ "Sec-WebSocket-Key2": "12998 5 Y3 1  .P00"}
-header_3 :{ "Sec-WebSocket-Protocol": "sample"}
-header_4 :{ "Upgrade": "WebSocket"}
-header_5 :{ "Sec-WebSocket-Key1": "4 @1  46546xW%0l 1 5"}
-header_6 :{ "Origin": "http://example.com"}
-should_keep_alive         :1
-upgrade                   :1
-http_major                :1
-http_minor                :1
-
-name  :connect request
-raw   :"CONNECT home0.netscape.com:443 HTTP/1.0\r\nUser-agent: Mozilla/1.1N\r\nProxy-authorization: basic aGVsbG86d29ybGQ=\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_CONNECT
-status_code :0
-request_path:
-request_url :home0.netscape.com:443
-fragment    :
-query_string:
-body        :""
-body_size   :0
-header_0 :{ "User-agent": "Mozilla/1.1N"}
-header_1 :{ "Proxy-authorization": "basic aGVsbG86d29ybGQ="}
-should_keep_alive         :0
-upgrade                   :1
-http_major                :1
-http_minor                :0
-
-name  :report request
-raw   :"REPORT /test HTTP/1.1\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_REPORT
-status_code :0
-request_path:/test
-request_url :/test
-fragment    :
-query_string:
-body        :""
-body_size   :0
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :request with no http version
-raw   :"GET /\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/
-request_url :/
-fragment    :
-query_string:
-body        :""
-body_size   :0
-should_keep_alive         :0
-upgrade                   :0
-http_major                :0
-http_minor                :9
-
-name  :m-search request
-raw   :"M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nST: \"ssdp:all\"\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_MSEARCH
-status_code :0
-request_path:*
-request_url :*
-fragment    :
-query_string:
-body        :""
-body_size   :0
-header_0 :{ "HOST": "239.255.255.250:1900"}
-header_1 :{ "MAN": ""ssdp:discover""}
-header_2 :{ "ST": ""ssdp:all""}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :utf-8 path request
-raw   :"GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\nHost: github.com\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/δ¶/δt/pope
-request_url :/δ¶/δt/pope?q=1#narf
-fragment    :narf
-query_string:q=1
-body        :""
-body_size   :0
-header_0 :{ "Host": "github.com"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :host terminated by a query string
-raw   :"GET http://hypnotoad.org?hail=all HTTP/1.1\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:
-request_url :http://hypnotoad.org?hail=all
-fragment    :
-query_string:hail=all
-body        :""
-body_size   :0
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :host:port terminated by a query string
-raw   :"GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:
-request_url :http://hypnotoad.org:1234?hail=all
-fragment    :
-query_string:hail=all
-body        :""
-body_size   :0
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :host:port terminated by a space
-raw   :"GET http://hypnotoad.org:1234 HTTP/1.1\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:
-request_url :http://hypnotoad.org:1234
-fragment    :
-query_string:
-body        :""
-body_size   :0
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :google 301
-raw   :"HTTP/1.1 301 Moved Permanently\r\nLocation: http://www.google.com/\r\nContent-Type: text/html; charset=UTF-8\r\nDate: Sun, 26 Apr 2009 11:11:49 GMT\r\nExpires: Tue, 26 May 2009 11:11:49 GMT\r\nX-$PrototypeBI-Version: 1.6.0.3\r\nCache-Control: public, max-age=2592000\r\nServer: gws\r\nContent-Length:  219  \r\n\r\n<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<TITLE>301 Moved</TITLE></HEAD><BODY>\n<H1>301 Moved</H1>\nThe document has moved\n<A HREF=\"http://www.google.com/\">here</A>.\r\n</BODY></HTML>\r\n"
-type  :HTTP_RESPONSE
-method: HTTP_DELETE
-status_code :301
-request_path:
-request_url :
-fragment    :
-query_string:
-body        :"<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<TITLE>301 Moved</TITLE></HEAD><BODY>\n<H1>301 Moved</H1>\nThe document has moved\n<A HREF=\"http://www.google.com/\">here</A>.\r\n</BODY></HTML>\r\n"
-body_size   :0
-header_0 :{ "Location": "http://www.google.com/"}
-header_1 :{ "Content-Type": "text/html; charset=UTF-8"}
-header_2 :{ "Date": "Sun, 26 Apr 2009 11:11:49 GMT"}
-header_3 :{ "Expires": "Tue, 26 May 2009 11:11:49 GMT"}
-header_4 :{ "X-$PrototypeBI-Version": "1.6.0.3"}
-header_5 :{ "Cache-Control": "public, max-age=2592000"}
-header_6 :{ "Server": "gws"}
-header_7 :{ "Content-Length": "219  "}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :no content-length response
-raw   :"HTTP/1.1 200 OK\r\nDate: Tue, 04 Aug 2009 07:59:32 GMT\r\nServer: Apache\r\nX-Powered-By: Servlet/2.5 JSP/2.1\r\nContent-Type: text/xml; charset=utf-8\r\nConnection: close\r\n\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <SOAP-ENV:Body>\n    <SOAP-ENV:Fault>\n       <faultcode>SOAP-ENV:Client</faultcode>\n       <faultstring>Client Error</faultstring>\n    </SOAP-ENV:Fault>\n  </SOAP-ENV:Body>\n</SOAP-ENV:Envelope>"
-type  :HTTP_RESPONSE
-method: HTTP_DELETE
-status_code :200
-request_path:
-request_url :
-fragment    :
-query_string:
-body        :"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <SOAP-ENV:Body>\n    <SOAP-ENV:Fault>\n       <faultcode>SOAP-ENV:Client</faultcode>\n       <faultstring>Client Error</faultstring>\n    </SOAP-ENV:Fault>\n  </SOAP-ENV:Body>\n</SOAP-ENV:Envelope>"
-body_size   :0
-header_0 :{ "Date": "Tue, 04 Aug 2009 07:59:32 GMT"}
-header_1 :{ "Server": "Apache"}
-header_2 :{ "X-Powered-By": "Servlet/2.5 JSP/2.1"}
-header_3 :{ "Content-Type": "text/xml; charset=utf-8"}
-header_4 :{ "Connection": "close"}
-should_keep_alive         :0
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :404 no headers no body
-raw   :"HTTP/1.1 404 Not Found\r\n\r\n"
-type  :HTTP_RESPONSE
-method: HTTP_DELETE
-status_code :404
-request_path:
-request_url :
-fragment    :
-query_string:
-body        :""
-body_size   :0
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :301 no response phrase
-raw   :"HTTP/1.1 301\r\n\r\n"
-type  :HTTP_RESPONSE
-method: HTTP_DELETE
-status_code :301
-request_path:
-request_url :
-fragment    :
-query_string:
-body        :""
-body_size   :0
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :200 trailing space on chunked body
-raw   :"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nTransfer-Encoding: chunked\r\n\r\n25  \r\nThis is the data in the first chunk\r\n\r\n1C\r\nand this is the second one\r\n\r\n0  \r\n\r\n"
-type  :HTTP_RESPONSE
-method: HTTP_DELETE
-status_code :200
-request_path:
-request_url :
-fragment    :
-query_string:
-body        :"This is the data in the first chunk\r\nand this is the second one\r\n"
-body_size   :65
-header_0 :{ "Content-Type": "text/plain"}
-header_1 :{ "Transfer-Encoding": "chunked"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :no carriage ret
-raw   :"HTTP/1.1 200 OK\nContent-Type: text/html; charset=utf-8\nConnection: close\n\nthese headers are from http://news.ycombinator.com/"
-type  :HTTP_RESPONSE
-method: HTTP_DELETE
-status_code :200
-request_path:
-request_url :
-fragment    :
-query_string:
-body        :"these headers are from http://news.ycombinator.com/"
-body_size   :0
-header_0 :{ "Content-Type": "text/html; charset=utf-8"}
-header_1 :{ "Connection": "close"}
-should_keep_alive         :0
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :proxy connection
-raw   :"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: 11\r\nProxy-Connection: close\r\nDate: Thu, 31 Dec 2009 20:55:48 +0000\r\n\r\nhello world"
-type  :HTTP_RESPONSE
-method: HTTP_DELETE
-status_code :200
-request_path:
-request_url :
-fragment    :
-query_string:
-body        :"hello world"
-body_size   :0
-header_0 :{ "Content-Type": "text/html; charset=UTF-8"}
-header_1 :{ "Content-Length": "11"}
-header_2 :{ "Proxy-Connection": "close"}
-header_3 :{ "Date": "Thu, 31 Dec 2009 20:55:48 +0000"}
-should_keep_alive         :0
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :underscore header key
-raw   :"HTTP/1.1 200 OK\r\nServer: DCLK-AdSvr\r\nContent-Type: text/xml\r\nContent-Length: 0\r\nDCLK_imp: v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o\r\n\r\n"
-type  :HTTP_RESPONSE
-method: HTTP_DELETE
-status_code :200
-request_path:
-request_url :
-fragment    :
-query_string:
-body        :""
-body_size   :0
-header_0 :{ "Server": "DCLK-AdSvr"}
-header_1 :{ "Content-Type": "text/xml"}
-header_2 :{ "Content-Length": "0"}
-header_3 :{ "DCLK_imp": "v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :bonjourmadame.fr
-raw   :"HTTP/1.0 301 Moved Permanently\r\nDate: Thu, 03 Jun 2010 09:56:32 GMT\r\nServer: Apache/2.2.3 (Red Hat)\r\nCache-Control: public\r\nPragma: \r\nLocation: http://www.bonjourmadame.fr/\r\nVary: Accept-Encoding\r\nContent-Length: 0\r\nContent-Type: text/html; charset=UTF-8\r\nConnection: keep-alive\r\n\r\n"
-type  :HTTP_RESPONSE
-method: HTTP_DELETE
-status_code :301
-request_path:
-request_url :
-fragment    :
-query_string:
-body        :""
-body_size   :0
-header_0 :{ "Date": "Thu, 03 Jun 2010 09:56:32 GMT"}
-header_1 :{ "Server": "Apache/2.2.3 (Red Hat)"}
-header_2 :{ "Cache-Control": "public"}
-header_3 :{ "Pragma": ""}
-header_4 :{ "Location": "http://www.bonjourmadame.fr/"}
-header_5 :{ "Vary": "Accept-Encoding"}
-header_6 :{ "Content-Length": "0"}
-header_7 :{ "Content-Type": "text/html; charset=UTF-8"}
-header_8 :{ "Connection": "keep-alive"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :0
-
-name  :field space
-raw   :"HTTP/1.1 200 OK\r\nServer: Microsoft-IIS/6.0\r\nX-Powered-By: ASP.NET\r\nen-US Content-Type: text/xml\r\nContent-Type: text/xml\r\nContent-Length: 16\r\nDate: Fri, 23 Jul 2010 18:45:38 GMT\r\nConnection: keep-alive\r\n\r\n<xml>hello</xml>"
-type  :HTTP_RESPONSE
-method: HTTP_DELETE
-status_code :200
-request_path:
-request_url :
-fragment    :
-query_string:
-body        :"<xml>hello</xml>"
-body_size   :0
-header_0 :{ "Server": "Microsoft-IIS/6.0"}
-header_1 :{ "X-Powered-By": "ASP.NET"}
-header_2 :{ "en-US Content-Type": "text/xml"}
-header_3 :{ "Content-Type": "text/xml"}
-header_4 :{ "Content-Length": "16"}
-header_5 :{ "Date": "Fri, 23 Jul 2010 18:45:38 GMT"}
-header_6 :{ "Connection": "keep-alive"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :field underscore
-raw   :"HTTP/1.1 200 OK\r\nDate: Tue, 28 Sep 2010 01:14:13 GMT\r\nServer: Apache\r\nCache-Control: no-cache, must-revalidate\r\nExpires: Mon, 26 Jul 1997 05:00:00 GMT\r\n.et-Cookie: PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com\r\nVary: Accept-Encoding\r\n_eep-Alive: timeout=45\r\n_onnection: Keep-Alive\r\nTransfer-Encoding: chunked\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n0\r\n\r\n"
-type  :HTTP_RESPONSE
-method: HTTP_DELETE
-status_code :200
-request_path:
-request_url :
-fragment    :
-query_string:
-body        :""
-body_size   :0
-header_0 :{ "Date": "Tue, 28 Sep 2010 01:14:13 GMT"}
-header_1 :{ "Server": "Apache"}
-header_2 :{ "Cache-Control": "no-cache, must-revalidate"}
-header_3 :{ "Expires": "Mon, 26 Jul 1997 05:00:00 GMT"}
-header_4 :{ ".et-Cookie": "PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com"}
-header_5 :{ "Vary": "Accept-Encoding"}
-header_6 :{ "_eep-Alive": "timeout=45"}
-header_7 :{ "_onnection": "Keep-Alive"}
-header_8 :{ "Transfer-Encoding": "chunked"}
-header_9 :{ "Content-Type": "text/html"}
-header_10 :{ "Connection": "close"}
-should_keep_alive         :0
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
-name  :non-ASCII in status line
-raw   :"HTTP/1.1 500 Oriëntatieprobleem\r\nDate: Fri, 5 Nov 2010 23:07:12 GMT+2\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"
-type  :HTTP_RESPONSE
-method: HTTP_DELETE
-status_code :500
-request_path:
-request_url :
-fragment    :
-query_string:
-body        :""
-body_size   :0
-header_0 :{ "Date": "Fri, 5 Nov 2010 23:07:12 GMT+2"}
-header_1 :{ "Content-Length": "0"}
-header_2 :{ "Connection": "close"}
-should_keep_alive         :0
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/tests.utf8 b/ext/ruby_http_parser/vendor/http-parser-java/tests.utf8
deleted file mode 100644
index 5266159..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/tests.utf8
+++ /dev/null
@@ -1,17 +0,0 @@
-name  :utf-8 path request
-raw   :"GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\nHost: github.com\r\n\r\n"
-type  :HTTP_REQUEST
-method: HTTP_GET
-status_code :0
-request_path:/δ¶/δt/pope
-request_url :/δ¶/δt/pope?q=1#narf
-fragment    :narf
-query_string:q=1
-body        :""
-body_size   :0
-header_0 :{ "Host": "github.com"}
-should_keep_alive         :1
-upgrade                   :0
-http_major                :1
-http_minor                :1
-
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/tools/byte_constants.rb b/ext/ruby_http_parser/vendor/http-parser-java/tools/byte_constants.rb
deleted file mode 100644
index 1604890..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/tools/byte_constants.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-
-"A".upto("Z") {|c|
-	puts "public static final byte #{c} = 0x#{c[0].to_s(16)};"
-}
-
-
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/tools/const_char.rb b/ext/ruby_http_parser/vendor/http-parser-java/tools/const_char.rb
deleted file mode 100644
index 84f9699..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/tools/const_char.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-def printbytes str
-str.each_byte { |b|
-	print "0x#{b.to_s(16)}, "
-}
-end
-
-if $0 == __FILE__
-	printf "static final byte [] #{ARGV[0]} = {\n"
-	printbytes ARGV[0]
-	printf "\n};\n"
-end
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/tools/lowcase.rb b/ext/ruby_http_parser/vendor/http-parser-java/tools/lowcase.rb
deleted file mode 100644
index 13960cb..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/tools/lowcase.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-0.upto(255) { |i|
-	printf "\n" if i%16 == 0
-	printf "  "  if i%8 == 0
-	s = ("" << i)
-	if s =~ /[A-Z0-9\-_\/ ]/
-		print "0x#{i.to_s(16)}," 	
-	elsif s =~ /[a-z]/
-		print "0x#{s.upcase[0].to_s(16)},"
-	else
-		print "0x00,"
-	end
-
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser-java/tools/parse_tests.rb b/ext/ruby_http_parser/vendor/http-parser-java/tools/parse_tests.rb
deleted file mode 100644
index 683adb9..0000000
--- a/ext/ruby_http_parser/vendor/http-parser-java/tools/parse_tests.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-# name  : 200 trailing space on chunked body
-# raw   : "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nTransfer-Encoding: chunked\r\n\r\n25  \r\nThis is the data in the first chunk\r\n\r\n1C\r\nand this is the second one\r\n\r\n0  \r\n\r\n"
-# type  : HTTP_RESPONSE
-# method: HTTP_DELETE
-# status code :200
-# request_path:
-# request_url :
-# fragment    :
-# query_string:
-# body        :"This is the data in the first chunk\r\nand this is the second one\r\n"
-# body_size   :65
-# header_0 :{ "Content-Type": "text/plain"}
-# header_1 :{ "Transfer-Encoding": "chunked"}
-# should_keep_alive         :1
-# upgrade                   :0
-# http_major                :1
-# http_minor                :1
-
-
-class ParserTest
-	attr_accessor :name
-	attr_accessor :raw
-	attr_accessor :type
-	attr_accessor :method
-	attr_accessor :status_code
-	attr_accessor :request_path
-	attr_accessor :method
-end
-
diff --git a/ext/ruby_http_parser/vendor/http-parser/CONTRIBUTIONS b/ext/ruby_http_parser/vendor/http-parser/CONTRIBUTIONS
deleted file mode 100644
index 11ba31e..0000000
--- a/ext/ruby_http_parser/vendor/http-parser/CONTRIBUTIONS
+++ /dev/null
@@ -1,4 +0,0 @@
-Contributors must agree to the Contributor License Agreement before patches
-can be accepted.
-
-http://spreadsheets2.google.com/viewform?hl=en&formkey=dDJXOGUwbzlYaWM4cHN1MERwQS1CSnc6MQ
diff --git a/ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT b/ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT
deleted file mode 100644
index 40ebce2..0000000
--- a/ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright Joyent, Inc. and other Node contributors. All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to
-deal in the Software without restriction, including without limitation the
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-IN THE SOFTWARE. 
diff --git a/ext/ruby_http_parser/vendor/http-parser/Makefile b/ext/ruby_http_parser/vendor/http-parser/Makefile
deleted file mode 100644
index 2b945c1..0000000
--- a/ext/ruby_http_parser/vendor/http-parser/Makefile
+++ /dev/null
@@ -1,41 +0,0 @@
-OPT_DEBUG=-O0 -g -Wall -Wextra -Werror -I.
-OPT_FAST=-O3 -DHTTP_PARSER_STRICT=0 -I.
-
-CC?=gcc
-
-
-test: test_g
-	./test_g
-
-test_g: http_parser_g.o test_g.o
-	$(CC) $(OPT_DEBUG) http_parser_g.o test_g.o -o $@
-
-test_g.o: test.c http_parser.h Makefile
-	$(CC) $(OPT_DEBUG) -c test.c -o $@
-
-test.o: test.c http_parser.h Makefile
-	$(CC) $(OPT_FAST) -c test.c -o $@
-
-http_parser_g.o: http_parser.c http_parser.h Makefile
-	$(CC) $(OPT_DEBUG) -c http_parser.c -o $@
-
-test-valgrind: test_g
-	valgrind ./test_g
-
-http_parser.o: http_parser.c http_parser.h Makefile
-	$(CC) $(OPT_FAST) -c http_parser.c
-
-test_fast: http_parser.o test.c http_parser.h
-	$(CC) $(OPT_FAST) http_parser.o test.c -o $@
-
-test-run-timed: test_fast
-	while(true) do time ./test_fast > /dev/null; done
-
-
-tags: http_parser.c http_parser.h test.c
-	ctags $^
-
-clean:
-	rm -f *.o test test_fast test_g http_parser.tar tags
-
-.PHONY: clean package test-run test-run-timed test-valgrind
diff --git a/ext/ruby_http_parser/vendor/http-parser/README.md b/ext/ruby_http_parser/vendor/http-parser/README.md
deleted file mode 100644
index 72332fb..0000000
--- a/ext/ruby_http_parser/vendor/http-parser/README.md
+++ /dev/null
@@ -1,171 +0,0 @@
-HTTP Parser
-===========
-
-This is a parser for HTTP messages written in C. It parses both requests and
-responses. The parser is designed to be used in performance HTTP
-applications. It does not make any syscalls nor allocations, it does not
-buffer data, it can be interrupted at anytime. Depending on your
-architecture, it only requires about 40 bytes of data per message
-stream (in a web server that is per connection).
-
-Features:
-
-  * No dependencies
-  * Handles persistent streams (keep-alive).
-  * Decodes chunked encoding.
-  * Upgrade support
-  * Defends against buffer overflow attacks.
-
-The parser extracts the following information from HTTP messages:
-
-  * Header fields and values
-  * Content-Length
-  * Request method
-  * Response status code
-  * Transfer-Encoding
-  * HTTP version
-  * Request path, query string, fragment
-  * Message body
-
-
-Usage
------
-
-One `http_parser` object is used per TCP connection. Initialize the struct
-using `http_parser_init()` and set the callbacks. That might look something
-like this for a request parser:
-
-    http_parser_settings settings;
-    settings.on_path = my_path_callback;
-    settings.on_header_field = my_header_field_callback;
-    /* ... */
-
-    http_parser *parser = malloc(sizeof(http_parser));
-    http_parser_init(parser, HTTP_REQUEST);
-    parser->data = my_socket;
-
-When data is received on the socket execute the parser and check for errors.
-
-    size_t len = 80*1024, nparsed;
-    char buf[len];
-    ssize_t recved;
-
-    recved = recv(fd, buf, len, 0);
-
-    if (recved < 0) {
-      /* Handle error. */
-    }
-
-    /* Start up / continue the parser.
-     * Note we pass recved==0 to signal that EOF has been recieved.
-     */
-    nparsed = http_parser_execute(parser, &settings, buf, recved);
-
-    if (parser->upgrade) {
-      /* handle new protocol */
-    } else if (nparsed != recved) {
-      /* Handle error. Usually just close the connection. */
-    }
-
-HTTP needs to know where the end of the stream is. For example, sometimes
-servers send responses without Content-Length and expect the client to
-consume input (for the body) until EOF. To tell http_parser about EOF, give
-`0` as the forth parameter to `http_parser_execute()`. Callbacks and errors
-can still be encountered during an EOF, so one must still be prepared
-to receive them.
-
-Scalar valued message information such as `status_code`, `method`, and the
-HTTP version are stored in the parser structure. This data is only
-temporally stored in `http_parser` and gets reset on each new message. If
-this information is needed later, copy it out of the structure during the
-`headers_complete` callback.
-
-The parser decodes the transfer-encoding for both requests and responses
-transparently. That is, a chunked encoding is decoded before being sent to
-the on_body callback.
-
-
-The Special Problem of Upgrade
-------------------------------
-
-HTTP supports upgrading the connection to a different protocol. An
-increasingly common example of this is the Web Socket protocol which sends
-a request like
-
-        GET /demo HTTP/1.1
-        Upgrade: WebSocket
-        Connection: Upgrade
-        Host: example.com
-        Origin: http://example.com
-        WebSocket-Protocol: sample
-
-followed by non-HTTP data.
-
-(See http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 for more
-information the Web Socket protocol.)
-
-To support this, the parser will treat this as a normal HTTP message without a
-body. Issuing both on_headers_complete and on_message_complete callbacks. However
-http_parser_execute() will stop parsing at the end of the headers and return.
-
-The user is expected to check if `parser->upgrade` has been set to 1 after
-`http_parser_execute()` returns. Non-HTTP data begins at the buffer supplied
-offset by the return value of `http_parser_execute()`.
-
-
-Callbacks
----------
-
-During the `http_parser_execute()` call, the callbacks set in
-`http_parser_settings` will be executed. The parser maintains state and
-never looks behind, so buffering the data is not necessary. If you need to
-save certain data for later usage, you can do that from the callbacks.
-
-There are two types of callbacks:
-
-* notification `typedef int (*http_cb) (http_parser*);`
-    Callbacks: on_message_begin, on_headers_complete, on_message_complete.
-* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);`
-    Callbacks: (requests only) on_path, on_query_string, on_uri, on_fragment,
-               (common) on_header_field, on_header_value, on_body;
-
-Callbacks must return 0 on success. Returning a non-zero value indicates
-error to the parser, making it exit immediately.
-
-In case you parse HTTP message in chunks (i.e. `read()` request line
-from socket, parse, read half headers, parse, etc) your data callbacks
-may be called more than once. Http-parser guarantees that data pointer is only
-valid for the lifetime of callback. You can also `read()` into a heap allocated
-buffer to avoid copying memory around if this fits your application.
-
-Reading headers may be a tricky task if you read/parse headers partially.
-Basically, you need to remember whether last header callback was field or value
-and apply following logic:
-
-    (on_header_field and on_header_value shortened to on_h_*)
-     ------------------------ ------------ --------------------------------------------
-    | State (prev. callback) | Callback   | Description/action                         |
-     ------------------------ ------------ --------------------------------------------
-    | nothing (first call)   | on_h_field | Allocate new buffer and copy callback data |
-    |                        |            | into it                                    |
-     ------------------------ ------------ --------------------------------------------
-    | value                  | on_h_field | New header started.                        |
-    |                        |            | Copy current name,value buffers to headers |
-    |                        |            | list and allocate new buffer for new name  |
-     ------------------------ ------------ --------------------------------------------
-    | field                  | on_h_field | Previous name continues. Reallocate name   |
-    |                        |            | buffer and append callback data to it      |
-     ------------------------ ------------ --------------------------------------------
-    | field                  | on_h_value | Value for current header started. Allocate |
-    |                        |            | new buffer and copy callback data to it    |
-     ------------------------ ------------ --------------------------------------------
-    | value                  | on_h_value | Value continues. Reallocate value buffer   |
-    |                        |            | and append callback data to it             |
-     ------------------------ ------------ --------------------------------------------
-
-
-See examples of reading in headers:
-
-* [partial example](http://gist.github.com/155877) in C
-* [from http-parser tests](http://github.com/ry/http-parser/blob/37a0ff8928fb0d83cec0d0d8909c5a4abcd221af/test.c#L403) in C
-* [from Node library](http://github.com/ry/node/blob/842eaf446d2fdcb33b296c67c911c32a0dabc747/src/http.js#L284) in Javascript
diff --git a/ext/ruby_http_parser/vendor/http-parser/http_parser.c b/ext/ruby_http_parser/vendor/http-parser/http_parser.c
deleted file mode 100644
index 0fe0e8f..0000000
--- a/ext/ruby_http_parser/vendor/http-parser/http_parser.c
+++ /dev/null
@@ -1,1644 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include <http_parser.h>
-#include <assert.h>
-#include <stddef.h>
-
-
-#ifndef MIN
-# define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-
-#define CALLBACK2(FOR)                                               \
-do {                                                                 \
-  if (settings->on_##FOR) {                                          \
-    if (0 != settings->on_##FOR(parser)) return (p - data);          \
-  }                                                                  \
-} while (0)
-
-
-#define MARK(FOR)                                                    \
-do {                                                                 \
-  FOR##_mark = p;                                                    \
-} while (0)
-
-#define CALLBACK_NOCLEAR(FOR)                                        \
-do {                                                                 \
-  if (FOR##_mark) {                                                  \
-    if (settings->on_##FOR) {                                        \
-      if (0 != settings->on_##FOR(parser,                            \
-                                 FOR##_mark,                         \
-                                 p - FOR##_mark))                    \
-      {                                                              \
-        return (p - data);                                           \
-      }                                                              \
-    }                                                                \
-  }                                                                  \
-} while (0)
-
-
-#define CALLBACK(FOR)                                                \
-do {                                                                 \
-  CALLBACK_NOCLEAR(FOR);                                             \
-  FOR##_mark = NULL;                                                 \
-} while (0)
-
-
-#define PROXY_CONNECTION "proxy-connection"
-#define CONNECTION "connection"
-#define CONTENT_LENGTH "content-length"
-#define TRANSFER_ENCODING "transfer-encoding"
-#define UPGRADE "upgrade"
-#define CHUNKED "chunked"
-#define KEEP_ALIVE "keep-alive"
-#define CLOSE "close"
-
-
-static const char *method_strings[] =
-  { "DELETE"
-  , "GET"
-  , "HEAD"
-  , "POST"
-  , "PUT"
-  , "CONNECT"
-  , "OPTIONS"
-  , "TRACE"
-  , "COPY"
-  , "LOCK"
-  , "MKCOL"
-  , "MOVE"
-  , "PROPFIND"
-  , "PROPPATCH"
-  , "UNLOCK"
-  , "REPORT"
-  , "MKACTIVITY"
-  , "CHECKOUT"
-  , "MERGE"
-  , "M-SEARCH"
-  , "NOTIFY"
-  , "SUBSCRIBE"
-  , "UNSUBSCRIBE"
-  };
-
-
-/* Tokens as defined by rfc 2616. Also lowercases them.
- *        token       = 1*<any CHAR except CTLs or separators>
- *     separators     = "(" | ")" | "<" | ">" | "@"
- *                    | "," | ";" | ":" | "\" | <">
- *                    | "/" | "[" | "]" | "?" | "="
- *                    | "{" | "}" | SP | HT
- */
-static const char tokens[256] = {
-/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */
-       ' ',      '!',     '"',     '#',     '$',     '%',     '&',    '\'',
-/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */
-        0,       0,      '*',     '+',      0,      '-',     '.',     '/',
-/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */
-       '0',     '1',     '2',     '3',     '4',     '5',     '6',     '7',
-/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */
-       '8',     '9',      0,       0,       0,       0,       0,       0,
-/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */
-        0,      'a',     'b',     'c',     'd',     'e',     'f',     'g',
-/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */
-       'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',
-/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */
-       'p',     'q',     'r',     's',     't',     'u',     'v',     'w',
-/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */
-       'x',     'y',     'z',      0,       0,       0,      '^',     '_',
-/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */
-       '`',     'a',     'b',     'c',     'd',     'e',     'f',     'g',
-/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */
-       'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',
-/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */
-       'p',     'q',     'r',     's',     't',     'u',     'v',     'w',
-/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */
-       'x',     'y',     'z',      0,      '|',     '}',     '~',       0 };
-
-
-static const int8_t unhex[256] =
-  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
-  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
-  };
-
-
-static const uint8_t normal_url_char[256] = {
-/*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */
-        0,       0,       0,       0,       0,       0,       0,       0,
-/*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */
-        0,       1,       1,       0,       1,       1,       1,       1,
-/*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */
-        1,       1,       1,       1,       1,       1,       1,       0,
-/*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */
-        1,       1,       1,       1,       1,       1,       1,       1,
-/* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */
-        1,       1,       1,       1,       1,       1,       1,       0,
-
-/* Remainder of non-ASCII range are accepted as-is to support implicitly UTF-8
-   encoded paths. This is out of spec, but clients generate this and most other
-   HTTP servers support it. We should, too. */
-
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1,
-        1,       1,       1,       1,       1,       1,       1,       1 };
-
-
-enum state
-  { s_dead = 1 /* important that this is > 0 */
-
-  , s_start_req_or_res
-  , s_res_or_resp_H
-  , s_start_res
-  , s_res_H
-  , s_res_HT
-  , s_res_HTT
-  , s_res_HTTP
-  , s_res_first_http_major
-  , s_res_http_major
-  , s_res_first_http_minor
-  , s_res_http_minor
-  , s_res_first_status_code
-  , s_res_status_code
-  , s_res_status
-  , s_res_line_almost_done
-
-  , s_start_req
-
-  , s_req_method
-  , s_req_spaces_before_url
-  , s_req_schema
-  , s_req_schema_slash
-  , s_req_schema_slash_slash
-  , s_req_host
-  , s_req_port
-  , s_req_path
-  , s_req_query_string_start
-  , s_req_query_string
-  , s_req_fragment_start
-  , s_req_fragment
-  , s_req_http_start
-  , s_req_http_H
-  , s_req_http_HT
-  , s_req_http_HTT
-  , s_req_http_HTTP
-  , s_req_first_http_major
-  , s_req_http_major
-  , s_req_first_http_minor
-  , s_req_http_minor
-  , s_req_line_almost_done
-
-  , s_header_field_start
-  , s_header_field
-  , s_header_value_start
-  , s_header_value
-
-  , s_header_almost_done
-
-  , s_chunk_size_start
-  , s_chunk_size
-  , s_chunk_parameters
-  , s_chunk_size_almost_done
-  
-  , s_headers_almost_done
-  /* Important: 's_headers_almost_done' must be the last 'header' state. All
-   * states beyond this must be 'body' states. It is used for overflow
-   * checking. See the PARSING_HEADER() macro.
-   */
-
-  , s_chunk_data
-  , s_chunk_data_almost_done
-  , s_chunk_data_done
-
-  , s_body_identity
-  , s_body_identity_eof
-  };
-
-
-#define PARSING_HEADER(state) (state <= s_headers_almost_done)
-
-
-enum header_states
-  { h_general = 0
-  , h_C
-  , h_CO
-  , h_CON
-
-  , h_matching_connection
-  , h_matching_proxy_connection
-  , h_matching_content_length
-  , h_matching_transfer_encoding
-  , h_matching_upgrade
-
-  , h_connection
-  , h_content_length
-  , h_transfer_encoding
-  , h_upgrade
-
-  , h_matching_transfer_encoding_chunked
-  , h_matching_connection_keep_alive
-  , h_matching_connection_close
-
-  , h_transfer_encoding_chunked
-  , h_connection_keep_alive
-  , h_connection_close
-  };
-
-
-enum flags
-  { F_CHUNKED               = 1 << 0
-  , F_CONNECTION_KEEP_ALIVE = 1 << 1
-  , F_CONNECTION_CLOSE      = 1 << 2
-  , F_TRAILING              = 1 << 3
-  , F_UPGRADE               = 1 << 4
-  , F_SKIPBODY              = 1 << 5
-  };
-
-
-#define CR '\r'
-#define LF '\n'
-#define LOWER(c) (unsigned char)(c | 0x20)
-#define TOKEN(c) tokens[(unsigned char)c]
-
-
-#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
-
-
-#if HTTP_PARSER_STRICT
-# define STRICT_CHECK(cond) if (cond) goto error
-# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
-#else
-# define STRICT_CHECK(cond)
-# define NEW_MESSAGE() start_state
-#endif
-
-
-size_t http_parser_execute (http_parser *parser,
-                            const http_parser_settings *settings,
-                            const char *data,
-                            size_t len)
-{
-  char c, ch;
-  const char *p = data, *pe;
-  int64_t to_read;
-
-  enum state state = (enum state) parser->state;
-  enum header_states header_state = (enum header_states) parser->header_state;
-  uint64_t index = parser->index;
-  uint64_t nread = parser->nread;
-
-  if (len == 0) {
-    switch (state) {
-      case s_body_identity_eof:
-        CALLBACK2(message_complete);
-        return 0;
-
-      case s_dead:
-      case s_start_req_or_res:
-      case s_start_res:
-      case s_start_req:
-        return 0;
-
-      default:
-        return 1; // error
-    }
-  }
-
-  /* technically we could combine all of these (except for url_mark) into one
-     variable, saving stack space, but it seems more clear to have them
-     separated. */
-  const char *header_field_mark = 0;
-  const char *header_value_mark = 0;
-  const char *fragment_mark = 0;
-  const char *query_string_mark = 0;
-  const char *path_mark = 0;
-  const char *url_mark = 0;
-
-  if (state == s_header_field)
-    header_field_mark = data;
-  if (state == s_header_value)
-    header_value_mark = data;
-  if (state == s_req_fragment)
-    fragment_mark = data;
-  if (state == s_req_query_string)
-    query_string_mark = data;
-  if (state == s_req_path)
-    path_mark = data;
-  if (state == s_req_path || state == s_req_schema || state == s_req_schema_slash
-      || state == s_req_schema_slash_slash || state == s_req_port
-      || state == s_req_query_string_start || state == s_req_query_string
-      || state == s_req_host
-      || state == s_req_fragment_start || state == s_req_fragment)
-    url_mark = data;
-
-  for (p=data, pe=data+len; p != pe; p++) {
-    ch = *p;
-
-    if (PARSING_HEADER(state)) {
-      ++nread;
-      /* Buffer overflow attack */
-      if (nread > HTTP_MAX_HEADER_SIZE) goto error;
-    }
-
-    switch (state) {
-
-      case s_dead:
-        /* this state is used after a 'Connection: close' message
-         * the parser will error out if it reads another message
-         */
-        goto error;
-
-      case s_start_req_or_res:
-      {
-        if (ch == CR || ch == LF)
-          break;
-        parser->flags = 0;
-        parser->content_length = -1;
-
-        CALLBACK2(message_begin);
-
-        if (ch == 'H')
-          state = s_res_or_resp_H;
-        else {
-          parser->type = HTTP_REQUEST;
-          goto start_req_method_assign;
-        }
-        break;
-      }
-
-      case s_res_or_resp_H:
-        if (ch == 'T') {
-          parser->type = HTTP_RESPONSE;
-          state = s_res_HT;
-        } else {
-          if (ch != 'E') goto error;
-          parser->type = HTTP_REQUEST;
-          parser->method = HTTP_HEAD;
-          index = 2;
-          state = s_req_method;
-        }
-        break;
-
-      case s_start_res:
-      {
-        parser->flags = 0;
-        parser->content_length = -1;
-
-        CALLBACK2(message_begin);
-
-        switch (ch) {
-          case 'H':
-            state = s_res_H;
-            break;
-
-          case CR:
-          case LF:
-            break;
-
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_res_H:
-        STRICT_CHECK(ch != 'T');
-        state = s_res_HT;
-        break;
-
-      case s_res_HT:
-        STRICT_CHECK(ch != 'T');
-        state = s_res_HTT;
-        break;
-
-      case s_res_HTT:
-        STRICT_CHECK(ch != 'P');
-        state = s_res_HTTP;
-        break;
-
-      case s_res_HTTP:
-        STRICT_CHECK(ch != '/');
-        state = s_res_first_http_major;
-        break;
-
-      case s_res_first_http_major:
-        if (ch < '1' || ch > '9') goto error;
-        parser->http_major = ch - '0';
-        state = s_res_http_major;
-        break;
-
-      /* major HTTP version or dot */
-      case s_res_http_major:
-      {
-        if (ch == '.') {
-          state = s_res_first_http_minor;
-          break;
-        }
-
-        if (ch < '0' || ch > '9') goto error;
-
-        parser->http_major *= 10;
-        parser->http_major += ch - '0';
-
-        if (parser->http_major > 999) goto error;
-        break;
-      }
-
-      /* first digit of minor HTTP version */
-      case s_res_first_http_minor:
-        if (ch < '0' || ch > '9') goto error;
-        parser->http_minor = ch - '0';
-        state = s_res_http_minor;
-        break;
-
-      /* minor HTTP version or end of request line */
-      case s_res_http_minor:
-      {
-        if (ch == ' ') {
-          state = s_res_first_status_code;
-          break;
-        }
-
-        if (ch < '0' || ch > '9') goto error;
-
-        parser->http_minor *= 10;
-        parser->http_minor += ch - '0';
-
-        if (parser->http_minor > 999) goto error;
-        break;
-      }
-
-      case s_res_first_status_code:
-      {
-        if (ch < '0' || ch > '9') {
-          if (ch == ' ') {
-            break;
-          }
-          goto error;
-        }
-        parser->status_code = ch - '0';
-        state = s_res_status_code;
-        break;
-      }
-
-      case s_res_status_code:
-      {
-        if (ch < '0' || ch > '9') {
-          switch (ch) {
-            case ' ':
-              state = s_res_status;
-              break;
-            case CR:
-              state = s_res_line_almost_done;
-              break;
-            case LF:
-              state = s_header_field_start;
-              break;
-            default:
-              goto error;
-          }
-          break;
-        }
-
-        parser->status_code *= 10;
-        parser->status_code += ch - '0';
-
-        if (parser->status_code > 999) goto error;
-        break;
-      }
-
-      case s_res_status:
-        /* the human readable status. e.g. "NOT FOUND"
-         * we are not humans so just ignore this */
-        if (ch == CR) {
-          state = s_res_line_almost_done;
-          break;
-        }
-
-        if (ch == LF) {
-          state = s_header_field_start;
-          break;
-        }
-        break;
-
-      case s_res_line_almost_done:
-        STRICT_CHECK(ch != LF);
-        state = s_header_field_start;
-        break;
-
-      case s_start_req:
-      {
-        if (ch == CR || ch == LF)
-          break;
-        parser->flags = 0;
-        parser->content_length = -1;
-
-        CALLBACK2(message_begin);
-
-        if (ch < 'A' || 'Z' < ch) goto error;
-
-      start_req_method_assign:
-        parser->method = (enum http_method) 0;
-        index = 1;
-        switch (ch) {
-          case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;
-          case 'D': parser->method = HTTP_DELETE; break;
-          case 'G': parser->method = HTTP_GET; break;
-          case 'H': parser->method = HTTP_HEAD; break;
-          case 'L': parser->method = HTTP_LOCK; break;
-          case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH */ break;
-          case 'N': parser->method = HTTP_NOTIFY; break;
-          case 'O': parser->method = HTTP_OPTIONS; break;
-          case 'P': parser->method = HTTP_POST; /* or PROPFIND or PROPPATCH or PUT */ break;
-          case 'R': parser->method = HTTP_REPORT; break;
-          case 'S': parser->method = HTTP_SUBSCRIBE; break;
-          case 'T': parser->method = HTTP_TRACE; break;
-          case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE */ break;
-          default: goto error;
-        }
-        state = s_req_method;
-        break;
-      }
-
-      case s_req_method:
-      {
-        if (ch == '\0')
-          goto error;
-
-        const char *matcher = method_strings[parser->method];
-        if (ch == ' ' && matcher[index] == '\0') {
-          state = s_req_spaces_before_url;
-        } else if (ch == matcher[index]) {
-          ; /* nada */
-        } else if (parser->method == HTTP_CONNECT) {
-          if (index == 1 && ch == 'H') {
-            parser->method = HTTP_CHECKOUT;
-          } else if (index == 2  && ch == 'P') {
-            parser->method = HTTP_COPY;
-          }
-        } else if (parser->method == HTTP_MKCOL) {
-          if (index == 1 && ch == 'O') {
-            parser->method = HTTP_MOVE;
-          } else if (index == 1 && ch == 'E') {
-            parser->method = HTTP_MERGE;
-          } else if (index == 1 && ch == '-') {
-            parser->method = HTTP_MSEARCH;
-          } else if (index == 2 && ch == 'A') {
-            parser->method = HTTP_MKACTIVITY;
-          }
-        } else if (index == 1 && parser->method == HTTP_POST && ch == 'R') {
-          parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */
-        } else if (index == 1 && parser->method == HTTP_POST && ch == 'U') {
-          parser->method = HTTP_PUT;
-        } else if (index == 2 && parser->method == HTTP_UNLOCK && ch == 'S') {
-          parser->method = HTTP_UNSUBSCRIBE;
-        } else if (index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') {
-          parser->method = HTTP_PROPPATCH;
-        } else {
-          goto error;
-        }
-
-        ++index;
-        break;
-      }
-      case s_req_spaces_before_url:
-      {
-        if (ch == ' ') break;
-
-        if (ch == '/' || ch == '*') {
-          MARK(url);
-          MARK(path);
-          state = s_req_path;
-          break;
-        }
-
-        c = LOWER(ch);
-
-        if (c >= 'a' && c <= 'z') {
-          MARK(url);
-          state = s_req_schema;
-          break;
-        }
-
-        goto error;
-      }
-
-      case s_req_schema:
-      {
-        c = LOWER(ch);
-
-        if (c >= 'a' && c <= 'z') break;
-
-        if (ch == ':') {
-          state = s_req_schema_slash;
-          break;
-        } else if (ch == '.') {
-          state = s_req_host;
-          break;
-        } else if ('0' <= ch && ch <= '9') {
-          state = s_req_host;
-          break;
-        }
-
-        goto error;
-      }
-
-      case s_req_schema_slash:
-        STRICT_CHECK(ch != '/');
-        state = s_req_schema_slash_slash;
-        break;
-
-      case s_req_schema_slash_slash:
-        STRICT_CHECK(ch != '/');
-        state = s_req_host;
-        break;
-
-      case s_req_host:
-      {
-        c = LOWER(ch);
-        if (c >= 'a' && c <= 'z') break;
-        if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') break;
-        switch (ch) {
-          case ':':
-            state = s_req_port;
-            break;
-          case '/':
-            MARK(path);
-            state = s_req_path;
-            break;
-          case ' ':
-            /* The request line looks like:
-             *   "GET http://foo.bar.com HTTP/1.1"
-             * That is, there is no path.
-             */
-            CALLBACK(url);
-            state = s_req_http_start;
-            break;
-          case '?':
-            state = s_req_query_string_start;
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_port:
-      {
-        if (ch >= '0' && ch <= '9') break;
-        switch (ch) {
-          case '/':
-            MARK(path);
-            state = s_req_path;
-            break;
-          case ' ':
-            /* The request line looks like:
-             *   "GET http://foo.bar.com:1234 HTTP/1.1"
-             * That is, there is no path.
-             */
-            CALLBACK(url);
-            state = s_req_http_start;
-            break;
-          case '?':
-            state = s_req_query_string_start;
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_path:
-      {
-        if (normal_url_char[(unsigned char)ch]) break;
-
-        switch (ch) {
-          case ' ':
-            CALLBACK(url);
-            CALLBACK(path);
-            state = s_req_http_start;
-            break;
-          case CR:
-            CALLBACK(url);
-            CALLBACK(path);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_req_line_almost_done;
-            break;
-          case LF:
-            CALLBACK(url);
-            CALLBACK(path);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_header_field_start;
-            break;
-          case '?':
-            CALLBACK(path);
-            state = s_req_query_string_start;
-            break;
-          case '#':
-            CALLBACK(path);
-            state = s_req_fragment_start;
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_query_string_start:
-      {
-        if (normal_url_char[(unsigned char)ch]) {
-          MARK(query_string);
-          state = s_req_query_string;
-          break;
-        }
-
-        switch (ch) {
-          case '?':
-            break; /* XXX ignore extra '?' ... is this right? */
-          case ' ':
-            CALLBACK(url);
-            state = s_req_http_start;
-            break;
-          case CR:
-            CALLBACK(url);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_req_line_almost_done;
-            break;
-          case LF:
-            CALLBACK(url);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_header_field_start;
-            break;
-          case '#':
-            state = s_req_fragment_start;
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_query_string:
-      {
-        if (normal_url_char[(unsigned char)ch]) break;
-
-        switch (ch) {
-          case '?':
-            /* allow extra '?' in query string */
-            break;
-          case ' ':
-            CALLBACK(url);
-            CALLBACK(query_string);
-            state = s_req_http_start;
-            break;
-          case CR:
-            CALLBACK(url);
-            CALLBACK(query_string);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_req_line_almost_done;
-            break;
-          case LF:
-            CALLBACK(url);
-            CALLBACK(query_string);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_header_field_start;
-            break;
-          case '#':
-            CALLBACK(query_string);
-            state = s_req_fragment_start;
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_fragment_start:
-      {
-        if (normal_url_char[(unsigned char)ch]) {
-          MARK(fragment);
-          state = s_req_fragment;
-          break;
-        }
-
-        switch (ch) {
-          case ' ':
-            CALLBACK(url);
-            state = s_req_http_start;
-            break;
-          case CR:
-            CALLBACK(url);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_req_line_almost_done;
-            break;
-          case LF:
-            CALLBACK(url);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_header_field_start;
-            break;
-          case '?':
-            MARK(fragment);
-            state = s_req_fragment;
-            break;
-          case '#':
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_fragment:
-      {
-        if (normal_url_char[(unsigned char)ch]) break;
-
-        switch (ch) {
-          case ' ':
-            CALLBACK(url);
-            CALLBACK(fragment);
-            state = s_req_http_start;
-            break;
-          case CR:
-            CALLBACK(url);
-            CALLBACK(fragment);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_req_line_almost_done;
-            break;
-          case LF:
-            CALLBACK(url);
-            CALLBACK(fragment);
-            parser->http_major = 0;
-            parser->http_minor = 9;
-            state = s_header_field_start;
-            break;
-          case '?':
-          case '#':
-            break;
-          default:
-            goto error;
-        }
-        break;
-      }
-
-      case s_req_http_start:
-        switch (ch) {
-          case 'H':
-            state = s_req_http_H;
-            break;
-          case ' ':
-            break;
-          default:
-            goto error;
-        }
-        break;
-
-      case s_req_http_H:
-        STRICT_CHECK(ch != 'T');
-        state = s_req_http_HT;
-        break;
-
-      case s_req_http_HT:
-        STRICT_CHECK(ch != 'T');
-        state = s_req_http_HTT;
-        break;
-
-      case s_req_http_HTT:
-        STRICT_CHECK(ch != 'P');
-        state = s_req_http_HTTP;
-        break;
-
-      case s_req_http_HTTP:
-        STRICT_CHECK(ch != '/');
-        state = s_req_first_http_major;
-        break;
-
-      /* first digit of major HTTP version */
-      case s_req_first_http_major:
-        if (ch < '1' || ch > '9') goto error;
-        parser->http_major = ch - '0';
-        state = s_req_http_major;
-        break;
-
-      /* major HTTP version or dot */
-      case s_req_http_major:
-      {
-        if (ch == '.') {
-          state = s_req_first_http_minor;
-          break;
-        }
-
-        if (ch < '0' || ch > '9') goto error;
-
-        parser->http_major *= 10;
-        parser->http_major += ch - '0';
-
-        if (parser->http_major > 999) goto error;
-        break;
-      }
-
-      /* first digit of minor HTTP version */
-      case s_req_first_http_minor:
-        if (ch < '0' || ch > '9') goto error;
-        parser->http_minor = ch - '0';
-        state = s_req_http_minor;
-        break;
-
-      /* minor HTTP version or end of request line */
-      case s_req_http_minor:
-      {
-        if (ch == CR) {
-          state = s_req_line_almost_done;
-          break;
-        }
-
-        if (ch == LF) {
-          state = s_header_field_start;
-          break;
-        }
-
-        /* XXX allow spaces after digit? */
-
-        if (ch < '0' || ch > '9') goto error;
-
-        parser->http_minor *= 10;
-        parser->http_minor += ch - '0';
-
-        if (parser->http_minor > 999) goto error;
-        break;
-      }
-
-      /* end of request line */
-      case s_req_line_almost_done:
-      {
-        if (ch != LF) goto error;
-        state = s_header_field_start;
-        break;
-      }
-
-      case s_header_field_start:
-      {
-        if (ch == CR) {
-          state = s_headers_almost_done;
-          break;
-        }
-
-        if (ch == LF) {
-          /* they might be just sending \n instead of \r\n so this would be
-           * the second \n to denote the end of headers*/
-          state = s_headers_almost_done;
-          goto headers_almost_done;
-        }
-
-        c = TOKEN(ch);
-
-        if (!c) goto error;
-
-        MARK(header_field);
-
-        index = 0;
-        state = s_header_field;
-
-        switch (c) {
-          case 'c':
-            header_state = h_C;
-            break;
-
-          case 'p':
-            header_state = h_matching_proxy_connection;
-            break;
-
-          case 't':
-            header_state = h_matching_transfer_encoding;
-            break;
-
-          case 'u':
-            header_state = h_matching_upgrade;
-            break;
-
-          default:
-            header_state = h_general;
-            break;
-        }
-        break;
-      }
-
-      case s_header_field:
-      {
-        c = TOKEN(ch);
-
-        if (c) {
-          switch (header_state) {
-            case h_general:
-              break;
-
-            case h_C:
-              index++;
-              header_state = (c == 'o' ? h_CO : h_general);
-              break;
-
-            case h_CO:
-              index++;
-              header_state = (c == 'n' ? h_CON : h_general);
-              break;
-
-            case h_CON:
-              index++;
-              switch (c) {
-                case 'n':
-                  header_state = h_matching_connection;
-                  break;
-                case 't':
-                  header_state = h_matching_content_length;
-                  break;
-                default:
-                  header_state = h_general;
-                  break;
-              }
-              break;
-
-            /* connection */
-
-            case h_matching_connection:
-              index++;
-              if (index > sizeof(CONNECTION)-1
-                  || c != CONNECTION[index]) {
-                header_state = h_general;
-              } else if (index == sizeof(CONNECTION)-2) {
-                header_state = h_connection;
-              }
-              break;
-
-            /* proxy-connection */
-
-            case h_matching_proxy_connection:
-              index++;
-              if (index > sizeof(PROXY_CONNECTION)-1
-                  || c != PROXY_CONNECTION[index]) {
-                header_state = h_general;
-              } else if (index == sizeof(PROXY_CONNECTION)-2) {
-                header_state = h_connection;
-              }
-              break;
-
-            /* content-length */
-
-            case h_matching_content_length:
-              index++;
-              if (index > sizeof(CONTENT_LENGTH)-1
-                  || c != CONTENT_LENGTH[index]) {
-                header_state = h_general;
-              } else if (index == sizeof(CONTENT_LENGTH)-2) {
-                header_state = h_content_length;
-              }
-              break;
-
-            /* transfer-encoding */
-
-            case h_matching_transfer_encoding:
-              index++;
-              if (index > sizeof(TRANSFER_ENCODING)-1
-                  || c != TRANSFER_ENCODING[index]) {
-                header_state = h_general;
-              } else if (index == sizeof(TRANSFER_ENCODING)-2) {
-                header_state = h_transfer_encoding;
-              }
-              break;
-
-            /* upgrade */
-
-            case h_matching_upgrade:
-              index++;
-              if (index > sizeof(UPGRADE)-1
-                  || c != UPGRADE[index]) {
-                header_state = h_general;
-              } else if (index == sizeof(UPGRADE)-2) {
-                header_state = h_upgrade;
-              }
-              break;
-
-            case h_connection:
-            case h_content_length:
-            case h_transfer_encoding:
-            case h_upgrade:
-              if (ch != ' ') header_state = h_general;
-              break;
-
-            default:
-              assert(0 && "Unknown header_state");
-              break;
-          }
-          break;
-        }
-
-        if (ch == ':') {
-          CALLBACK(header_field);
-          state = s_header_value_start;
-          break;
-        }
-
-        if (ch == CR) {
-          state = s_header_almost_done;
-          CALLBACK(header_field);
-          break;
-        }
-
-        if (ch == LF) {
-          CALLBACK(header_field);
-          state = s_header_field_start;
-          break;
-        }
-
-        goto error;
-      }
-
-      case s_header_value_start:
-      {
-        if (ch == ' ') break;
-
-        MARK(header_value);
-
-        state = s_header_value;
-        index = 0;
-
-        c = LOWER(ch);
-
-        if (ch == CR) {
-          CALLBACK(header_value);
-          header_state = h_general;
-          state = s_header_almost_done;
-          break;
-        }
-
-        if (ch == LF) {
-          CALLBACK(header_value);
-          state = s_header_field_start;
-          break;
-        }
-
-        switch (header_state) {
-          case h_upgrade:
-            parser->flags |= F_UPGRADE;
-            header_state = h_general;
-            break;
-
-          case h_transfer_encoding:
-            /* looking for 'Transfer-Encoding: chunked' */
-            if ('c' == c) {
-              header_state = h_matching_transfer_encoding_chunked;
-            } else {
-              header_state = h_general;
-            }
-            break;
-
-          case h_content_length:
-            if (ch < '0' || ch > '9') goto error;
-            parser->content_length = ch - '0';
-            break;
-
-          case h_connection:
-            /* looking for 'Connection: keep-alive' */
-            if (c == 'k') {
-              header_state = h_matching_connection_keep_alive;
-            /* looking for 'Connection: close' */
-            } else if (c == 'c') {
-              header_state = h_matching_connection_close;
-            } else {
-              header_state = h_general;
-            }
-            break;
-
-          default:
-            header_state = h_general;
-            break;
-        }
-        break;
-      }
-
-      case s_header_value:
-      {
-        c = LOWER(ch);
-
-        if (ch == CR) {
-          CALLBACK(header_value);
-          state = s_header_almost_done;
-          break;
-        }
-
-        if (ch == LF) {
-          CALLBACK(header_value);
-          goto header_almost_done;
-        }
-
-        switch (header_state) {
-          case h_general:
-            break;
-
-          case h_connection:
-          case h_transfer_encoding:
-            assert(0 && "Shouldn't get here.");
-            break;
-
-          case h_content_length:
-            if (ch == ' ') break;
-            if (ch < '0' || ch > '9') goto error;
-            parser->content_length *= 10;
-            parser->content_length += ch - '0';
-            break;
-
-          /* Transfer-Encoding: chunked */
-          case h_matching_transfer_encoding_chunked:
-            index++;
-            if (index > sizeof(CHUNKED)-1
-                || c != CHUNKED[index]) {
-              header_state = h_general;
-            } else if (index == sizeof(CHUNKED)-2) {
-              header_state = h_transfer_encoding_chunked;
-            }
-            break;
-
-          /* looking for 'Connection: keep-alive' */
-          case h_matching_connection_keep_alive:
-            index++;
-            if (index > sizeof(KEEP_ALIVE)-1
-                || c != KEEP_ALIVE[index]) {
-              header_state = h_general;
-            } else if (index == sizeof(KEEP_ALIVE)-2) {
-              header_state = h_connection_keep_alive;
-            }
-            break;
-
-          /* looking for 'Connection: close' */
-          case h_matching_connection_close:
-            index++;
-            if (index > sizeof(CLOSE)-1 || c != CLOSE[index]) {
-              header_state = h_general;
-            } else if (index == sizeof(CLOSE)-2) {
-              header_state = h_connection_close;
-            }
-            break;
-
-          case h_transfer_encoding_chunked:
-          case h_connection_keep_alive:
-          case h_connection_close:
-            if (ch != ' ') header_state = h_general;
-            break;
-
-          default:
-            state = s_header_value;
-            header_state = h_general;
-            break;
-        }
-        break;
-      }
-
-      case s_header_almost_done:
-      header_almost_done:
-      {
-        STRICT_CHECK(ch != LF);
-
-        state = s_header_field_start;
-
-        switch (header_state) {
-          case h_connection_keep_alive:
-            parser->flags |= F_CONNECTION_KEEP_ALIVE;
-            break;
-          case h_connection_close:
-            parser->flags |= F_CONNECTION_CLOSE;
-            break;
-          case h_transfer_encoding_chunked:
-            parser->flags |= F_CHUNKED;
-            break;
-          default:
-            break;
-        }
-        break;
-      }
-
-      case s_headers_almost_done:
-      headers_almost_done:
-      {
-        STRICT_CHECK(ch != LF);
-
-        if (parser->flags & F_TRAILING) {
-          /* End of a chunked request */
-          CALLBACK2(message_complete);
-          state = NEW_MESSAGE();
-          break;
-        }
-
-        nread = 0;
-
-        if (parser->flags & F_UPGRADE || parser->method == HTTP_CONNECT) {
-          parser->upgrade = 1;
-        }
-
-        /* Here we call the headers_complete callback. This is somewhat
-         * different than other callbacks because if the user returns 1, we
-         * will interpret that as saying that this message has no body. This
-         * is needed for the annoying case of recieving a response to a HEAD
-         * request.
-         */
-        if (settings->on_headers_complete) {
-          switch (settings->on_headers_complete(parser)) {
-            case 0:
-              break;
-
-            case 1:
-              parser->flags |= F_SKIPBODY;
-              break;
-
-            default:
-              parser->state = state;
-              return p - data; /* Error */
-          }
-        }
-
-        /* Exit, the rest of the connect is in a different protocol. */
-        if (parser->upgrade) {
-          CALLBACK2(message_complete);
-          return (p - data);
-        }
-
-        if (parser->flags & F_SKIPBODY) {
-          CALLBACK2(message_complete);
-          state = NEW_MESSAGE();
-        } else if (parser->flags & F_CHUNKED) {
-          /* chunked encoding - ignore Content-Length header */
-          state = s_chunk_size_start;
-        } else {
-          if (parser->content_length == 0) {
-            /* Content-Length header given but zero: Content-Length: 0\r\n */
-            CALLBACK2(message_complete);
-            state = NEW_MESSAGE();
-          } else if (parser->content_length > 0) {
-            /* Content-Length header given and non-zero */
-            state = s_body_identity;
-          } else {
-            if (parser->type == HTTP_REQUEST || http_should_keep_alive(parser)) {
-              /* Assume content-length 0 - read the next */
-              CALLBACK2(message_complete);
-              state = NEW_MESSAGE();
-            } else {
-              /* Read body until EOF */
-              state = s_body_identity_eof;
-            }
-          }
-        }
-
-        break;
-      }
-
-      case s_body_identity:
-        to_read = MIN(pe - p, (int64_t)parser->content_length);
-        if (to_read > 0) {
-          if (settings->on_body) settings->on_body(parser, p, to_read);
-          p += to_read - 1;
-          parser->content_length -= to_read;
-          if (parser->content_length == 0) {
-            CALLBACK2(message_complete);
-            state = NEW_MESSAGE();
-          }
-        }
-        break;
-
-      /* read until EOF */
-      case s_body_identity_eof:
-        to_read = pe - p;
-        if (to_read > 0) {
-          if (settings->on_body) settings->on_body(parser, p, to_read);
-          p += to_read - 1;
-        }
-        break;
-
-      case s_chunk_size_start:
-      {
-        assert(nread == 1);
-        assert(parser->flags & F_CHUNKED);
-
-        c = unhex[(unsigned char)ch];
-        if (c == -1) goto error;
-        parser->content_length = c;
-        state = s_chunk_size;
-        break;
-      }
-
-      case s_chunk_size:
-      {
-        assert(parser->flags & F_CHUNKED);
-
-        if (ch == CR) {
-          state = s_chunk_size_almost_done;
-          break;
-        }
-
-        c = unhex[(unsigned char)ch];
-
-        if (c == -1) {
-          if (ch == ';' || ch == ' ') {
-            state = s_chunk_parameters;
-            break;
-          }
-          goto error;
-        }
-
-        parser->content_length *= 16;
-        parser->content_length += c;
-        break;
-      }
-
-      case s_chunk_parameters:
-      {
-        assert(parser->flags & F_CHUNKED);
-        /* just ignore this shit. TODO check for overflow */
-        if (ch == CR) {
-          state = s_chunk_size_almost_done;
-          break;
-        }
-        break;
-      }
-
-      case s_chunk_size_almost_done:
-      {
-        assert(parser->flags & F_CHUNKED);
-        STRICT_CHECK(ch != LF);
-
-        nread = 0;
-
-        if (parser->content_length == 0) {
-          parser->flags |= F_TRAILING;
-          state = s_header_field_start;
-        } else {
-          state = s_chunk_data;
-        }
-        break;
-      }
-
-      case s_chunk_data:
-      {
-        assert(parser->flags & F_CHUNKED);
-
-        to_read = MIN(pe - p, (int64_t)(parser->content_length));
-
-        if (to_read > 0) {
-          if (settings->on_body) settings->on_body(parser, p, to_read);
-          p += to_read - 1;
-        }
-
-        if (to_read == parser->content_length) {
-          state = s_chunk_data_almost_done;
-        }
-
-        parser->content_length -= to_read;
-        break;
-      }
-
-      case s_chunk_data_almost_done:
-        assert(parser->flags & F_CHUNKED);
-        STRICT_CHECK(ch != CR);
-        state = s_chunk_data_done;
-        break;
-
-      case s_chunk_data_done:
-        assert(parser->flags & F_CHUNKED);
-        STRICT_CHECK(ch != LF);
-        state = s_chunk_size_start;
-        break;
-
-      default:
-        assert(0 && "unhandled state");
-        goto error;
-    }
-  }
-
-  CALLBACK_NOCLEAR(header_field);
-  CALLBACK_NOCLEAR(header_value);
-  CALLBACK_NOCLEAR(fragment);
-  CALLBACK_NOCLEAR(query_string);
-  CALLBACK_NOCLEAR(path);
-  CALLBACK_NOCLEAR(url);
-
-  parser->state = state;
-  parser->header_state = header_state;
-  parser->index = index;
-  parser->nread = nread;
-
-  return len;
-
-error:
-  parser->state = s_dead;
-  return (p - data);
-}
-
-
-int
-http_should_keep_alive (http_parser *parser)
-{
-  if (parser->http_major > 0 && parser->http_minor > 0) {
-    /* HTTP/1.1 */
-    if (parser->flags & F_CONNECTION_CLOSE) {
-      return 0;
-    } else {
-      return 1;
-    }
-  } else {
-    /* HTTP/1.0 or earlier */
-    if (parser->flags & F_CONNECTION_KEEP_ALIVE) {
-      return 1;
-    } else {
-      return 0;
-    }
-  }
-}
-
-
-const char * http_method_str (enum http_method m)
-{
-  return method_strings[m];
-}
-
-
-void
-http_parser_init (http_parser *parser, enum http_parser_type t)
-{
-  parser->type = t;
-  parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
-  parser->nread = 0;
-  parser->upgrade = 0;
-  parser->flags = 0;
-  parser->method = 0;
-}
diff --git a/ext/ruby_http_parser/vendor/http-parser/http_parser.h b/ext/ruby_http_parser/vendor/http-parser/http_parser.h
deleted file mode 100644
index 9c7a26d..0000000
--- a/ext/ruby_http_parser/vendor/http-parser/http_parser.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#ifndef http_parser_h
-#define http_parser_h
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define HTTP_PARSER_VERSION_MAJOR 1
-#define HTTP_PARSER_VERSION_MINOR 0
-
-#include <sys/types.h>
-#if defined(_WIN32) && !defined(__MINGW32__)
-typedef __int8 int8_t;
-typedef unsigned __int8 uint8_t;
-typedef __int16 int16_t;
-typedef unsigned __int16 uint16_t;
-typedef __int32 int32_t;
-typedef unsigned __int32 uint32_t;
-typedef __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-
-typedef unsigned int size_t;
-typedef int ssize_t;
-#else
-#include <stdint.h>
-#endif
-
-/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
- * faster
- */
-#ifndef HTTP_PARSER_STRICT
-# define HTTP_PARSER_STRICT 1
-#else
-# define HTTP_PARSER_STRICT 0
-#endif
-
-
-/* Maximium header size allowed */
-#define HTTP_MAX_HEADER_SIZE (80*1024)
-
-
-typedef struct http_parser http_parser;
-typedef struct http_parser_settings http_parser_settings;
-
-
-/* Callbacks should return non-zero to indicate an error. The parser will
- * then halt execution.
- *
- * The one exception is on_headers_complete. In a HTTP_RESPONSE parser
- * returning '1' from on_headers_complete will tell the parser that it
- * should not expect a body. This is used when receiving a response to a
- * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
- * chunked' headers that indicate the presence of a body.
- *
- * http_data_cb does not return data chunks. It will be call arbitrarally
- * many times for each string. E.G. you might get 10 callbacks for "on_path"
- * each providing just a few characters more data.
- */
-typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
-typedef int (*http_cb) (http_parser*);
-
-
-/* Request Methods */
-enum http_method
-  { HTTP_DELETE    = 0
-  , HTTP_GET
-  , HTTP_HEAD
-  , HTTP_POST
-  , HTTP_PUT
-  /* pathological */
-  , HTTP_CONNECT
-  , HTTP_OPTIONS
-  , HTTP_TRACE
-  /* webdav */
-  , HTTP_COPY
-  , HTTP_LOCK
-  , HTTP_MKCOL
-  , HTTP_MOVE
-  , HTTP_PROPFIND
-  , HTTP_PROPPATCH
-  , HTTP_UNLOCK
-  /* subversion */
-  , HTTP_REPORT
-  , HTTP_MKACTIVITY
-  , HTTP_CHECKOUT
-  , HTTP_MERGE
-  /* upnp */
-  , HTTP_MSEARCH
-  , HTTP_NOTIFY
-  , HTTP_SUBSCRIBE
-  , HTTP_UNSUBSCRIBE
-  };
-
-
-enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
-
-
-struct http_parser {
-  /** PRIVATE **/
-  unsigned char type : 2;
-  unsigned char flags : 6;
-  unsigned char state;
-  unsigned char header_state;
-  unsigned char index;
-
-  uint32_t nread;
-  int64_t content_length;
-
-  /** READ-ONLY **/
-  unsigned short http_major;
-  unsigned short http_minor;
-  unsigned short status_code; /* responses only */
-  unsigned char method;    /* requests only */
-
-  /* 1 = Upgrade header was present and the parser has exited because of that.
-   * 0 = No upgrade header present.
-   * Should be checked when http_parser_execute() returns in addition to
-   * error checking.
-   */
-  char upgrade;
-
-  /** PUBLIC **/
-  void *data; /* A pointer to get hook to the "connection" or "socket" object */
-};
-
-
-struct http_parser_settings {
-  http_cb      on_message_begin;
-  http_data_cb on_path;
-  http_data_cb on_query_string;
-  http_data_cb on_url;
-  http_data_cb on_fragment;
-  http_data_cb on_header_field;
-  http_data_cb on_header_value;
-  http_cb      on_headers_complete;
-  http_data_cb on_body;
-  http_cb      on_message_complete;
-};
-
-
-void http_parser_init(http_parser *parser, enum http_parser_type type);
-
-
-size_t http_parser_execute(http_parser *parser,
-                           const http_parser_settings *settings,
-                           const char *data,
-                           size_t len);
-
-
-/* If http_should_keep_alive() in the on_headers_complete or
- * on_message_complete callback returns true, then this will be should be
- * the last message on the connection.
- * If you are the server, respond with the "Connection: close" header.
- * If you are the client, close the connection.
- */
-int http_should_keep_alive(http_parser *parser);
-
-/* Returns a string version of the HTTP method. */
-const char *http_method_str(enum http_method);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/ext/ruby_http_parser/vendor/http-parser/test.c b/ext/ruby_http_parser/vendor/http-parser/test.c
deleted file mode 100644
index 4a93163..0000000
--- a/ext/ruby_http_parser/vendor/http-parser/test.c
+++ /dev/null
@@ -1,1952 +0,0 @@
-/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-#include "http_parser.h"
-#include <stdlib.h>
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h> /* rand */
-#include <string.h>
-#include <stdarg.h>
-
-#undef TRUE
-#define TRUE 1
-#undef FALSE
-#define FALSE 0
-
-#define MAX_HEADERS 13
-#define MAX_ELEMENT_SIZE 500
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-
-static http_parser *parser;
-
-struct message {
-  const char *name; // for debugging purposes
-  const char *raw;
-  enum http_parser_type type;
-  enum http_method method;
-  int status_code;
-  char request_path[MAX_ELEMENT_SIZE];
-  char request_url[MAX_ELEMENT_SIZE];
-  char fragment[MAX_ELEMENT_SIZE];
-  char query_string[MAX_ELEMENT_SIZE];
-  char body[MAX_ELEMENT_SIZE];
-  size_t body_size;
-  int num_headers;
-  enum { NONE=0, FIELD, VALUE } last_header_element;
-  char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE];
-  int should_keep_alive;
-
-  int upgrade;
-
-  unsigned short http_major;
-  unsigned short http_minor;
-
-  int message_begin_cb_called;
-  int headers_complete_cb_called;
-  int message_complete_cb_called;
-  int message_complete_on_eof;
-};
-
-static int currently_parsing_eof;
-
-static struct message messages[5];
-static int num_messages;
-
-/* * R E Q U E S T S * */
-const struct message requests[] =
-#define CURL_GET 0
-{ {.name= "curl get"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /test HTTP/1.1\r\n"
-         "User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n"
-         "Host: 0.0.0.0=5000\r\n"
-         "Accept: */*\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/test"
-  ,.request_url= "/test"
-  ,.num_headers= 3
-  ,.headers=
-    { { "User-Agent", "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1" }
-    , { "Host", "0.0.0.0=5000" }
-    , { "Accept", "*/*" }
-    }
-  ,.body= ""
-  }
-
-#define FIREFOX_GET 1
-, {.name= "firefox get"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /favicon.ico HTTP/1.1\r\n"
-         "Host: 0.0.0.0=5000\r\n"
-         "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n"
-         "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
-         "Accept-Language: en-us,en;q=0.5\r\n"
-         "Accept-Encoding: gzip,deflate\r\n"
-         "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"
-         "Keep-Alive: 300\r\n"
-         "Connection: keep-alive\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/favicon.ico"
-  ,.request_url= "/favicon.ico"
-  ,.num_headers= 8
-  ,.headers=
-    { { "Host", "0.0.0.0=5000" }
-    , { "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0" }
-    , { "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" }
-    , { "Accept-Language", "en-us,en;q=0.5" }
-    , { "Accept-Encoding", "gzip,deflate" }
-    , { "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7" }
-    , { "Keep-Alive", "300" }
-    , { "Connection", "keep-alive" }
-    }
-  ,.body= ""
-  }
-
-#define DUMBFUCK 2
-, {.name= "dumbfuck"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /dumbfuck HTTP/1.1\r\n"
-         "aaaaaaaaaaaaa:++++++++++\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/dumbfuck"
-  ,.request_url= "/dumbfuck"
-  ,.num_headers= 1
-  ,.headers=
-    { { "aaaaaaaaaaaaa",  "++++++++++" }
-    }
-  ,.body= ""
-  }
-
-#define FRAGMENT_IN_URI 3
-, {.name= "fragment in url"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= "page=1"
-  ,.fragment= "posts-17408"
-  ,.request_path= "/forums/1/topics/2375"
-  /* XXX request url does include fragment? */
-  ,.request_url= "/forums/1/topics/2375?page=1#posts-17408"
-  ,.num_headers= 0
-  ,.body= ""
-  }
-
-#define GET_NO_HEADERS_NO_BODY 4
-, {.name= "get no headers no body"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /get_no_headers_no_body/world HTTP/1.1\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE /* would need Connection: close */
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/get_no_headers_no_body/world"
-  ,.request_url= "/get_no_headers_no_body/world"
-  ,.num_headers= 0
-  ,.body= ""
-  }
-
-#define GET_ONE_HEADER_NO_BODY 5
-, {.name= "get one header no body"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /get_one_header_no_body HTTP/1.1\r\n"
-         "Accept: */*\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE /* would need Connection: close */
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/get_one_header_no_body"
-  ,.request_url= "/get_one_header_no_body"
-  ,.num_headers= 1
-  ,.headers=
-    { { "Accept" , "*/*" }
-    }
-  ,.body= ""
-  }
-
-#define GET_FUNKY_CONTENT_LENGTH 6
-, {.name= "get funky content length body hello"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /get_funky_content_length_body_hello HTTP/1.0\r\n"
-         "conTENT-Length: 5\r\n"
-         "\r\n"
-         "HELLO"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 0
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/get_funky_content_length_body_hello"
-  ,.request_url= "/get_funky_content_length_body_hello"
-  ,.num_headers= 1
-  ,.headers=
-    { { "conTENT-Length" , "5" }
-    }
-  ,.body= "HELLO"
-  }
-
-#define POST_IDENTITY_BODY_WORLD 7
-, {.name= "post identity body world"
-  ,.type= HTTP_REQUEST
-  ,.raw= "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n"
-         "Accept: */*\r\n"
-         "Transfer-Encoding: identity\r\n"
-         "Content-Length: 5\r\n"
-         "\r\n"
-         "World"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_POST
-  ,.query_string= "q=search"
-  ,.fragment= "hey"
-  ,.request_path= "/post_identity_body_world"
-  ,.request_url= "/post_identity_body_world?q=search#hey"
-  ,.num_headers= 3
-  ,.headers=
-    { { "Accept", "*/*" }
-    , { "Transfer-Encoding", "identity" }
-    , { "Content-Length", "5" }
-    }
-  ,.body= "World"
-  }
-
-#define POST_CHUNKED_ALL_YOUR_BASE 8
-, {.name= "post - chunked body: all your base are belong to us"
-  ,.type= HTTP_REQUEST
-  ,.raw= "POST /post_chunked_all_your_base HTTP/1.1\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "1e\r\nall your base are belong to us\r\n"
-         "0\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_POST
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/post_chunked_all_your_base"
-  ,.request_url= "/post_chunked_all_your_base"
-  ,.num_headers= 1
-  ,.headers=
-    { { "Transfer-Encoding" , "chunked" }
-    }
-  ,.body= "all your base are belong to us"
-  }
-
-#define TWO_CHUNKS_MULT_ZERO_END 9
-, {.name= "two chunks ; triple zero ending"
-  ,.type= HTTP_REQUEST
-  ,.raw= "POST /two_chunks_mult_zero_end HTTP/1.1\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "5\r\nhello\r\n"
-         "6\r\n world\r\n"
-         "000\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_POST
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/two_chunks_mult_zero_end"
-  ,.request_url= "/two_chunks_mult_zero_end"
-  ,.num_headers= 1
-  ,.headers=
-    { { "Transfer-Encoding", "chunked" }
-    }
-  ,.body= "hello world"
-  }
-
-#define CHUNKED_W_TRAILING_HEADERS 10
-, {.name= "chunked with trailing headers. blech."
-  ,.type= HTTP_REQUEST
-  ,.raw= "POST /chunked_w_trailing_headers HTTP/1.1\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "5\r\nhello\r\n"
-         "6\r\n world\r\n"
-         "0\r\n"
-         "Vary: *\r\n"
-         "Content-Type: text/plain\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_POST
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/chunked_w_trailing_headers"
-  ,.request_url= "/chunked_w_trailing_headers"
-  ,.num_headers= 3
-  ,.headers=
-    { { "Transfer-Encoding",  "chunked" }
-    , { "Vary", "*" }
-    , { "Content-Type", "text/plain" }
-    }
-  ,.body= "hello world"
-  }
-
-#define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11
-, {.name= "with bullshit after the length"
-  ,.type= HTTP_REQUEST
-  ,.raw= "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "5; ihatew3;whatthefuck=aretheseparametersfor\r\nhello\r\n"
-         "6; blahblah; blah\r\n world\r\n"
-         "0\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_POST
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/chunked_w_bullshit_after_length"
-  ,.request_url= "/chunked_w_bullshit_after_length"
-  ,.num_headers= 1
-  ,.headers=
-    { { "Transfer-Encoding", "chunked" }
-    }
-  ,.body= "hello world"
-  }
-
-#define WITH_QUOTES 12
-, {.name= "with quotes"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /with_\"stupid\"_quotes?foo=\"bar\" HTTP/1.1\r\n\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= "foo=\"bar\""
-  ,.fragment= ""
-  ,.request_path= "/with_\"stupid\"_quotes"
-  ,.request_url= "/with_\"stupid\"_quotes?foo=\"bar\""
-  ,.num_headers= 0
-  ,.headers= { }
-  ,.body= ""
-  }
-
-#define APACHEBENCH_GET 13
-/* The server receiving this request SHOULD NOT wait for EOF
- * to know that content-length == 0.
- * How to represent this in a unit test? message_complete_on_eof
- * Compare with NO_CONTENT_LENGTH_RESPONSE.
- */
-, {.name = "apachebench get"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /test HTTP/1.0\r\n"
-         "Host: 0.0.0.0:5000\r\n"
-         "User-Agent: ApacheBench/2.3\r\n"
-         "Accept: */*\r\n\r\n"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 0
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/test"
-  ,.request_url= "/test"
-  ,.num_headers= 3
-  ,.headers= { { "Host", "0.0.0.0:5000" }
-             , { "User-Agent", "ApacheBench/2.3" }
-             , { "Accept", "*/*" }
-             }
-  ,.body= ""
-  }
-
-#define QUERY_URL_WITH_QUESTION_MARK_GET 14
-/* Some clients include '?' characters in query strings.
- */
-, {.name = "query url with question mark"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /test.cgi?foo=bar?baz HTTP/1.1\r\n\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= "foo=bar?baz"
-  ,.fragment= ""
-  ,.request_path= "/test.cgi"
-  ,.request_url= "/test.cgi?foo=bar?baz"
-  ,.num_headers= 0
-  ,.headers= {}
-  ,.body= ""
-  }
-
-#define PREFIX_NEWLINE_GET 15
-/* Some clients, especially after a POST in a keep-alive connection,
- * will send an extra CRLF before the next request
- */
-, {.name = "newline prefix get"
-  ,.type= HTTP_REQUEST
-  ,.raw= "\r\nGET /test HTTP/1.1\r\n\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/test"
-  ,.request_url= "/test"
-  ,.num_headers= 0
-  ,.headers= { }
-  ,.body= ""
-  }
-
-#define UPGRADE_REQUEST 16
-, {.name = "upgrade request"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /demo HTTP/1.1\r\n"
-         "Host: example.com\r\n"
-         "Connection: Upgrade\r\n"
-         "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
-         "Sec-WebSocket-Protocol: sample\r\n"
-         "Upgrade: WebSocket\r\n"
-         "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
-         "Origin: http://example.com\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/demo"
-  ,.request_url= "/demo"
-  ,.num_headers= 7
-  ,.upgrade=1
-  ,.headers= { { "Host", "example.com" }
-             , { "Connection", "Upgrade" }
-             , { "Sec-WebSocket-Key2", "12998 5 Y3 1  .P00" }
-             , { "Sec-WebSocket-Protocol", "sample" }
-             , { "Upgrade", "WebSocket" }
-             , { "Sec-WebSocket-Key1", "4 @1  46546xW%0l 1 5" }
-             , { "Origin", "http://example.com" }
-             }
-  ,.body= ""
-  }
-
-#define CONNECT_REQUEST 17
-, {.name = "connect request"
-  ,.type= HTTP_REQUEST
-  ,.raw= "CONNECT home0.netscape.com:443 HTTP/1.0\r\n"
-         "User-agent: Mozilla/1.1N\r\n"
-         "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"
-         "\r\n"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 0
-  ,.method= HTTP_CONNECT
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= ""
-  ,.request_url= "home0.netscape.com:443"
-  ,.num_headers= 2
-  ,.upgrade=1
-  ,.headers= { { "User-agent", "Mozilla/1.1N" }
-             , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }
-             }
-  ,.body= ""
-  }
-
-#define REPORT_REQ 18
-, {.name= "report request"
-  ,.type= HTTP_REQUEST
-  ,.raw= "REPORT /test HTTP/1.1\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_REPORT
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/test"
-  ,.request_url= "/test"
-  ,.num_headers= 0
-  ,.headers= {}
-  ,.body= ""
-  }
-
-#define NO_HTTP_VERSION 19
-, {.name= "request with no http version"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /\r\n"
-         "\r\n"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 0
-  ,.http_minor= 9
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "/"
-  ,.request_url= "/"
-  ,.num_headers= 0
-  ,.headers= {}
-  ,.body= ""
-  }
-
-#define MSEARCH_REQ 20
-, {.name= "m-search request"
-  ,.type= HTTP_REQUEST
-  ,.raw= "M-SEARCH * HTTP/1.1\r\n"
-         "HOST: 239.255.255.250:1900\r\n"
-         "MAN: \"ssdp:discover\"\r\n"
-         "ST: \"ssdp:all\"\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_MSEARCH
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= "*"
-  ,.request_url= "*"
-  ,.num_headers= 3
-  ,.headers= { { "HOST", "239.255.255.250:1900" }
-             , { "MAN", "\"ssdp:discover\"" }
-             , { "ST", "\"ssdp:all\"" }
-             }
-  ,.body= ""
-  }
-
-#define UTF8_PATH_REQ 21
-, {.name= "utf-8 path request"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n"
-         "Host: github.com\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= "q=1"
-  ,.fragment= "narf"
-  ,.request_path= "/δ¶/δt/pope"
-  ,.request_url= "/δ¶/δt/pope?q=1#narf"
-  ,.num_headers= 1
-  ,.headers= { {"Host", "github.com" }
-             }
-  ,.body= ""
-  }
-
-#define QUERY_TERMINATED_HOST 22
-, {.name= "host terminated by a query string"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= "hail=all"
-  ,.fragment= ""
-  ,.request_path= ""
-  ,.request_url= "http://hypnotoad.org?hail=all"
-  ,.num_headers= 0
-  ,.headers= { }
-  ,.body= ""
-  }
-
-#define QUERY_TERMINATED_HOSTPORT 23
-, {.name= "host:port terminated by a query string"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= "hail=all"
-  ,.fragment= ""
-  ,.request_path= ""
-  ,.request_url= "http://hypnotoad.org:1234?hail=all"
-  ,.num_headers= 0
-  ,.headers= { }
-  ,.body= ""
-  }
-
-#define SPACE_TERMINATED_HOSTPORT 24
-, {.name= "host:port terminated by a space"
-  ,.type= HTTP_REQUEST
-  ,.raw= "GET http://hypnotoad.org:1234 HTTP/1.1\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.method= HTTP_GET
-  ,.query_string= ""
-  ,.fragment= ""
-  ,.request_path= ""
-  ,.request_url= "http://hypnotoad.org:1234"
-  ,.num_headers= 0
-  ,.headers= { }
-  ,.body= ""
-  }
-
-, {.name= NULL } /* sentinel */
-};
-
-/* * R E S P O N S E S * */
-const struct message responses[] =
-#define GOOGLE_301 0
-{ {.name= "google 301"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 301 Moved Permanently\r\n"
-         "Location: http://www.google.com/\r\n"
-         "Content-Type: text/html; charset=UTF-8\r\n"
-         "Date: Sun, 26 Apr 2009 11:11:49 GMT\r\n"
-         "Expires: Tue, 26 May 2009 11:11:49 GMT\r\n"
-         "X-$PrototypeBI-Version: 1.6.0.3\r\n" /* $ char in header field */
-         "Cache-Control: public, max-age=2592000\r\n"
-         "Server: gws\r\n"
-         "Content-Length:  219  \r\n"
-         "\r\n"
-         "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n"
-         "<TITLE>301 Moved</TITLE></HEAD><BODY>\n"
-         "<H1>301 Moved</H1>\n"
-         "The document has moved\n"
-         "<A HREF=\"http://www.google.com/\">here</A>.\r\n"
-         "</BODY></HTML>\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 301
-  ,.num_headers= 8
-  ,.headers=
-    { { "Location", "http://www.google.com/" }
-    , { "Content-Type", "text/html; charset=UTF-8" }
-    , { "Date", "Sun, 26 Apr 2009 11:11:49 GMT" }
-    , { "Expires", "Tue, 26 May 2009 11:11:49 GMT" }
-    , { "X-$PrototypeBI-Version", "1.6.0.3" }
-    , { "Cache-Control", "public, max-age=2592000" }
-    , { "Server", "gws" }
-    , { "Content-Length", "219  " }
-    }
-  ,.body= "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n"
-          "<TITLE>301 Moved</TITLE></HEAD><BODY>\n"
-          "<H1>301 Moved</H1>\n"
-          "The document has moved\n"
-          "<A HREF=\"http://www.google.com/\">here</A>.\r\n"
-          "</BODY></HTML>\r\n"
-  }
-
-#define NO_CONTENT_LENGTH_RESPONSE 1
-/* The client should wait for the server's EOF. That is, when content-length
- * is not specified, and "Connection: close", the end of body is specified
- * by the EOF.
- * Compare with APACHEBENCH_GET
- */
-, {.name= "no content-length response"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\r\n"
-         "Date: Tue, 04 Aug 2009 07:59:32 GMT\r\n"
-         "Server: Apache\r\n"
-         "X-Powered-By: Servlet/2.5 JSP/2.1\r\n"
-         "Content-Type: text/xml; charset=utf-8\r\n"
-         "Connection: close\r\n"
-         "\r\n"
-         "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-         "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
-         "  <SOAP-ENV:Body>\n"
-         "    <SOAP-ENV:Fault>\n"
-         "       <faultcode>SOAP-ENV:Client</faultcode>\n"
-         "       <faultstring>Client Error</faultstring>\n"
-         "    </SOAP-ENV:Fault>\n"
-         "  </SOAP-ENV:Body>\n"
-         "</SOAP-ENV:Envelope>"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= TRUE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 5
-  ,.headers=
-    { { "Date", "Tue, 04 Aug 2009 07:59:32 GMT" }
-    , { "Server", "Apache" }
-    , { "X-Powered-By", "Servlet/2.5 JSP/2.1" }
-    , { "Content-Type", "text/xml; charset=utf-8" }
-    , { "Connection", "close" }
-    }
-  ,.body= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-          "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
-          "  <SOAP-ENV:Body>\n"
-          "    <SOAP-ENV:Fault>\n"
-          "       <faultcode>SOAP-ENV:Client</faultcode>\n"
-          "       <faultstring>Client Error</faultstring>\n"
-          "    </SOAP-ENV:Fault>\n"
-          "  </SOAP-ENV:Body>\n"
-          "</SOAP-ENV:Envelope>"
-  }
-
-#define NO_HEADERS_NO_BODY_404 2
-, {.name= "404 no headers no body"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 404 Not Found\r\n\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 404
-  ,.num_headers= 0
-  ,.headers= {}
-  ,.body_size= 0
-  ,.body= ""
-  }
-
-#define NO_REASON_PHRASE 3
-, {.name= "301 no response phrase"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 301\r\n\r\n"
-  ,.should_keep_alive = TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 301
-  ,.num_headers= 0
-  ,.headers= {}
-  ,.body= ""
-  }
-
-#define TRAILING_SPACE_ON_CHUNKED_BODY 4
-, {.name="200 trailing space on chunked body"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\r\n"
-         "Content-Type: text/plain\r\n"
-         "Transfer-Encoding: chunked\r\n"
-         "\r\n"
-         "25  \r\n"
-         "This is the data in the first chunk\r\n"
-         "\r\n"
-         "1C\r\n"
-         "and this is the second one\r\n"
-         "\r\n"
-         "0  \r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 2
-  ,.headers=
-    { {"Content-Type", "text/plain" }
-    , {"Transfer-Encoding", "chunked" }
-    }
-  ,.body_size = 37+28
-  ,.body =
-         "This is the data in the first chunk\r\n"
-         "and this is the second one\r\n"
-
-  }
-
-#define NO_CARRIAGE_RET 5
-, {.name="no carriage ret"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\n"
-         "Content-Type: text/html; charset=utf-8\n"
-         "Connection: close\n"
-         "\n"
-         "these headers are from http://news.ycombinator.com/"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= TRUE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 2
-  ,.headers=
-    { {"Content-Type", "text/html; charset=utf-8" }
-    , {"Connection", "close" }
-    }
-  ,.body= "these headers are from http://news.ycombinator.com/"
-  }
-
-#define PROXY_CONNECTION 6
-, {.name="proxy connection"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\r\n"
-         "Content-Type: text/html; charset=UTF-8\r\n"
-         "Content-Length: 11\r\n"
-         "Proxy-Connection: close\r\n"
-         "Date: Thu, 31 Dec 2009 20:55:48 +0000\r\n"
-         "\r\n"
-         "hello world"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 4
-  ,.headers=
-    { {"Content-Type", "text/html; charset=UTF-8" }
-    , {"Content-Length", "11" }
-    , {"Proxy-Connection", "close" }
-    , {"Date", "Thu, 31 Dec 2009 20:55:48 +0000"}
-    }
-  ,.body= "hello world"
-  }
-
-#define UNDERSTORE_HEADER_KEY 7
-  // shown by
-  // curl -o /dev/null -v "http://ad.doubleclick.net/pfadx/DARTSHELLCONFIGXML;dcmt=text/xml;"
-, {.name="underscore header key"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\r\n"
-         "Server: DCLK-AdSvr\r\n"
-         "Content-Type: text/xml\r\n"
-         "Content-Length: 0\r\n"
-         "DCLK_imp: v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o\r\n\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 4
-  ,.headers=
-    { {"Server", "DCLK-AdSvr" }
-    , {"Content-Type", "text/xml" }
-    , {"Content-Length", "0" }
-    , {"DCLK_imp", "v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o" }
-    }
-  ,.body= ""
-  }
-
-#define BONJOUR_MADAME_FR 8
-/* The client should not merge two headers fields when the first one doesn't
- * have a value.
- */
-, {.name= "bonjourmadame.fr"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.0 301 Moved Permanently\r\n"
-         "Date: Thu, 03 Jun 2010 09:56:32 GMT\r\n"
-         "Server: Apache/2.2.3 (Red Hat)\r\n"
-         "Cache-Control: public\r\n"
-         "Pragma: \r\n"
-         "Location: http://www.bonjourmadame.fr/\r\n"
-         "Vary: Accept-Encoding\r\n"
-         "Content-Length: 0\r\n"
-         "Content-Type: text/html; charset=UTF-8\r\n"
-         "Connection: keep-alive\r\n"
-         "\r\n"
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 0
-  ,.status_code= 301
-  ,.num_headers= 9
-  ,.headers=
-    { { "Date", "Thu, 03 Jun 2010 09:56:32 GMT" }
-    , { "Server", "Apache/2.2.3 (Red Hat)" }
-    , { "Cache-Control", "public" }
-    , { "Pragma", "" }
-    , { "Location", "http://www.bonjourmadame.fr/" }
-    , { "Vary",  "Accept-Encoding" }
-    , { "Content-Length", "0" }
-    , { "Content-Type", "text/html; charset=UTF-8" }
-    , { "Connection", "keep-alive" }
-    }
-  ,.body= ""
-  }
-
-#define SPACE_IN_FIELD_RES 9
-/* Should handle spaces in header fields */
-, {.name= "field space"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\r\n"
-         "Server: Microsoft-IIS/6.0\r\n"
-         "X-Powered-By: ASP.NET\r\n"
-         "en-US Content-Type: text/xml\r\n" /* this is the problem */
-         "Content-Type: text/xml\r\n"
-         "Content-Length: 16\r\n"
-         "Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n"
-         "Connection: keep-alive\r\n"
-         "\r\n"
-         "<xml>hello</xml>" /* fake body */
-  ,.should_keep_alive= TRUE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 7
-  ,.headers=
-    { { "Server",  "Microsoft-IIS/6.0" }
-    , { "X-Powered-By", "ASP.NET" }
-    , { "en-US Content-Type", "text/xml" }
-    , { "Content-Type", "text/xml" }
-    , { "Content-Length", "16" }
-    , { "Date", "Fri, 23 Jul 2010 18:45:38 GMT" }
-    , { "Connection", "keep-alive" }
-    }
-  ,.body= "<xml>hello</xml>"
-  }
-
-
-#define RES_FIELD_UNDERSCORE 10
-/* Should handle spaces in header fields */
-, {.name= "field underscore"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 200 OK\r\n"
-         "Date: Tue, 28 Sep 2010 01:14:13 GMT\r\n"
-         "Server: Apache\r\n"
-         "Cache-Control: no-cache, must-revalidate\r\n"
-         "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"
-         ".et-Cookie: PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com\r\n"
-         "Vary: Accept-Encoding\r\n"
-         "_eep-Alive: timeout=45\r\n" /* semantic value ignored */
-         "_onnection: Keep-Alive\r\n" /* semantic value ignored */
-         "Transfer-Encoding: chunked\r\n"
-         "Content-Type: text/html\r\n"
-         "Connection: close\r\n"
-         "\r\n"
-         "0\r\n\r\n"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 200
-  ,.num_headers= 11
-  ,.headers=
-    { { "Date", "Tue, 28 Sep 2010 01:14:13 GMT" }
-    , { "Server", "Apache" }
-    , { "Cache-Control", "no-cache, must-revalidate" }
-    , { "Expires", "Mon, 26 Jul 1997 05:00:00 GMT" }
-    , { ".et-Cookie", "PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com" }
-    , { "Vary", "Accept-Encoding" }
-    , { "_eep-Alive", "timeout=45" }
-    , { "_onnection", "Keep-Alive" }
-    , { "Transfer-Encoding", "chunked" }
-    , { "Content-Type", "text/html" }
-    , { "Connection", "close" }
-    }
-  ,.body= ""
-  }
-
-#define NON_ASCII_IN_STATUS_LINE 11
-/* Should handle non-ASCII in status line */
-, {.name= "non-ASCII in status line"
-  ,.type= HTTP_RESPONSE
-  ,.raw= "HTTP/1.1 500 Oriëntatieprobleem\r\n"
-         "Date: Fri, 5 Nov 2010 23:07:12 GMT+2\r\n"
-         "Content-Length: 0\r\n"
-         "Connection: close\r\n"
-         "\r\n"
-  ,.should_keep_alive= FALSE
-  ,.message_complete_on_eof= FALSE
-  ,.http_major= 1
-  ,.http_minor= 1
-  ,.status_code= 500
-  ,.num_headers= 3
-  ,.headers=
-    { { "Date", "Fri, 5 Nov 2010 23:07:12 GMT+2" }
-    , { "Content-Length", "0" }
-    , { "Connection", "close" }
-    }
-  ,.body= ""
-  }
-
-
-, {.name= NULL } /* sentinel */
-};
-
-int
-request_path_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  strncat(messages[num_messages].request_path, buf, len);
-  return 0;
-}
-
-int
-request_url_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  strncat(messages[num_messages].request_url, buf, len);
-  return 0;
-}
-
-int
-query_string_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  strncat(messages[num_messages].query_string, buf, len);
-  return 0;
-}
-
-int
-fragment_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  strncat(messages[num_messages].fragment, buf, len);
-  return 0;
-}
-
-int
-header_field_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  struct message *m = &messages[num_messages];
-
-  if (m->last_header_element != FIELD)
-    m->num_headers++;
-
-  strncat(m->headers[m->num_headers-1][0], buf, len);
-
-  m->last_header_element = FIELD;
-
-  return 0;
-}
-
-int
-header_value_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  struct message *m = &messages[num_messages];
-
-  strncat(m->headers[m->num_headers-1][1], buf, len);
-
-  m->last_header_element = VALUE;
-
-  return 0;
-}
-
-int
-body_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  strncat(messages[num_messages].body, buf, len);
-  messages[num_messages].body_size += len;
- // printf("body_cb: '%s'\n", requests[num_messages].body);
-  return 0;
-}
-
-int
-count_body_cb (http_parser *p, const char *buf, size_t len)
-{
-  assert(p == parser);
-  assert(buf);
-  messages[num_messages].body_size += len;
-  return 0;
-}
-
-int
-message_begin_cb (http_parser *p)
-{
-  assert(p == parser);
-  messages[num_messages].message_begin_cb_called = TRUE;
-  return 0;
-}
-
-int
-headers_complete_cb (http_parser *p)
-{
-  assert(p == parser);
-  messages[num_messages].method = parser->method;
-  messages[num_messages].status_code = parser->status_code;
-  messages[num_messages].http_major = parser->http_major;
-  messages[num_messages].http_minor = parser->http_minor;
-  messages[num_messages].headers_complete_cb_called = TRUE;
-  messages[num_messages].should_keep_alive = http_should_keep_alive(parser);
-  return 0;
-}
-
-int
-message_complete_cb (http_parser *p)
-{
-  assert(p == parser);
-  if (messages[num_messages].should_keep_alive != http_should_keep_alive(parser))
-  {
-    fprintf(stderr, "\n\n *** Error http_should_keep_alive() should have same "
-                    "value in both on_message_complete and on_headers_complete "
-                    "but it doesn't! ***\n\n");
-    assert(0);
-    exit(1);
-  }
-  messages[num_messages].message_complete_cb_called = TRUE;
-
-  messages[num_messages].message_complete_on_eof = currently_parsing_eof;
-
-  num_messages++;
-  return 0;
-}
-
-static http_parser_settings settings =
-  {.on_message_begin = message_begin_cb
-  ,.on_header_field = header_field_cb
-  ,.on_header_value = header_value_cb
-  ,.on_path = request_path_cb
-  ,.on_url = request_url_cb
-  ,.on_fragment = fragment_cb
-  ,.on_query_string = query_string_cb
-  ,.on_body = body_cb
-  ,.on_headers_complete = headers_complete_cb
-  ,.on_message_complete = message_complete_cb
-  };
-
-static http_parser_settings settings_count_body =
-  {.on_message_begin = message_begin_cb
-  ,.on_header_field = header_field_cb
-  ,.on_header_value = header_value_cb
-  ,.on_path = request_path_cb
-  ,.on_url = request_url_cb
-  ,.on_fragment = fragment_cb
-  ,.on_query_string = query_string_cb
-  ,.on_body = count_body_cb
-  ,.on_headers_complete = headers_complete_cb
-  ,.on_message_complete = message_complete_cb
-  };
-
-static http_parser_settings settings_null =
-  {.on_message_begin = 0
-  ,.on_header_field = 0
-  ,.on_header_value = 0
-  ,.on_path = 0
-  ,.on_url = 0
-  ,.on_fragment = 0
-  ,.on_query_string = 0
-  ,.on_body = 0
-  ,.on_headers_complete = 0
-  ,.on_message_complete = 0
-  };
-
-void
-parser_init (enum http_parser_type type)
-{
-  num_messages = 0;
-
-  assert(parser == NULL);
-
-  parser = malloc(sizeof(http_parser));
-
-  http_parser_init(parser, type);
-
-  memset(&messages, 0, sizeof messages);
-
-}
-
-void
-parser_free ()
-{
-  assert(parser);
-  free(parser);
-  parser = NULL;
-}
-
-size_t parse (const char *buf, size_t len)
-{
-  size_t nparsed;
-  currently_parsing_eof = (len == 0);
-  nparsed = http_parser_execute(parser, &settings, buf, len);
-  return nparsed;
-}
-
-size_t parse_count_body (const char *buf, size_t len)
-{
-  size_t nparsed;
-  currently_parsing_eof = (len == 0);
-  nparsed = http_parser_execute(parser, &settings_count_body, buf, len);
-  return nparsed;
-}
-
-static inline int
-check_str_eq (const struct message *m,
-              const char *prop,
-              const char *expected,
-              const char *found) {
-  if (0 != strcmp(expected, found)) {
-    printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name);
-    printf("expected '%s'\n", expected);
-    printf("   found '%s'\n", found);
-    return 0;
-  }
-  return 1;
-}
-
-static inline int
-check_num_eq (const struct message *m,
-              const char *prop,
-              int expected,
-              int found) {
-  if (expected != found) {
-    printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name);
-    printf("expected %d\n", expected);
-    printf("   found %d\n", found);
-    return 0;
-  }
-  return 1;
-}
-
-#define MESSAGE_CHECK_STR_EQ(expected, found, prop) \
-  if (!check_str_eq(expected, #prop, expected->prop, found->prop)) return 0
-
-#define MESSAGE_CHECK_NUM_EQ(expected, found, prop) \
-  if (!check_num_eq(expected, #prop, expected->prop, found->prop)) return 0
-
-
-int
-message_eq (int index, const struct message *expected)
-{
-  int i;
-  struct message *m = &messages[index];
-
-  MESSAGE_CHECK_NUM_EQ(expected, m, http_major);
-  MESSAGE_CHECK_NUM_EQ(expected, m, http_minor);
-
-  if (expected->type == HTTP_REQUEST) {
-    MESSAGE_CHECK_NUM_EQ(expected, m, method);
-  } else {
-    MESSAGE_CHECK_NUM_EQ(expected, m, status_code);
-  }
-
-  MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive);
-  MESSAGE_CHECK_NUM_EQ(expected, m, message_complete_on_eof);
-
-  assert(m->message_begin_cb_called);
-  assert(m->headers_complete_cb_called);
-  assert(m->message_complete_cb_called);
-
-
-  MESSAGE_CHECK_STR_EQ(expected, m, request_path);
-  MESSAGE_CHECK_STR_EQ(expected, m, query_string);
-  MESSAGE_CHECK_STR_EQ(expected, m, fragment);
-  MESSAGE_CHECK_STR_EQ(expected, m, request_url);
-  if (expected->body_size) {
-    MESSAGE_CHECK_NUM_EQ(expected, m, body_size);
-  } else {
-    MESSAGE_CHECK_STR_EQ(expected, m, body);
-  }
-
-  MESSAGE_CHECK_NUM_EQ(expected, m, num_headers);
-
-  int r;
-  for (i = 0; i < m->num_headers; i++) {
-    r = check_str_eq(expected, "header field", expected->headers[i][0], m->headers[i][0]);
-    if (!r) return 0;
-    r = check_str_eq(expected, "header value", expected->headers[i][1], m->headers[i][1]);
-    if (!r) return 0;
-  }
-
-  return 1;
-}
-
-static void
-print_error (const char *raw, size_t error_location)
-{
-  fprintf(stderr, "\n*** parse error ***\n\n");
-
-  int this_line = 0, char_len = 0;
-  size_t i, j, len = strlen(raw), error_location_line = 0;
-  for (i = 0; i < len; i++) {
-    if (i == error_location) this_line = 1;
-    switch (raw[i]) {
-      case '\r':
-        char_len = 2;
-        fprintf(stderr, "\\r");
-        break;
-
-      case '\n':
-        char_len = 2;
-        fprintf(stderr, "\\n\n");
-
-        if (this_line) goto print;
-
-        error_location_line = 0;
-        continue;
-
-      default:
-        char_len = 1;
-        fputc(raw[i], stderr);
-        break;
-    }
-    if (!this_line) error_location_line += char_len;
-  }
-
-  fprintf(stderr, "[eof]\n");
-
- print:
-  for (j = 0; j < error_location_line; j++) {
-    fputc(' ', stderr);
-  }
-  fprintf(stderr, "^\n\nerror location: %u\n", (unsigned int)error_location);
-}
-
-
-void
-test_message (const struct message *message)
-{
-  size_t raw_len = strlen(message->raw);
-  size_t msg1len;
-  for (msg1len = 0; msg1len < raw_len; msg1len++) {
-    parser_init(message->type);
-
-    size_t read;
-    const char *msg1 = message->raw;
-    const char *msg2 = msg1 + msg1len;
-    size_t msg2len = raw_len - msg1len;
-
-    if (msg1len) {
-      read = parse(msg1, msg1len);
-
-      if (message->upgrade && parser->upgrade) goto test;
-
-      if (read != msg1len) {
-        print_error(msg1, read);
-        exit(1);
-      }
-    }
-
-
-    read = parse(msg2, msg2len);
-
-    if (message->upgrade && parser->upgrade) goto test;
-
-    if (read != msg2len) {
-      print_error(msg2, read);
-      exit(1);
-    }
-
-    read = parse(NULL, 0);
-
-    if (message->upgrade && parser->upgrade) goto test;
-
-    if (read != 0) {
-      print_error(message->raw, read);
-      exit(1);
-    }
-
-  test:
-
-    if (num_messages != 1) {
-      printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name);
-      exit(1);
-    }
-
-    if(!message_eq(0, message)) exit(1);
-
-    parser_free();
-  }
-}
-
-void
-test_message_count_body (const struct message *message)
-{
-  parser_init(message->type);
-
-  size_t read;
-  size_t l = strlen(message->raw);
-  size_t i, toread;
-  size_t chunk = 4024;
-
-  for (i = 0; i < l; i+= chunk) {
-    toread = MIN(l-i, chunk);
-    read = parse_count_body(message->raw + i, toread);
-    if (read != toread) {
-      print_error(message->raw, read);
-      exit(1);
-    }
-  }
-
-
-  read = parse_count_body(NULL, 0);
-  if (read != 0) {
-    print_error(message->raw, read);
-    exit(1);
-  }
-
-  if (num_messages != 1) {
-    printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name);
-    exit(1);
-  }
-
-  if(!message_eq(0, message)) exit(1);
-
-  parser_free();
-}
-
-void
-test_simple (const char *buf, int should_pass)
-{
-  parser_init(HTTP_REQUEST);
-
-  size_t parsed;
-  int pass;
-  parsed = parse(buf, strlen(buf));
-  pass = (parsed == strlen(buf));
-  parsed = parse(NULL, 0);
-  pass &= (parsed == 0);
-
-  parser_free();
-
-  if (pass != should_pass) {
-    fprintf(stderr, "\n*** test_simple expected %s ***\n\n%s", should_pass ? "success" : "error", buf);
-    exit(1);
-  }
-}
-
-void
-test_header_overflow_error (int req)
-{
-  http_parser parser;
-  http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
-  size_t parsed;
-  const char *buf;
-  buf = req ? "GET / HTTP/1.1\r\n" : "HTTP/1.0 200 OK\r\n";
-  parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));
-  assert(parsed == strlen(buf));
-
-  buf = "header-key: header-value\r\n";
-  int i;
-  for (i = 0; i < 10000; i++) {
-    if (http_parser_execute(&parser, &settings_null, buf, strlen(buf)) != strlen(buf)) {
-      //fprintf(stderr, "error found on iter %d\n", i);
-      return;
-    }
-  }
-
-  fprintf(stderr, "\n*** Error expected but none in header overflow test ***\n");
-  exit(1);
-}
-
-void
-test_no_overflow_long_body (int req, size_t length)
-{
-  http_parser parser;
-  http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);
-  size_t parsed;
-  size_t i;
-  char buf1[3000];
-  size_t buf1len = sprintf(buf1, "%s\r\nConnection: Keep-Alive\r\nContent-Length: %zu\r\n\r\n",
-      req ? "POST / HTTP/1.0" : "HTTP/1.0 200 OK", length);
-  parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len);
-  if (parsed != buf1len)
-    goto err;
-
-  for (i = 0; i < length; i++) {
-    char foo = 'a';
-    parsed = http_parser_execute(&parser, &settings_null, &foo, 1);
-    if (parsed != 1)
-      goto err;
-  }
-
-  parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len);
-  if (parsed != buf1len) goto err;
-  return;
-
- err:
-  fprintf(stderr,
-          "\n*** error in test_no_overflow_long_body %s of length %zu ***\n",
-          req ? "REQUEST" : "RESPONSE",
-          length);
-  exit(1);
-}
-
-void
-test_multiple3 (const struct message *r1, const struct message *r2, const struct message *r3)
-{
-  int message_count = 1;
-  if (!r1->upgrade) {
-    message_count++;
-    if (!r2->upgrade) message_count++;
-  }
-  int has_upgrade = (message_count < 3 || r3->upgrade);
-
-  char total[ strlen(r1->raw)
-            + strlen(r2->raw)
-            + strlen(r3->raw)
-            + 1
-            ];
-  total[0] = '\0';
-
-  strcat(total, r1->raw);
-  strcat(total, r2->raw);
-  strcat(total, r3->raw);
-
-  parser_init(r1->type);
-
-  size_t read;
-
-  read = parse(total, strlen(total));
-
-  if (has_upgrade && parser->upgrade) goto test;
-
-  if (read != strlen(total)) {
-    print_error(total, read);
-    exit(1);
-  }
-
-  read = parse(NULL, 0);
-
-  if (has_upgrade && parser->upgrade) goto test;
-
-  if (read != 0) {
-    print_error(total, read);
-    exit(1);
-  }
-
-test:
-
-  if (message_count != num_messages) {
-    fprintf(stderr, "\n\n*** Parser didn't see 3 messages only %d *** \n", num_messages);
-    exit(1);
-  }
-
-  if (!message_eq(0, r1)) exit(1);
-  if (message_count > 1) {
-    if (!message_eq(1, r2)) exit(1);
-    if (message_count > 2) {
-      if (!message_eq(2, r3)) exit(1);
-    }
-  }
-
-  parser_free();
-}
-
-/* SCAN through every possible breaking to make sure the
- * parser can handle getting the content in any chunks that
- * might come from the socket
- */
-void
-test_scan (const struct message *r1, const struct message *r2, const struct message *r3)
-{
-  char total[80*1024] = "\0";
-  char buf1[80*1024] = "\0";
-  char buf2[80*1024] = "\0";
-  char buf3[80*1024] = "\0";
-
-  strcat(total, r1->raw);
-  strcat(total, r2->raw);
-  strcat(total, r3->raw);
-
-  size_t read;
-
-  int total_len = strlen(total);
-
-  int total_ops = 2 * (total_len - 1) * (total_len - 2) / 2;
-  int ops = 0 ;
-
-  size_t buf1_len, buf2_len, buf3_len;
-
-  int i,j,type_both;
-  for (type_both = 0; type_both < 2; type_both ++ ) {
-    for (j = 2; j < total_len; j ++ ) {
-      for (i = 1; i < j; i ++ ) {
-
-        if (ops % 1000 == 0)  {
-          printf("\b\b\b\b%3.0f%%", 100 * (float)ops /(float)total_ops);
-          fflush(stdout);
-        }
-        ops += 1;
-
-        parser_init(type_both ? HTTP_BOTH : r1->type);
-
-        buf1_len = i;
-        strncpy(buf1, total, buf1_len);
-        buf1[buf1_len] = 0;
-
-        buf2_len = j - i;
-        strncpy(buf2, total+i, buf2_len);
-        buf2[buf2_len] = 0;
-
-        buf3_len = total_len - j;
-        strncpy(buf3, total+j, buf3_len);
-        buf3[buf3_len] = 0;
-
-        read = parse(buf1, buf1_len);
-
-        if (r3->upgrade && parser->upgrade) goto test;
-
-        if (read != buf1_len) {
-          print_error(buf1, read);
-          goto error;
-        }
-
-        read = parse(buf2, buf2_len);
-
-        if (r3->upgrade && parser->upgrade) goto test;
-
-        if (read != buf2_len) {
-          print_error(buf2, read);
-          goto error;
-        }
-
-        read = parse(buf3, buf3_len);
-
-        if (r3->upgrade && parser->upgrade) goto test;
-
-        if (read != buf3_len) {
-          print_error(buf3, read);
-          goto error;
-        }
-
-        parse(NULL, 0);
-
-test:
-
-        if (3 != num_messages) {
-          fprintf(stderr, "\n\nParser didn't see 3 messages only %d\n", num_messages);
-          goto error;
-        }
-
-        if (!message_eq(0, r1)) {
-          fprintf(stderr, "\n\nError matching messages[0] in test_scan.\n");
-          goto error;
-        }
-
-        if (!message_eq(1, r2)) {
-          fprintf(stderr, "\n\nError matching messages[1] in test_scan.\n");
-          goto error;
-        }
-
-        if (!message_eq(2, r3)) {
-          fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n");
-          goto error;
-        }
-
-        parser_free();
-      }
-    }
-  }
-  puts("\b\b\b\b100%");
-  return;
-
- error:
-  fprintf(stderr, "i=%d  j=%d\n", i, j);
-  fprintf(stderr, "buf1 (%u) %s\n\n", (unsigned int)buf1_len, buf1);
-  fprintf(stderr, "buf2 (%u) %s\n\n", (unsigned int)buf2_len , buf2);
-  fprintf(stderr, "buf3 (%u) %s\n", (unsigned int)buf3_len, buf3);
-  exit(1);
-}
-
-// user required to free the result
-// string terminated by \0
-char *
-create_large_chunked_message (int body_size_in_kb, const char* headers)
-{
-  int i;
-  size_t wrote = 0;
-  size_t headers_len = strlen(headers);
-  size_t bufsize = headers_len + (5+1024+2)*body_size_in_kb + 6;
-  char * buf = malloc(bufsize);
-
-  memcpy(buf, headers, headers_len);
-  wrote += headers_len;
-
-  for (i = 0; i < body_size_in_kb; i++) {
-    // write 1kb chunk into the body.
-    memcpy(buf + wrote, "400\r\n", 5);
-    wrote += 5;
-    memset(buf + wrote, 'C', 1024);
-    wrote += 1024;
-    strcpy(buf + wrote, "\r\n");
-    wrote += 2;
-  }
-
-  memcpy(buf + wrote, "0\r\n\r\n", 6);
-  wrote += 6;
-  assert(wrote == bufsize);
-
-  return buf;
-}
-
-
-int
-main (void)
-{
-  parser = NULL;
-  int i, j, k;
-  int request_count;
-  int response_count;
-
-  printf("sizeof(http_parser) = %u\n", (unsigned int)sizeof(http_parser));
-
-  for (request_count = 0; requests[request_count].name; request_count++);
-  for (response_count = 0; responses[response_count].name; response_count++);
-
-  //// OVERFLOW CONDITIONS
-
-  test_header_overflow_error(HTTP_REQUEST);
-  test_no_overflow_long_body(HTTP_REQUEST, 1000);
-  test_no_overflow_long_body(HTTP_REQUEST, 100000);
-
-  test_header_overflow_error(HTTP_RESPONSE);
-  test_no_overflow_long_body(HTTP_RESPONSE, 1000);
-  test_no_overflow_long_body(HTTP_RESPONSE, 100000);
-
-  //// RESPONSES
-
-  for (i = 0; i < response_count; i++) {
-    test_message(&responses[i]);
-  }
-
-  for (i = 0; i < response_count; i++) {
-    if (!responses[i].should_keep_alive) continue;
-    for (j = 0; j < response_count; j++) {
-      if (!responses[j].should_keep_alive) continue;
-      for (k = 0; k < response_count; k++) {
-        test_multiple3(&responses[i], &responses[j], &responses[k]);
-      }
-    }
-  }
-
-  test_message_count_body(&responses[NO_HEADERS_NO_BODY_404]);
-  test_message_count_body(&responses[TRAILING_SPACE_ON_CHUNKED_BODY]);
-
-  // test very large chunked response
-  {
-    char * msg = create_large_chunked_message(31337,
-      "HTTP/1.0 200 OK\r\n"
-      "Transfer-Encoding: chunked\r\n"
-      "Content-Type: text/plain\r\n"
-      "\r\n");
-    struct message large_chunked =
-      {.name= "large chunked"
-      ,.type= HTTP_RESPONSE
-      ,.raw= msg
-      ,.should_keep_alive= FALSE
-      ,.message_complete_on_eof= FALSE
-      ,.http_major= 1
-      ,.http_minor= 0
-      ,.status_code= 200
-      ,.num_headers= 2
-      ,.headers=
-        { { "Transfer-Encoding", "chunked" }
-        , { "Content-Type", "text/plain" }
-        }
-      ,.body_size= 31337*1024
-      };
-    test_message_count_body(&large_chunked);
-    free(msg);
-  }
-
-
-
-  printf("response scan 1/2      ");
-  test_scan( &responses[TRAILING_SPACE_ON_CHUNKED_BODY]
-           , &responses[NO_HEADERS_NO_BODY_404]
-           , &responses[NO_REASON_PHRASE]
-           );
-
-  printf("response scan 2/2      ");
-  test_scan( &responses[BONJOUR_MADAME_FR]
-           , &responses[UNDERSTORE_HEADER_KEY]
-           , &responses[NO_CARRIAGE_RET]
-           );
-
-  puts("responses okay");
-
-
-  /// REQUESTS
-
-  test_simple("hello world", 0);
-  test_simple("GET / HTP/1.1\r\n\r\n", 0);
-
-
-  test_simple("ASDF / HTTP/1.1\r\n\r\n", 0);
-  test_simple("PROPPATCHA / HTTP/1.1\r\n\r\n", 0);
-  test_simple("GETA / HTTP/1.1\r\n\r\n", 0);
-
-  // Well-formed but incomplete
-  test_simple("GET / HTTP/1.1\r\n"
-              "Content-Type: text/plain\r\n"
-              "Content-Length: 6\r\n"
-              "\r\n"
-              "fooba",
-              0);
-
-  static const char *all_methods[] = {
-    "DELETE",
-    "GET",
-    "HEAD",
-    "POST",
-    "PUT",
-    //"CONNECT", //CONNECT can't be tested like other methods, it's a tunnel
-    "OPTIONS",
-    "TRACE",
-    "COPY",
-    "LOCK",
-    "MKCOL",
-    "MOVE",
-    "PROPFIND",
-    "PROPPATCH",
-    "UNLOCK",
-    0 };
-  const char **this_method;
-  for (this_method = all_methods; *this_method; this_method++) {
-    char buf[200];
-    sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method);
-    test_simple(buf, 1);
-  }
-
-  const char *dumbfuck2 =
-    "GET / HTTP/1.1\r\n"
-    "X-SSL-Bullshit:   -----BEGIN CERTIFICATE-----\r\n"
-    "\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n"
-    "\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n"
-    "\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n"
-    "\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n"
-    "\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n"
-    "\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n"
-    "\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n"
-    "\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n"
-    "\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n"
-    "\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n"
-    "\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n"
-    "\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n"
-    "\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgHTTPAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n"
-    "\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n"
-    "\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n"
-    "\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n"
-    "\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n"
-    "\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n"
-    "\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n"
-    "\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n"
-    "\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n"
-    "\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n"
-    "\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n"
-    "\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n"
-    "\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n"
-    "\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n"
-    "\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n"
-    "\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n"
-    "\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n"
-    "\tRA==\r\n"
-    "\t-----END CERTIFICATE-----\r\n"
-    "\r\n";
-  test_simple(dumbfuck2, 0);
-
-#if 0
-  // NOTE(Wed Nov 18 11:57:27 CET 2009) this seems okay. we just read body
-  // until EOF.
-  //
-  // no content-length
-  // error if there is a body without content length
-  const char *bad_get_no_headers_no_body = "GET /bad_get_no_headers_no_body/world HTTP/1.1\r\n"
-                                           "Accept: */*\r\n"
-                                           "\r\n"
-                                           "HELLO";
-  test_simple(bad_get_no_headers_no_body, 0);
-#endif
-  /* TODO sending junk and large headers gets rejected */
-
-
-  /* check to make sure our predefined requests are okay */
-  for (i = 0; requests[i].name; i++) {
-    test_message(&requests[i]);
-  }
-
-
-
-  for (i = 0; i < request_count; i++) {
-    if (!requests[i].should_keep_alive) continue;
-    for (j = 0; j < request_count; j++) {
-      if (!requests[j].should_keep_alive) continue;
-      for (k = 0; k < request_count; k++) {
-        test_multiple3(&requests[i], &requests[j], &requests[k]);
-      }
-    }
-  }
-
-  printf("request scan 1/4      ");
-  test_scan( &requests[GET_NO_HEADERS_NO_BODY]
-           , &requests[GET_ONE_HEADER_NO_BODY]
-           , &requests[GET_NO_HEADERS_NO_BODY]
-           );
-
-  printf("request scan 2/4      ");
-  test_scan( &requests[POST_CHUNKED_ALL_YOUR_BASE]
-           , &requests[POST_IDENTITY_BODY_WORLD]
-           , &requests[GET_FUNKY_CONTENT_LENGTH]
-           );
-
-  printf("request scan 3/4      ");
-  test_scan( &requests[TWO_CHUNKS_MULT_ZERO_END]
-           , &requests[CHUNKED_W_TRAILING_HEADERS]
-           , &requests[CHUNKED_W_BULLSHIT_AFTER_LENGTH]
-           );
-
-  printf("request scan 4/4      ");
-  test_scan( &requests[QUERY_URL_WITH_QUESTION_MARK_GET]
-           , &requests[PREFIX_NEWLINE_GET ]
-           , &requests[CONNECT_REQUEST]
-           );
-
-  puts("requests okay");
-
-  return 0;
-}
diff --git a/http_parser.rb.gemspec b/http_parser.rb.gemspec
index 3fff255..3cff960 100644
--- a/http_parser.rb.gemspec
+++ b/http_parser.rb.gemspec
@@ -1,6 +1,6 @@
 Gem::Specification.new do |s|
   s.name = "http_parser.rb"
-  s.version = "0.5.3"
+  s.version = "0.6.0.beta.2"
   s.summary = "Simple callback-based HTTP request/response parser"
   s.description = "Ruby bindings to http://github.com/ry/http-parser and http://github.com/a2800276/http-parser.java"
 
@@ -16,6 +16,8 @@ Gem::Specification.new do |s|
   s.add_development_dependency 'rake-compiler', '>= 0.7.9'
   s.add_development_dependency 'rspec', '>= 2.0.1'
   s.add_development_dependency 'json', '>= 1.4.6'
+  s.add_development_dependency 'benchmark_suite'
+  s.add_development_dependency 'ffi'
 
   if RUBY_PLATFORM =~ /java/
     s.add_development_dependency 'jruby-openssl'
diff --git a/metadata.yml b/metadata.yml
deleted file mode 100644
index 3c306d6..0000000
--- a/metadata.yml
+++ /dev/null
@@ -1,209 +0,0 @@
---- !ruby/object:Gem::Specification 
-name: http_parser.rb
-version: !ruby/object:Gem::Version 
-  hash: 13
-  prerelease: 
-  segments: 
-  - 0
-  - 5
-  - 3
-  version: 0.5.3
-platform: ruby
-authors: 
-- Marc-Andre Cournoyer
-- Aman Gupta
-autorequire: 
-bindir: bin
-cert_chain: []
-
-date: 2011-10-01 00:00:00 -05:00
-default_executable: 
-dependencies: 
-- !ruby/object:Gem::Dependency 
-  name: rake-compiler
-  prerelease: false
-  requirement: &id001 !ruby/object:Gem::Requirement 
-    none: false
-    requirements: 
-    - - ">="
-      - !ruby/object:Gem::Version 
-        hash: 17
-        segments: 
-        - 0
-        - 7
-        - 9
-        version: 0.7.9
-  type: :development
-  version_requirements: *id001
-- !ruby/object:Gem::Dependency 
-  name: rspec
-  prerelease: false
-  requirement: &id002 !ruby/object:Gem::Requirement 
-    none: false
-    requirements: 
-    - - ">="
-      - !ruby/object:Gem::Version 
-        hash: 13
-        segments: 
-        - 2
-        - 0
-        - 1
-        version: 2.0.1
-  type: :development
-  version_requirements: *id002
-- !ruby/object:Gem::Dependency 
-  name: json
-  prerelease: false
-  requirement: &id003 !ruby/object:Gem::Requirement 
-    none: false
-    requirements: 
-    - - ">="
-      - !ruby/object:Gem::Version 
-        hash: 11
-        segments: 
-        - 1
-        - 4
-        - 6
-        version: 1.4.6
-  type: :development
-  version_requirements: *id003
-- !ruby/object:Gem::Dependency 
-  name: yajl-ruby
-  prerelease: false
-  requirement: &id004 !ruby/object:Gem::Requirement 
-    none: false
-    requirements: 
-    - - ">="
-      - !ruby/object:Gem::Version 
-        hash: 61
-        segments: 
-        - 0
-        - 8
-        - 1
-        version: 0.8.1
-  type: :development
-  version_requirements: *id004
-description: Ruby bindings to http://github.com/ry/http-parser and http://github.com/a2800276/http-parser.java
-email: 
-- macournoyer at gmail.com
-- aman at tmm1.net
-executables: []
-
-extensions: 
-- ext/ruby_http_parser/extconf.rb
-extra_rdoc_files: []
-
-files: 
-- .gitignore
-- .gitmodules
-- Gemfile
-- Gemfile.lock
-- LICENSE-MIT
-- README.md
-- Rakefile
-- bench/thin.rb
-- ext/ruby_http_parser/.gitignore
-- ext/ruby_http_parser/RubyHttpParserService.java
-- ext/ruby_http_parser/ext_help.h
-- ext/ruby_http_parser/extconf.rb
-- ext/ruby_http_parser/org/ruby_http_parser/RubyHttpParser.java
-- ext/ruby_http_parser/ruby_http_parser.c
-- ext/ruby_http_parser/vendor/.gitkeep
-- http_parser.rb.gemspec
-- lib/http/parser.rb
-- lib/http_parser.rb
-- spec/parser_spec.rb
-- spec/spec_helper.rb
-- spec/support/requests.json
-- spec/support/responses.json
-- tasks/compile.rake
-- tasks/fixtures.rake
-- tasks/spec.rake
-- tasks/submodules.rake
-- ext/ruby_http_parser/vendor/http-parser/CONTRIBUTIONS
-- ext/ruby_http_parser/vendor/http-parser/http_parser.c
-- ext/ruby_http_parser/vendor/http-parser/http_parser.h
-- ext/ruby_http_parser/vendor/http-parser/LICENSE-MIT
-- ext/ruby_http_parser/vendor/http-parser/Makefile
-- ext/ruby_http_parser/vendor/http-parser/README.md
-- ext/ruby_http_parser/vendor/http-parser/test.c
-- ext/ruby_http_parser/vendor/http-parser-java/build.xml
-- ext/ruby_http_parser/vendor/http-parser-java/compile
-- ext/ruby_http_parser/vendor/http-parser-java/ext/primitives.jar
-- ext/ruby_http_parser/vendor/http-parser-java/http_parser.c
-- ext/ruby_http_parser/vendor/http-parser-java/http_parser.h
-- ext/ruby_http_parser/vendor/http-parser-java/LICENSE-MIT
-- ext/ruby_http_parser/vendor/http-parser-java/Makefile
-- ext/ruby_http_parser/vendor/http-parser-java/README.md
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPCallback.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPDataCallback.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPErrorCallback.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPException.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPMethod.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/HTTPParser.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPCallback.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPDataCallback.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPErrorCallback.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/HTTPParser.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/lolevel/ParserSettings.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserSettings.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/ParserType.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/impl/http_parser/Util.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Message.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Requests.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Responses.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Test.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestHeaderOverflowError.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestLoaderNG.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/TestNoOverflowLongBody.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/UnitTest.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Upgrade.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/Util.java
-- ext/ruby_http_parser/vendor/http-parser-java/src/test/http_parser/lolevel/WrongContentLength.java
-- ext/ruby_http_parser/vendor/http-parser-java/test.c
-- ext/ruby_http_parser/vendor/http-parser-java/test_permutations
-- ext/ruby_http_parser/vendor/http-parser-java/test_unit
-- ext/ruby_http_parser/vendor/http-parser-java/test_utf8
-- ext/ruby_http_parser/vendor/http-parser-java/tests.dumped
-- ext/ruby_http_parser/vendor/http-parser-java/tests.utf8
-- ext/ruby_http_parser/vendor/http-parser-java/TODO
-- ext/ruby_http_parser/vendor/http-parser-java/tools/byte_constants.rb
-- ext/ruby_http_parser/vendor/http-parser-java/tools/const_char.rb
-- ext/ruby_http_parser/vendor/http-parser-java/tools/lowcase.rb
-- ext/ruby_http_parser/vendor/http-parser-java/tools/parse_tests.rb
-has_rdoc: true
-homepage: http://github.com/tmm1/http_parser.rb
-licenses: []
-
-post_install_message: 
-rdoc_options: []
-
-require_paths: 
-- lib
-required_ruby_version: !ruby/object:Gem::Requirement 
-  none: false
-  requirements: 
-  - - ">="
-    - !ruby/object:Gem::Version 
-      hash: 3
-      segments: 
-      - 0
-      version: "0"
-required_rubygems_version: !ruby/object:Gem::Requirement 
-  none: false
-  requirements: 
-  - - ">="
-    - !ruby/object:Gem::Version 
-      hash: 3
-      segments: 
-      - 0
-      version: "0"
-requirements: []
-
-rubyforge_project: 
-rubygems_version: 1.6.2
-signing_key: 
-specification_version: 3
-summary: Simple callback-based HTTP request/response parser
-test_files: []
-
diff --git a/spec/parser_spec.rb b/spec/parser_spec.rb
index 5cd5624..7134476 100644
--- a/spec/parser_spec.rb
+++ b/spec/parser_spec.rb
@@ -24,9 +24,6 @@ describe HTTP::Parser do
     @parser.status_code.should be_nil
 
     @parser.request_url.should be_nil
-    @parser.request_path.should be_nil
-    @parser.query_string.should be_nil
-    @parser.fragment.should be_nil
 
     @parser.header_value_type.should == :mixed
   end
@@ -78,9 +75,6 @@ describe HTTP::Parser do
     @parser.status_code.should be_nil
 
     @parser.request_url.should == '/test?ok=1'
-    @parser.request_path.should == '/test'
-    @parser.query_string.should == 'ok=1'
-    @parser.fragment.should be_empty
 
     @parser.headers.should == @headers
     @parser.headers['User-Agent'].should == 'curl/7.18.0'
@@ -119,9 +113,6 @@ describe HTTP::Parser do
     @parser.http_version.should == [1,0]
 
     @parser.request_url.should == '/'
-    @parser.request_path.should == '/'
-    @parser.query_string.should == ''
-    @parser.fragment.should == ''
 
     @parser.reset!.should be_true
 
@@ -130,9 +121,6 @@ describe HTTP::Parser do
     @parser.status_code.should be_nil
 
     @parser.request_url.should be_nil
-    @parser.request_path.should be_nil
-    @parser.query_string.should be_nil
-    @parser.fragment.should be_nil
   end
 
   it "should optionally reset parser state on no-body responses" do
@@ -282,16 +270,55 @@ describe HTTP::Parser do
     @parser.upgrade_data.should == ''
   end
 
+  it 'should stop parsing headers when instructed' do
+    request = "GET /websocket HTTP/1.1\r\n" +
+      "host: localhost\r\n" +
+      "connection: Upgrade\r\n" +
+      "upgrade: websocket\r\n" +
+      "sec-websocket-key: SD6/hpYbKjQ6Sown7pBbWQ==\r\n" +
+      "sec-websocket-version: 13\r\n" +
+      "\r\n"
+
+    @parser.on_headers_complete = proc { |e| :stop }
+    offset = (@parser << request)
+    @parser.upgrade?.should be_true
+    @parser.upgrade_data.should == ''
+    offset.should == request.length
+  end
+
+  it "should execute on_body on requests with no content-length" do
+   @parser.reset!.should be_true
+
+   @head, @complete, @body = 0, 0, 0
+   @parser.on_headers_complete = proc {|h| @head += 1 }
+   @parser.on_message_complete = proc { @complete += 1 }
+   @parser.on_body = proc {|b| @body += 1 }
+
+   head_response = "HTTP/1.1 200 OK\r\n\r\nstuff"
+
+   @parser << head_response
+   @parser << ''
+   @head.should == 1
+   @complete.should == 1
+   @body.should == 1
+  end
+
+
   %w[ request response ].each do |type|
     JSON.parse(File.read(File.expand_path("../support/#{type}s.json", __FILE__))).each do |test|
       test['headers'] ||= {}
+      next if !defined?(JRUBY_VERSION) and HTTP::Parser.strict? != test['strict']
 
       it "should parse #{type}: #{test['name']}" do
         @parser << test['raw']
 
-        @parser.keep_alive?.should == test['should_keep_alive']
-        @parser.upgrade?.should == (test['upgrade']==1)
         @parser.http_method.should == test['method']
+        @parser.keep_alive?.should == test['should_keep_alive']
+
+        if test.has_key?('upgrade') and test['upgrade'] != 0
+          @parser.upgrade?.should be_true
+          @parser.upgrade_data.should == test['upgrade']
+        end
 
         fields = %w[
           http_major
@@ -301,9 +328,6 @@ describe HTTP::Parser do
         if test['type'] == 'HTTP_REQUEST'
           fields += %w[
             request_url
-            request_path
-            query_string
-            fragment
           ]
         else
           fields += %w[
diff --git a/spec/support/requests.json b/spec/support/requests.json
index c3fd0fd..dbb6e98 100644
--- a/spec/support/requests.json
+++ b/spec/support/requests.json
@@ -18,7 +18,8 @@
       "Host": "0.0.0.0=5000",
       "Accept": "*/*"
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "firefox get",
@@ -44,7 +45,8 @@
       "Keep-Alive": "300",
       "Connection": "keep-alive"
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "dumbfuck",
@@ -63,7 +65,8 @@
     "headers": {
       "aaaaaaaaaaaaa": "++++++++++"
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "fragment in url",
@@ -79,7 +82,8 @@
     "request_path": "/forums/1/topics/2375",
     "request_url": "/forums/1/topics/2375?page=1#posts-17408",
     "num_headers": 0,
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "get no headers no body",
@@ -95,7 +99,8 @@
     "request_path": "/get_no_headers_no_body/world",
     "request_url": "/get_no_headers_no_body/world",
     "num_headers": 0,
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "get one header no body",
@@ -114,7 +119,8 @@
     "headers": {
       "Accept": "*/*"
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "get funky content length body hello",
@@ -133,7 +139,8 @@
     "headers": {
       "conTENT-Length": "5"
     },
-    "body": "HELLO"
+    "body": "HELLO",
+    "strict": true
   },
   {
     "name": "post identity body world",
@@ -154,7 +161,8 @@
       "Transfer-Encoding": "identity",
       "Content-Length": "5"
     },
-    "body": "World"
+    "body": "World",
+    "strict": true
   },
   {
     "name": "post - chunked body: all your base are belong to us",
@@ -173,7 +181,8 @@
     "headers": {
       "Transfer-Encoding": "chunked"
     },
-    "body": "all your base are belong to us"
+    "body": "all your base are belong to us",
+    "strict": true
   },
   {
     "name": "two chunks ; triple zero ending",
@@ -192,7 +201,8 @@
     "headers": {
       "Transfer-Encoding": "chunked"
     },
-    "body": "hello world"
+    "body": "hello world",
+    "strict": true
   },
   {
     "name": "chunked with trailing headers. blech.",
@@ -213,7 +223,8 @@
       "Vary": "*",
       "Content-Type": "text/plain"
     },
-    "body": "hello world"
+    "body": "hello world",
+    "strict": true
   },
   {
     "name": "with bullshit after the length",
@@ -232,7 +243,8 @@
     "headers": {
       "Transfer-Encoding": "chunked"
     },
-    "body": "hello world"
+    "body": "hello world",
+    "strict": true
   },
   {
     "name": "with quotes",
@@ -251,7 +263,8 @@
     "headers": {
 
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "apachebench get",
@@ -272,7 +285,8 @@
       "User-Agent": "ApacheBench/2.3",
       "Accept": "*/*"
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "query url with question mark",
@@ -291,7 +305,8 @@
     "headers": {
 
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "newline prefix get",
@@ -310,12 +325,13 @@
     "headers": {
 
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "upgrade request",
     "type": "HTTP_REQUEST",
-    "raw": "GET /demo HTTP/1.1\r\nHost: example.com\r\nConnection: Upgrade\r\nSec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\nSec-WebSocket-Protocol: sample\r\nUpgrade: WebSocket\r\nSec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\nOrigin: http://example.com\r\n\r\n",
+    "raw": "GET /demo HTTP/1.1\r\nHost: example.com\r\nConnection: Upgrade\r\nSec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\nSec-WebSocket-Protocol: sample\r\nUpgrade: WebSocket\r\nSec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\nOrigin: http://example.com\r\n\r\nHot diggity dogg",
     "should_keep_alive": true,
     "message_complete_on_eof": false,
     "http_major": 1,
@@ -326,7 +342,7 @@
     "request_path": "/demo",
     "request_url": "/demo",
     "num_headers": 7,
-    "upgrade": 1,
+    "upgrade": "Hot diggity dogg",
     "headers": {
       "Host": "example.com",
       "Connection": "Upgrade",
@@ -336,12 +352,13 @@
       "Sec-WebSocket-Key1": "4 @1  46546xW%0l 1 5",
       "Origin": "http://example.com"
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "connect request",
     "type": "HTTP_REQUEST",
-    "raw": "CONNECT home0.netscape.com:443 HTTP/1.0\r\nUser-agent: Mozilla/1.1N\r\nProxy-authorization: basic aGVsbG86d29ybGQ=\r\n\r\n",
+    "raw": "CONNECT 0-home0.netscape.com:443 HTTP/1.0\r\nUser-agent: Mozilla/1.1N\r\nProxy-authorization: basic aGVsbG86d29ybGQ=\r\n\r\nsome data\r\nand yet even more data",
     "should_keep_alive": false,
     "message_complete_on_eof": false,
     "http_major": 1,
@@ -350,14 +367,15 @@
     "query_string": "",
     "fragment": "",
     "request_path": "",
-    "request_url": "home0.netscape.com:443",
+    "request_url": "0-home0.netscape.com:443",
     "num_headers": 2,
-    "upgrade": 1,
+    "upgrade": "some data\r\nand yet even more data",
     "headers": {
       "User-agent": "Mozilla/1.1N",
       "Proxy-authorization": "basic aGVsbG86d29ybGQ="
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "report request",
@@ -376,7 +394,8 @@
     "headers": {
 
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "request with no http version",
@@ -395,6 +414,199 @@
     "headers": {
 
     },
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "m-search request",
+    "type": "HTTP_REQUEST",
+    "raw": "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nST: \"ssdp:all\"\r\n\r\n",
+    "should_keep_alive": true,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 1,
+    "method": "M-SEARCH",
+    "query_string": "",
+    "fragment": "",
+    "request_path": "*",
+    "request_url": "*",
+    "num_headers": 3,
+    "headers": {
+      "HOST": "239.255.255.250:1900",
+      "MAN": "\"ssdp:discover\"",
+      "ST": "\"ssdp:all\""
+    },
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "line folding in header value",
+    "type": "HTTP_REQUEST",
+    "raw": "GET / HTTP/1.1\r\nLine1:   abc\r\n\tdef\r\n ghi\r\n\t\tjkl\r\n  mno \r\n\t \tqrs\r\nLine2: \t line2\t\r\n\r\n",
+    "should_keep_alive": true,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 1,
+    "method": "GET",
+    "query_string": "",
+    "fragment": "",
+    "request_path": "/",
+    "request_url": "/",
+    "num_headers": 2,
+    "headers": {
+      "Line1": "abcdefghijklmno qrs",
+      "Line2": "line2\t"
+    },
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "host terminated by a query string",
+    "type": "HTTP_REQUEST",
+    "raw": "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n\r\n",
+    "should_keep_alive": true,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 1,
+    "method": "GET",
+    "query_string": "hail=all",
+    "fragment": "",
+    "request_path": "",
+    "request_url": "http://hypnotoad.org?hail=all",
+    "num_headers": 0,
+    "headers": {
+
+    },
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "host:port terminated by a query string",
+    "type": "HTTP_REQUEST",
+    "raw": "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n\r\n",
+    "should_keep_alive": true,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 1,
+    "method": "GET",
+    "query_string": "hail=all",
+    "fragment": "",
+    "request_path": "",
+    "request_url": "http://hypnotoad.org:1234?hail=all",
+    "port": 1234,
+    "num_headers": 0,
+    "headers": {
+
+    },
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "host:port terminated by a space",
+    "type": "HTTP_REQUEST",
+    "raw": "GET http://hypnotoad.org:1234 HTTP/1.1\r\n\r\n",
+    "should_keep_alive": true,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 1,
+    "method": "GET",
+    "query_string": "",
+    "fragment": "",
+    "request_path": "",
+    "request_url": "http://hypnotoad.org:1234",
+    "port": 1234,
+    "num_headers": 0,
+    "headers": {
+
+    },
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "PATCH request",
+    "type": "HTTP_REQUEST",
+    "raw": "PATCH /file.txt HTTP/1.1\r\nHost: www.example.com\r\nContent-Type: application/example\r\nIf-Match: \"e0023aa4e\"\r\nContent-Length: 10\r\n\r\ncccccccccc",
+    "should_keep_alive": true,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 1,
+    "method": "PATCH",
+    "query_string": "",
+    "fragment": "",
+    "request_path": "/file.txt",
+    "request_url": "/file.txt",
+    "num_headers": 4,
+    "headers": {
+      "Host": "www.example.com",
+      "Content-Type": "application/example",
+      "If-Match": "\"e0023aa4e\"",
+      "Content-Length": "10"
+    },
+    "body": "cccccccccc",
+    "strict": true
+  },
+  {
+    "name": "connect caps request",
+    "type": "HTTP_REQUEST",
+    "raw": "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\nUser-agent: Mozilla/1.1N\r\nProxy-authorization: basic aGVsbG86d29ybGQ=\r\n\r\n",
+    "should_keep_alive": false,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 0,
+    "method": "CONNECT",
+    "query_string": "",
+    "fragment": "",
+    "request_path": "",
+    "request_url": "HOME0.NETSCAPE.COM:443",
+    "num_headers": 2,
+    "upgrade": "",
+    "headers": {
+      "User-agent": "Mozilla/1.1N",
+      "Proxy-authorization": "basic aGVsbG86d29ybGQ="
+    },
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "utf-8 path request",
+    "type": "HTTP_REQUEST",
+    "strict": false,
+    "raw": "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\nHost: github.com\r\n\r\n",
+    "should_keep_alive": true,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 1,
+    "method": "GET",
+    "query_string": "q=1",
+    "fragment": "narf",
+    "request_path": "/δ¶/δt/pope",
+    "request_url": "/δ¶/δt/pope?q=1#narf",
+    "num_headers": 1,
+    "headers": {
+      "Host": "github.com"
+    },
+    "body": ""
+  },
+  {
+    "name": "hostname underscore",
+    "type": "HTTP_REQUEST",
+    "strict": false,
+    "raw": "CONNECT home_0.netscape.com:443 HTTP/1.0\r\nUser-agent: Mozilla/1.1N\r\nProxy-authorization: basic aGVsbG86d29ybGQ=\r\n\r\n",
+    "should_keep_alive": false,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 0,
+    "method": "CONNECT",
+    "query_string": "",
+    "fragment": "",
+    "request_path": "",
+    "request_url": "home_0.netscape.com:443",
+    "num_headers": 2,
+    "upgrade": "",
+    "headers": {
+      "User-agent": "Mozilla/1.1N",
+      "Proxy-authorization": "basic aGVsbG86d29ybGQ="
+    },
     "body": ""
   }
 ]
\ No newline at end of file
diff --git a/spec/support/responses.json b/spec/support/responses.json
index 96cb793..6dde20b 100644
--- a/spec/support/responses.json
+++ b/spec/support/responses.json
@@ -19,7 +19,8 @@
       "Server": "gws",
       "Content-Length": "219  "
     },
-    "body": "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<TITLE>301 Moved</TITLE></HEAD><BODY>\n<H1>301 Moved</H1>\nThe document has moved\n<A HREF=\"http://www.google.com/\">here</A>.\r\n</BODY></HTML>\r\n"
+    "body": "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<TITLE>301 Moved</TITLE></HEAD><BODY>\n<H1>301 Moved</H1>\nThe document has moved\n<A HREF=\"http://www.google.com/\">here</A>.\r\n</BODY></HTML>\r\n",
+    "strict": true
   },
   {
     "name": "no content-length response",
@@ -38,14 +39,15 @@
       "Content-Type": "text/xml; charset=utf-8",
       "Connection": "close"
     },
-    "body": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <SOAP-ENV:Body>\n    <SOAP-ENV:Fault>\n       <faultcode>SOAP-ENV:Client</faultcode>\n       <faultstring>Client Error</faultstring>\n    </SOAP-ENV:Fault>\n  </SOAP-ENV:Body>\n</SOAP-ENV:Envelope>"
+    "body": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <SOAP-ENV:Body>\n    <SOAP-ENV:Fault>\n       <faultcode>SOAP-ENV:Client</faultcode>\n       <faultstring>Client Error</faultstring>\n    </SOAP-ENV:Fault>\n  </SOAP-ENV:Body>\n</SOAP-ENV:Envelope>",
+    "strict": true
   },
   {
     "name": "404 no headers no body",
     "type": "HTTP_RESPONSE",
     "raw": "HTTP/1.1 404 Not Found\r\n\r\n",
-    "should_keep_alive": true,
-    "message_complete_on_eof": false,
+    "should_keep_alive": false,
+    "message_complete_on_eof": true,
     "http_major": 1,
     "http_minor": 1,
     "status_code": 404,
@@ -54,14 +56,15 @@
 
     },
     "body_size": 0,
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "301 no response phrase",
     "type": "HTTP_RESPONSE",
     "raw": "HTTP/1.1 301\r\n\r\n",
-    "should_keep_alive": true,
-    "message_complete_on_eof": false,
+    "should_keep_alive": false,
+    "message_complete_on_eof": true,
     "http_major": 1,
     "http_minor": 1,
     "status_code": 301,
@@ -69,7 +72,8 @@
     "headers": {
 
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "200 trailing space on chunked body",
@@ -86,7 +90,8 @@
       "Transfer-Encoding": "chunked"
     },
     "body_size": 65,
-    "body": "This is the data in the first chunk\r\nand this is the second one\r\n"
+    "body": "This is the data in the first chunk\r\nand this is the second one\r\n",
+    "strict": true
   },
   {
     "name": "no carriage ret",
@@ -102,7 +107,8 @@
       "Content-Type": "text/html; charset=utf-8",
       "Connection": "close"
     },
-    "body": "these headers are from http://news.ycombinator.com/"
+    "body": "these headers are from http://news.ycombinator.com/",
+    "strict": true
   },
   {
     "name": "proxy connection",
@@ -120,7 +126,8 @@
       "Proxy-Connection": "close",
       "Date": "Thu, 31 Dec 2009 20:55:48 +0000"
     },
-    "body": "hello world"
+    "body": "hello world",
+    "strict": true
   },
   {
     "name": "underscore header key",
@@ -138,7 +145,8 @@
       "Content-Length": "0",
       "DCLK_imp": "v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o"
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "bonjourmadame.fr",
@@ -161,28 +169,8 @@
       "Content-Type": "text/html; charset=UTF-8",
       "Connection": "keep-alive"
     },
-    "body": ""
-  },
-  {
-    "name": "field space",
-    "type": "HTTP_RESPONSE",
-    "raw": "HTTP/1.1 200 OK\r\nServer: Microsoft-IIS/6.0\r\nX-Powered-By: ASP.NET\r\nen-US Content-Type: text/xml\r\nContent-Type: text/xml\r\nContent-Length: 16\r\nDate: Fri, 23 Jul 2010 18:45:38 GMT\r\nConnection: keep-alive\r\n\r\n<xml>hello</xml>",
-    "should_keep_alive": true,
-    "message_complete_on_eof": false,
-    "http_major": 1,
-    "http_minor": 1,
-    "status_code": 200,
-    "num_headers": 7,
-    "headers": {
-      "Server": "Microsoft-IIS/6.0",
-      "X-Powered-By": "ASP.NET",
-      "en-US Content-Type": "text/xml",
-      "Content-Type": "text/xml",
-      "Content-Length": "16",
-      "Date": "Fri, 23 Jul 2010 18:45:38 GMT",
-      "Connection": "keep-alive"
-    },
-    "body": "<xml>hello</xml>"
+    "body": "",
+    "strict": true
   },
   {
     "name": "field underscore",
@@ -207,7 +195,8 @@
       "Content-Type": "text/html",
       "Connection": "close"
     },
-    "body": ""
+    "body": "",
+    "strict": true
   },
   {
     "name": "non-ASCII in status line",
@@ -224,6 +213,163 @@
       "Content-Length": "0",
       "Connection": "close"
     },
-    "body": ""
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "http version 0.9",
+    "type": "HTTP_RESPONSE",
+    "raw": "HTTP/0.9 200 OK\r\n\r\n",
+    "should_keep_alive": false,
+    "message_complete_on_eof": true,
+    "http_major": 0,
+    "http_minor": 9,
+    "status_code": 200,
+    "num_headers": 0,
+    "headers": {
+
+    },
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "neither content-length nor transfer-encoding response",
+    "type": "HTTP_RESPONSE",
+    "raw": "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nhello world",
+    "should_keep_alive": false,
+    "message_complete_on_eof": true,
+    "http_major": 1,
+    "http_minor": 1,
+    "status_code": 200,
+    "num_headers": 1,
+    "headers": {
+      "Content-Type": "text/plain"
+    },
+    "body": "hello world",
+    "strict": true
+  },
+  {
+    "name": "HTTP/1.0 with keep-alive and EOF-terminated 200 status",
+    "type": "HTTP_RESPONSE",
+    "raw": "HTTP/1.0 200 OK\r\nConnection: keep-alive\r\n\r\n",
+    "should_keep_alive": false,
+    "message_complete_on_eof": true,
+    "http_major": 1,
+    "http_minor": 0,
+    "status_code": 200,
+    "num_headers": 1,
+    "headers": {
+      "Connection": "keep-alive"
+    },
+    "body_size": 0,
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "HTTP/1.0 with keep-alive and a 204 status",
+    "type": "HTTP_RESPONSE",
+    "raw": "HTTP/1.0 204 No content\r\nConnection: keep-alive\r\n\r\n",
+    "should_keep_alive": true,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 0,
+    "status_code": 204,
+    "num_headers": 1,
+    "headers": {
+      "Connection": "keep-alive"
+    },
+    "body_size": 0,
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "HTTP/1.1 with an EOF-terminated 200 status",
+    "type": "HTTP_RESPONSE",
+    "raw": "HTTP/1.1 200 OK\r\n\r\n",
+    "should_keep_alive": false,
+    "message_complete_on_eof": true,
+    "http_major": 1,
+    "http_minor": 1,
+    "status_code": 200,
+    "num_headers": 0,
+    "headers": {
+
+    },
+    "body_size": 0,
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "HTTP/1.1 with a 204 status",
+    "type": "HTTP_RESPONSE",
+    "raw": "HTTP/1.1 204 No content\r\n\r\n",
+    "should_keep_alive": true,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 1,
+    "status_code": 204,
+    "num_headers": 0,
+    "headers": {
+
+    },
+    "body_size": 0,
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "HTTP/1.1 with a 204 status and keep-alive disabled",
+    "type": "HTTP_RESPONSE",
+    "raw": "HTTP/1.1 204 No content\r\nConnection: close\r\n\r\n",
+    "should_keep_alive": false,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 1,
+    "status_code": 204,
+    "num_headers": 1,
+    "headers": {
+      "Connection": "close"
+    },
+    "body_size": 0,
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "HTTP/1.1 with chunked endocing and a 200 response",
+    "type": "HTTP_RESPONSE",
+    "raw": "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n",
+    "should_keep_alive": true,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 1,
+    "status_code": 200,
+    "num_headers": 1,
+    "headers": {
+      "Transfer-Encoding": "chunked"
+    },
+    "body_size": 0,
+    "body": "",
+    "strict": true
+  },
+  {
+    "name": "field space",
+    "type": "HTTP_RESPONSE",
+    "strict": false,
+    "raw": "HTTP/1.1 200 OK\r\nServer: Microsoft-IIS/6.0\r\nX-Powered-By: ASP.NET\r\nen-US Content-Type: text/xml\r\nContent-Type: text/xml\r\nContent-Length: 16\r\nDate: Fri, 23 Jul 2010 18:45:38 GMT\r\nConnection: keep-alive\r\n\r\n<xml>hello</xml>",
+    "should_keep_alive": true,
+    "message_complete_on_eof": false,
+    "http_major": 1,
+    "http_minor": 1,
+    "status_code": 200,
+    "num_headers": 7,
+    "headers": {
+      "Server": "Microsoft-IIS/6.0",
+      "X-Powered-By": "ASP.NET",
+      "en-US Content-Type": "text/xml",
+      "Content-Type": "text/xml",
+      "Content-Length": "16",
+      "Date": "Fri, 23 Jul 2010 18:45:38 GMT",
+      "Connection": "keep-alive"
+    },
+    "body": "<xml>hello</xml>"
   }
 ]
\ No newline at end of file
diff --git a/tasks/compile.rake b/tasks/compile.rake
index a9f1f1b..22d6f6d 100644
--- a/tasks/compile.rake
+++ b/tasks/compile.rake
@@ -1,4 +1,4 @@
-require 'rake/gempackagetask'
+require 'rubygems/package_task'
 require 'rake/extensiontask'
 require 'rake/javaextensiontask'
 
@@ -6,7 +6,7 @@ def gemspec
   @clean_gemspec ||= eval(File.read(File.expand_path('../../http_parser.rb.gemspec', __FILE__)))
 end
 
-Rake::GemPackageTask.new(gemspec) do |pkg|
+Gem::PackageTask.new(gemspec) do |pkg|
 end
 
 if RUBY_PLATFORM =~ /java/
diff --git a/tasks/fixtures.rake b/tasks/fixtures.rake
index 586310e..b5d36ef 100644
--- a/tasks/fixtures.rake
+++ b/tasks/fixtures.rake
@@ -14,13 +14,18 @@ task :fixtures => :submodules do
     tmp.gsub!('TRUE', 'true')
     tmp.gsub!('FALSE', 'false')
 
+    # mark strict mode tests
+    tmp.gsub!(%r|#if\s+!HTTP_PARSER_STRICT(.+?)#endif\s*/\*\s*!HTTP_PARSER_STRICT.+\n|m){
+      $1.gsub(/^(.+,\.type= .+)$/, "\\1\n,  .strict= false")
+    }
+
     # remove macros and comments
     tmp.gsub!(/^#(if|elif|endif|define).+$/,'')
     tmp.gsub!(/\/\*(.+?)\*\/$/,'')
 
     # HTTP_* enums become strings
     tmp.gsub!(/(= )(HTTP_\w+)/){
-      "#{$1}#{$2.dump}"
+      "#{$1}#{$2.sub('MSEARCH','M-SEARCH').dump}"
     }
 
     # join multiline strings for body and raw data
@@ -55,6 +60,7 @@ task :fixtures => :submodules do
     results.map{ |res|
       res[:headers] and res[:headers] = Hash[*res[:headers].flatten]
       res[:method]  and res[:method].gsub!(/^HTTP_/, '')
+      res[:strict] = true unless res.has_key?(:strict)
     }
 
     # write to a file

-- 
ruby-http-parser.rb.git



More information about the Pkg-ruby-extras-commits mailing list