[DRE-commits] [ruby-http-parser.rb] 01/07: Imported Upstream version 0.6.0
Praveen Arimbrathodiyil
praveen at moszumanska.debian.org
Wed Apr 2 17:38:57 UTC 2014
This is an automated email from the git hooks/post-receive script.
praveen pushed a commit to branch master
in repository ruby-http-parser.rb.
commit dd0028f0801693c82e81be9c11a9d73e8ebf75d0
Author: Praveen Arimbrathodiyil <praveen at debian.org>
Date: Wed Apr 2 21:46:00 2014 +0530
Imported Upstream version 0.6.0
---
.gitmodules | 6 +-
Gemfile | 2 +-
Gemfile.lock | 15 +-
README.md | 97 +-
bench/standalone.rb | 23 +
bench/thin.rb | 1 +
.../org/ruby_http_parser/RubyHttpParser.java | 205 +-
ext/ruby_http_parser/ruby_http_parser.c | 51 +-
.../vendor/http-parser-java/LICENSE-MIT | 44 -
.../vendor/http-parser-java/Makefile | 41 -
.../vendor/http-parser-java/README.md | 51 -
ext/ruby_http_parser/vendor/http-parser-java/TODO | 22 -
.../vendor/http-parser-java/build.xml | 74 -
.../vendor/http-parser-java/compile | 1 -
.../vendor/http-parser-java/ext/primitives.jar | Bin 54971 -> 0 bytes
.../vendor/http-parser-java/http_parser.c | 1644 ----------------
.../vendor/http-parser-java/http_parser.h | 183 --
.../src/impl/http_parser/HTTPCallback.java | 8 -
.../src/impl/http_parser/HTTPDataCallback.java | 34 -
.../src/impl/http_parser/HTTPErrorCallback.java | 12 -
.../src/impl/http_parser/HTTPException.java | 9 -
.../src/impl/http_parser/HTTPMethod.java | 102 -
.../src/impl/http_parser/HTTPParser.java | 36 -
.../src/impl/http_parser/ParserSettings.java | 323 ---
.../src/impl/http_parser/ParserType.java | 13 -
.../src/impl/http_parser/Util.java | 111 --
.../src/impl/http_parser/lolevel/HTTPCallback.java | 5 -
.../impl/http_parser/lolevel/HTTPDataCallback.java | 25 -
.../http_parser/lolevel/HTTPErrorCallback.java | 7 -
.../src/impl/http_parser/lolevel/HTTPParser.java | 2068 --------------------
.../impl/http_parser/lolevel/ParserSettings.java | 79 -
.../src/test/http_parser/lolevel/Message.java | 324 ---
.../src/test/http_parser/lolevel/Requests.java | 69 -
.../src/test/http_parser/lolevel/Responses.java | 51 -
.../src/test/http_parser/lolevel/Test.java | 15 -
.../lolevel/TestHeaderOverflowError.java | 47 -
.../src/test/http_parser/lolevel/TestLoaderNG.java | 223 ---
.../lolevel/TestNoOverflowLongBody.java | 61 -
.../src/test/http_parser/lolevel/UnitTest.java | 116 --
.../src/test/http_parser/lolevel/Upgrade.java | 26 -
.../src/test/http_parser/lolevel/Util.java | 165 --
.../http_parser/lolevel/WrongContentLength.java | 58 -
.../vendor/http-parser-java/test.c | 2068 --------------------
.../vendor/http-parser-java/test_permutations | 1 -
.../vendor/http-parser-java/test_unit | 1 -
.../vendor/http-parser-java/test_utf8 | 1 -
.../vendor/http-parser-java/tests.dumped | 686 -------
.../vendor/http-parser-java/tests.utf8 | 17 -
.../http-parser-java/tools/byte_constants.rb | 6 -
.../vendor/http-parser-java/tools/const_char.rb | 13 -
.../vendor/http-parser-java/tools/lowcase.rb | 15 -
.../vendor/http-parser-java/tools/parse_tests.rb | 33 -
.../vendor/http-parser/CONTRIBUTIONS | 4 -
.../vendor/http-parser/LICENSE-MIT | 19 -
ext/ruby_http_parser/vendor/http-parser/Makefile | 41 -
ext/ruby_http_parser/vendor/http-parser/README.md | 171 --
.../vendor/http-parser/http_parser.c | 1644 ----------------
.../vendor/http-parser/http_parser.h | 183 --
ext/ruby_http_parser/vendor/http-parser/test.c | 1952 ------------------
http_parser.rb.gemspec | 5 +-
metadata.yml | 209 --
spec/parser_spec.rb | 58 +-
spec/support/requests.json | 260 ++-
spec/support/responses.json | 218 ++-
tasks/compile.rake | 4 +-
tasks/fixtures.rake | 8 +-
66 files changed, 692 insertions(+), 13372 deletions(-)
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..35dad45 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
A simple callback-based HTTP request/response parser for writing http
servers, clients and proxies.
-This gem is built on top of [joyent/http-parser](http://github.com/joyent/http-parser) and its java port [a2800276/http-parser.java](http://github.com/a2800276/http-parser.java).
+This gem is built on top of [joyent/http-parser](http://github.com/joyent/http-parser) and its java port [http-parser/http-parser.java](http://github.com/http-parser/http-parser.java).
## Supported Platforms
@@ -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/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 [...]
-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 [...]
-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..9a406f8 100644
--- a/http_parser.rb.gemspec
+++ b/http_parser.rb.gemspec
@@ -1,11 +1,12 @@
Gem::Specification.new do |s|
s.name = "http_parser.rb"
- s.version = "0.5.3"
+ s.version = "0.6.0"
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"
s.authors = ["Marc-Andre Cournoyer", "Aman Gupta"]
s.email = ["macournoyer at gmail.com", "aman at tmm1.net"]
+ s.license = 'MIT'
s.homepage = "http://github.com/tmm1/http_parser.rb"
s.files = `git ls-files`.split("\n") + Dir['ext/ruby_http_parser/vendor/**/*']
@@ -16,6 +17,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
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-http-parser.rb.git
More information about the Pkg-ruby-extras-commits
mailing list