http_tools 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +3 -3
- data/bench/parser/request_bench.rb +9 -0
- data/lib/http_tools.rb +26 -9
- data/lib/http_tools/builder.rb +1 -1
- data/lib/http_tools/encoding.rb +10 -9
- data/lib/http_tools/parser.rb +12 -17
- data/profile/parser/request_profile.rb +13 -5
- data/test/cover.rb +5 -5
- data/test/parser/request_test.rb +26 -4
- data/test/parser/response_test.rb +1 -4
- data/test/runner.rb +1 -10
- metadata +23 -42
data/README.rdoc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= HTTPTools
|
1
|
+
= HTTPTools {<img src=https://secure.travis-ci.org/matsadler/http_tools.png>}[http://travis-ci.org/matsadler/http_tools]
|
2
2
|
|
3
3
|
HTTPTools is a collection of lower level utilities to aid working with HTTP,
|
4
4
|
including a fast-as-possible pure Ruby HTTP parser.
|
@@ -12,9 +12,9 @@ Written purely in Ruby, with no dependencies outside of the standard library, it
|
|
12
12
|
should run across all Ruby implementations compatible with 1.8 or later, and
|
13
13
|
install in environments without a compiler available.
|
14
14
|
|
15
|
-
|
15
|
+
Tests are currently run on travis-ci[http://travis-ci.org/] against Ruby 1.8.6, 1.8.7, 1.9.2, 1.9.3, JRuby, Rubinius, Rubinius 2, and Ruby Enterprise Edition. Additionally tests are run against MacRuby 0.10
|
16
16
|
|
17
|
-
Performance tuning is mainly aimed at
|
17
|
+
Performance tuning is mainly aimed at Ruby 1.9, with Ruby 1.8 and JRuby taken in to consideration. JRuby is generally fastest.
|
18
18
|
|
19
19
|
== HTTPTools::Parser
|
20
20
|
|
@@ -29,6 +29,15 @@ Benchmark.bm(41) do |x|
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
x.report("HTTPTools::Parser (reset, with env)") do
|
33
|
+
parser = HTTPTools::Parser.new
|
34
|
+
10_000.times do
|
35
|
+
parser << request
|
36
|
+
parser.env
|
37
|
+
parser.reset
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
32
41
|
begin
|
33
42
|
require 'rubygems'
|
34
43
|
require 'http/parser'
|
data/lib/http_tools.rb
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
require_base = File.expand_path('../http_tools', __FILE__)
|
2
|
+
require require_base + '/encoding'
|
3
|
+
require require_base + '/parser'
|
4
|
+
require require_base + '/builder'
|
5
|
+
|
1
6
|
module HTTPTools
|
2
7
|
STATUS_CODES = {
|
3
8
|
:continue => 100,
|
@@ -9,6 +14,8 @@ module HTTPTools
|
|
9
14
|
:no_content => 204,
|
10
15
|
:reset_content => 205,
|
11
16
|
:partial_content => 206,
|
17
|
+
:multi_status => 207,
|
18
|
+
:im_used => 226,
|
12
19
|
:multiple_choices => 300,
|
13
20
|
:moved_permanently => 301,
|
14
21
|
:found => 302,
|
@@ -34,12 +41,19 @@ module HTTPTools
|
|
34
41
|
:unsupported_media_type => 415,
|
35
42
|
:requested_range_not_satisfiable => 416,
|
36
43
|
:expectation_failed => 417,
|
44
|
+
:im_a_teapot => 418,
|
45
|
+
:unprocessable_entity => 422,
|
46
|
+
:locked => 423,
|
47
|
+
:failed_dependency => 424,
|
48
|
+
:upgrade_required => 426,
|
37
49
|
:internal_server_error => 500,
|
38
50
|
:not_implemented => 501,
|
39
51
|
:bad_gateway => 502,
|
40
52
|
:service_unavailable => 503,
|
41
53
|
:gateway_timeout => 504,
|
42
|
-
:http_version_not_supported => 505
|
54
|
+
:http_version_not_supported => 505,
|
55
|
+
:variant_also_negotiates => 506,
|
56
|
+
:insufficient_storage => 507}.freeze
|
43
57
|
|
44
58
|
STATUS_DESCRIPTIONS = {
|
45
59
|
100 => "Continue",
|
@@ -51,6 +65,8 @@ module HTTPTools
|
|
51
65
|
204 => "No Content",
|
52
66
|
205 => "Reset Content",
|
53
67
|
206 => "Partial Content",
|
68
|
+
207 => "Multi-Status",
|
69
|
+
226 => "IM Used",
|
54
70
|
300 => "Multiple Choices",
|
55
71
|
301 => "Moved Permanently",
|
56
72
|
302 => "Found",
|
@@ -76,12 +92,19 @@ module HTTPTools
|
|
76
92
|
415 => "Unsupported Media Type",
|
77
93
|
416 => "Requested Range Not Satisfiable",
|
78
94
|
417 => "Expectation Failed",
|
95
|
+
418 => "I'm a teapot",
|
96
|
+
422 => "Unprocessable Entity",
|
97
|
+
423 => "Locked",
|
98
|
+
424 => "Failed Dependency",
|
99
|
+
426 => "Upgrade Required",
|
79
100
|
500 => "Internal Server Error",
|
80
101
|
501 => "Not Implemented",
|
81
102
|
502 => "Bad Gateway",
|
82
103
|
503 => "Service Unavailable",
|
83
104
|
504 => "Gateway Timeout",
|
84
|
-
505 => "HTTP Version Not Supported"
|
105
|
+
505 => "HTTP Version Not Supported",
|
106
|
+
506 => "Variant Also Negotiates",
|
107
|
+
507 => "Insufficient Storage"}.freeze
|
85
108
|
STATUS_DESCRIPTIONS.values.each {|val| val.freeze}
|
86
109
|
|
87
110
|
# :stopdoc: hide from rdoc as it makes a mess
|
@@ -103,10 +126,4 @@ module HTTPTools
|
|
103
126
|
EndOfMessageError = Class.new(ParseError)
|
104
127
|
MessageIncompleteError = Class.new(EndOfMessageError)
|
105
128
|
EmptyMessageError = Class.new(MessageIncompleteError)
|
106
|
-
|
107
|
-
require_base = File.dirname(__FILE__) + '/http_tools/'
|
108
|
-
autoload :Encoding, require_base + 'encoding'
|
109
|
-
autoload :Parser, require_base + 'parser'
|
110
|
-
autoload :Builder, require_base + 'builder'
|
111
|
-
|
112
|
-
end
|
129
|
+
end
|
data/lib/http_tools/builder.rb
CHANGED
@@ -43,7 +43,7 @@ module HTTPTools
|
|
43
43
|
def format_headers(headers, buffer="")
|
44
44
|
headers.each do |key, value|
|
45
45
|
if value.respond_to?(:each_line)
|
46
|
-
value.each_line {|val| buffer << "#{key}: #{val
|
46
|
+
value.each_line {|val| val.chomp!; buffer << "#{key}: #{val}\r\n"}
|
47
47
|
elsif value.respond_to?(:each)
|
48
48
|
value.each {|val| buffer << "#{key}: #{val}\r\n"}
|
49
49
|
else
|
data/lib/http_tools/encoding.rb
CHANGED
@@ -15,7 +15,6 @@ module HTTPTools
|
|
15
15
|
SPACE = " ".freeze
|
16
16
|
AMPERSAND = "&".freeze
|
17
17
|
EQUALS = "=".freeze
|
18
|
-
CHUNK_FORMAT = "%x\r\n%s\r\n".freeze
|
19
18
|
# :startdoc:
|
20
19
|
|
21
20
|
module_function
|
@@ -25,7 +24,7 @@ module HTTPTools
|
|
25
24
|
# URL encode a string, eg "le café" becomes "le+caf%c3%a9"
|
26
25
|
#
|
27
26
|
def url_encode(string)
|
28
|
-
string.gsub(/[^a-
|
27
|
+
string.gsub(/[^a-z0-9._~-]+/i) do |match|
|
29
28
|
length = match.respond_to?(:bytesize) ? match.bytesize : match.length
|
30
29
|
PERCENT + match.unpack(HEX_BIG_ENDIAN_2_BYTES * length).join(PERCENT)
|
31
30
|
end
|
@@ -36,7 +35,7 @@ module HTTPTools
|
|
36
35
|
# URL decode a string, eg "le+caf%c3%a9" becomes "le café"
|
37
36
|
#
|
38
37
|
def url_decode(string)
|
39
|
-
string.tr(PLUS, SPACE).gsub(/(%[0-9a-
|
38
|
+
string.tr(PLUS, SPACE).gsub(/(%[0-9a-f]{2})+/i) do |match|
|
40
39
|
r = [match.delete(PERCENT)].pack(HEX_BIG_ENDIAN_REPEATING)
|
41
40
|
r.respond_to?(:force_encoding) ? r.force_encoding(string.encoding) : r
|
42
41
|
end
|
@@ -72,15 +71,17 @@ module HTTPTools
|
|
72
71
|
# an array value, eg "lang=en&lang=fr" becomes {"lang" => ["en", "fr"]}
|
73
72
|
#
|
74
73
|
def www_form_decode(string)
|
75
|
-
|
74
|
+
out = {}
|
75
|
+
string.split(AMPERSAND).each do |key_value|
|
76
76
|
key, value = key_value.split(EQUALS)
|
77
77
|
key, value = url_decode(key), url_decode(value)
|
78
|
-
if
|
79
|
-
|
78
|
+
if out.key?(key)
|
79
|
+
out[key] = [*out[key]].push(value)
|
80
80
|
else
|
81
|
-
|
81
|
+
out[key] = value
|
82
82
|
end
|
83
83
|
end
|
84
|
+
out
|
84
85
|
end
|
85
86
|
|
86
87
|
# :call-seq:
|
@@ -94,8 +95,8 @@ module HTTPTools
|
|
94
95
|
# passing an empty string or nil will generate the empty chunk.
|
95
96
|
#
|
96
97
|
def transfer_encoding_chunked_encode(string)
|
97
|
-
if string && string.length > 0
|
98
|
-
|
98
|
+
if string && (length = string.length) > 0
|
99
|
+
"#{length.to_s(16)}\r\n#{string}\r\n"
|
99
100
|
else
|
100
101
|
"0\r\n"
|
101
102
|
end
|
data/lib/http_tools/parser.rb
CHANGED
@@ -29,6 +29,7 @@ module HTTPTools
|
|
29
29
|
#
|
30
30
|
class Parser
|
31
31
|
# :stopdoc:
|
32
|
+
EMPTY = "".freeze
|
32
33
|
COLON = ":".freeze
|
33
34
|
KEY_TERMINATOR = ": ".freeze
|
34
35
|
CONTENT_LENGTH = "Content-Length".freeze
|
@@ -92,7 +93,7 @@ module HTTPTools
|
|
92
93
|
@force_trailer = nil
|
93
94
|
@max_chunk_size = nil
|
94
95
|
@status_code = nil
|
95
|
-
@
|
96
|
+
@header_complete = nil
|
96
97
|
@content_left = nil
|
97
98
|
@chunked = nil
|
98
99
|
@body = nil
|
@@ -131,15 +132,15 @@ module HTTPTools
|
|
131
132
|
def env
|
132
133
|
return unless @header_complete
|
133
134
|
env = PROTOTYPE_ENV.dup
|
134
|
-
env[REQUEST_METHOD] = @request_method
|
135
|
+
env[REQUEST_METHOD] = @request_method.upcase
|
135
136
|
env[PATH_INFO] = @path_info
|
136
137
|
env[QUERY_STRING] = @query_string
|
137
138
|
@header.each do |key, value|
|
138
139
|
upper_key = key.tr(LOWERCASE, UPPERCASE)
|
139
|
-
upper_key = HTTP_
|
140
|
-
env[upper_key] = value
|
140
|
+
upper_key[0,0] = HTTP_ unless NO_HTTP_.key?(upper_key)
|
141
|
+
env[upper_key.freeze] = value
|
141
142
|
end
|
142
|
-
host, port = env[HTTP_HOST].split(COLON)
|
143
|
+
host, port = env[HTTP_HOST].split(COLON) if env.key?(HTTP_HOST)
|
143
144
|
env[SERVER_NAME] = host
|
144
145
|
env[SERVER_PORT] = port || "80"
|
145
146
|
@trailer.each {|k, val| env[HTTP_ + k.tr(LOWERCASE, UPPERCASE)] = val}
|
@@ -207,7 +208,7 @@ module HTTPTools
|
|
207
208
|
# otherwise.
|
208
209
|
#
|
209
210
|
def header?
|
210
|
-
@
|
211
|
+
@header_complete
|
211
212
|
end
|
212
213
|
|
213
214
|
# :call-seq: parser.rest -> string
|
@@ -241,7 +242,7 @@ module HTTPTools
|
|
241
242
|
@request_uri = nil
|
242
243
|
@version = nil
|
243
244
|
@status_code = nil
|
244
|
-
@
|
245
|
+
@header_complete = nil
|
245
246
|
@header = {}
|
246
247
|
@trailer = {}
|
247
248
|
@last_key = nil
|
@@ -290,9 +291,7 @@ module HTTPTools
|
|
290
291
|
alias on add_listener
|
291
292
|
|
292
293
|
def inspect # :nodoc:
|
293
|
-
|
294
|
-
str[-1, 0] = " #{posstr} #{state}"
|
295
|
-
str
|
294
|
+
super.sub(/ .*>$/, " #{posstr} #{state}>")
|
296
295
|
end
|
297
296
|
|
298
297
|
private
|
@@ -300,7 +299,6 @@ module HTTPTools
|
|
300
299
|
@request_method = @buffer.scan(/[a-z]+ /i)
|
301
300
|
if @request_method
|
302
301
|
@request_method.chop!
|
303
|
-
@request_method.upcase!
|
304
302
|
uri
|
305
303
|
elsif @buffer.check(/HTTP\//i)
|
306
304
|
response_http_version
|
@@ -319,7 +317,7 @@ module HTTPTools
|
|
319
317
|
@path_info = @request_uri.dup
|
320
318
|
@path_info.slice!(/^([a-z0-9+.-]*:\/\/)?[^\/]+/i)
|
321
319
|
@query_string = @path_info.slice!(/\?[a-z0-9;\/?:@&=+$,%_.!~*')(-]*/i)
|
322
|
-
@query_string ? @query_string
|
320
|
+
@query_string ? @query_string[0] = EMPTY : @query_string = ""
|
323
321
|
request_http_version
|
324
322
|
elsif @buffer.check(/[a-z0-9;\/?:@&=+$,%_.!~*')(#-]+\Z/i)
|
325
323
|
:uri
|
@@ -332,7 +330,6 @@ module HTTPTools
|
|
332
330
|
@version = @buffer.scan(/ HTTP\/[0-9]+\.[0-9x]+\r\n/i)
|
333
331
|
if @version
|
334
332
|
@version.strip!
|
335
|
-
@version.upcase!
|
336
333
|
key_or_newline
|
337
334
|
elsif @buffer.skip(/\r\n/i)
|
338
335
|
key_or_newline
|
@@ -348,7 +345,6 @@ module HTTPTools
|
|
348
345
|
@version = @buffer.scan(/HTTP\/[0-9]+\.[0-9x]+ /i)
|
349
346
|
if @version
|
350
347
|
@version.chop!
|
351
|
-
@version.upcase!
|
352
348
|
status
|
353
349
|
elsif @buffer.eos? ||
|
354
350
|
@buffer.check(/H(T(T(P(\/(\d+(\.(\d+\r?)?)?)?)?)?)?)?\Z/i)
|
@@ -417,7 +413,7 @@ module HTTPTools
|
|
417
413
|
if @header.key?(@last_key)
|
418
414
|
@header[@last_key] << "\n#{value}"
|
419
415
|
else
|
420
|
-
@header[@last_key] = value
|
416
|
+
@header[@last_key.freeze] = value
|
421
417
|
end
|
422
418
|
if CONTENT_LENGTH.casecmp(@last_key) == 0
|
423
419
|
@content_left = value.to_i
|
@@ -433,7 +429,6 @@ module HTTPTools
|
|
433
429
|
end
|
434
430
|
|
435
431
|
def start_body
|
436
|
-
@header_done = true
|
437
432
|
if @request_method && !(@content_left || @chunked) ||
|
438
433
|
NO_BODY.key?(@status_code) || @force_no_body
|
439
434
|
end_of_message
|
@@ -541,7 +536,7 @@ module HTTPTools
|
|
541
536
|
if @trailer.key?(@last_key)
|
542
537
|
@trailer[@last_key] << "\n#{value}"
|
543
538
|
else
|
544
|
-
@trailer[@last_key] = value
|
539
|
+
@trailer[@last_key.freeze] = value
|
545
540
|
end
|
546
541
|
trailer_key_or_newline
|
547
542
|
elsif @buffer.eos? || @buffer.check(/[^\x00\n\x7f]+\Z/i)
|
@@ -1,12 +1,20 @@
|
|
1
1
|
base = File.expand_path(File.dirname(__FILE__) + '/../../lib')
|
2
2
|
require base + '/http_tools'
|
3
3
|
require 'rubygems'
|
4
|
-
require 'ruby-prof'
|
5
4
|
|
6
5
|
request = "GET / HTTP/1.1\r\nHost: example.com\r\nUser-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-gb) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16\r\nAccept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\nAccept-Language: en-gb\r\nAccept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\n\r\n"
|
7
6
|
parser = HTTPTools::Parser.new
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
# require 'ruby-prof'
|
9
|
+
# result = RubyProf.profile do
|
10
|
+
# parser << request
|
11
|
+
# end
|
12
|
+
# RubyProf::FlatPrinter.new(result).print(STDOUT, 0)
|
13
|
+
|
14
|
+
require 'perftools'
|
15
|
+
PerfTools::CpuProfiler.start("/tmp/http_tools_parser_request_profile") do
|
16
|
+
100_000.times do
|
17
|
+
parser << request
|
18
|
+
parser.reset
|
19
|
+
end
|
20
|
+
end
|
data/test/cover.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
#!/opt/local/bin/ruby1.9 -w
|
2
|
-
|
3
1
|
require 'coverage' # >= ruby 1.9 only
|
4
2
|
|
5
3
|
at_exit do
|
6
|
-
testing = Dir["
|
4
|
+
testing = Dir[File.expand_path("../../lib/**/*.rb", __FILE__)]
|
7
5
|
|
8
6
|
results = Coverage.result.select {|key, value| testing.include?(key)}
|
9
7
|
|
@@ -15,9 +13,11 @@ at_exit do
|
|
15
13
|
results.each do |key, value|
|
16
14
|
next unless value.include?(0)
|
17
15
|
puts key
|
16
|
+
puts " line calls code"
|
18
17
|
puts
|
19
18
|
File.readlines(key).zip(value).each_with_index do |(line, val), i|
|
20
|
-
print
|
19
|
+
print val == 0 ? "> " : " "
|
20
|
+
print "%3i %5s %s" % [(i + 1), val, line]
|
21
21
|
end
|
22
22
|
puts
|
23
23
|
puts
|
@@ -25,4 +25,4 @@ at_exit do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
Coverage.start
|
28
|
-
Dir["
|
28
|
+
Dir[File.expand_path("../**/*_test.rb", __FILE__)].each {|test| require test}
|
data/test/parser/request_test.rb
CHANGED
@@ -314,7 +314,7 @@ class ParserRequestTest < Test::Unit::TestCase
|
|
314
314
|
|
315
315
|
parser << "GET / HTTP/1.x\r\n\r\n"
|
316
316
|
|
317
|
-
assert_equal("HTTP/1.
|
317
|
+
assert_equal("HTTP/1.x", version)
|
318
318
|
end
|
319
319
|
|
320
320
|
def test_finish_without_body_trigger
|
@@ -455,7 +455,7 @@ class ParserRequestTest < Test::Unit::TestCase
|
|
455
455
|
|
456
456
|
parser << "get / HTTP/1.1\r\n\r\n"
|
457
457
|
|
458
|
-
assert_equal("
|
458
|
+
assert_equal("get", result)
|
459
459
|
end
|
460
460
|
|
461
461
|
def test_lowercase_http
|
@@ -466,7 +466,7 @@ class ParserRequestTest < Test::Unit::TestCase
|
|
466
466
|
|
467
467
|
parser << "GET / http/1.1\r\n\r\n"
|
468
468
|
|
469
|
-
assert_equal("
|
469
|
+
assert_equal("http/1.1", version)
|
470
470
|
end
|
471
471
|
|
472
472
|
def test_invalid_version
|
@@ -692,10 +692,32 @@ class ParserRequestTest < Test::Unit::TestCase
|
|
692
692
|
assert_equal(nil, env["rack.input"])
|
693
693
|
end
|
694
694
|
|
695
|
+
def test_env_lowercase_method
|
696
|
+
parser = HTTPTools::Parser.new
|
697
|
+
|
698
|
+
parser << "get /test?q=foo HTTP/1.1\r\n"
|
699
|
+
parser << "Host: www.example.com\r\n\r\n"
|
700
|
+
|
701
|
+
assert_equal("GET", parser.env["REQUEST_METHOD"])
|
702
|
+
end
|
703
|
+
|
704
|
+
def test_env_no_host
|
705
|
+
parser = HTTPTools::Parser.new
|
706
|
+
|
707
|
+
parser << "GET /test?q=foo HTTP/1.1\r\n\r\n"
|
708
|
+
|
709
|
+
assert_nothing_raised(NoMethodError) do
|
710
|
+
parser.env
|
711
|
+
end
|
712
|
+
assert_equal(nil, parser.env["HTTP_HOST"])
|
713
|
+
assert_equal(nil, parser.env["SERVER_NAME"])
|
714
|
+
assert_equal("80", parser.env["SERVER_PORT"])
|
715
|
+
end
|
716
|
+
|
695
717
|
def test_inspect
|
696
718
|
parser = HTTPTools::Parser.new
|
697
719
|
|
698
|
-
|
720
|
+
assert_match(/#<HTTPTools::Parser:0x[a-f0-9]+ line 1, char 1 start>/, parser.inspect)
|
699
721
|
end
|
700
722
|
|
701
723
|
end
|
@@ -24,7 +24,7 @@ class ParserResponseTest < Test::Unit::TestCase
|
|
24
24
|
|
25
25
|
parser << "HTTP/1.x 200 OK\r\n\r\n"
|
26
26
|
|
27
|
-
assert_equal("HTTP/1.
|
27
|
+
assert_equal("HTTP/1.x", version)
|
28
28
|
end
|
29
29
|
|
30
30
|
def test_ok
|
@@ -882,7 +882,6 @@ class ParserResponseTest < Test::Unit::TestCase
|
|
882
882
|
parser.add_listener(:header) do
|
883
883
|
code = parser.status_code
|
884
884
|
message = parser.message
|
885
|
-
headers = parser.header
|
886
885
|
end
|
887
886
|
parser.add_listener(:stream) {|chunk| body << chunk}
|
888
887
|
parser.add_listener(:finish) {remainder = parser.rest}
|
@@ -905,7 +904,6 @@ class ParserResponseTest < Test::Unit::TestCase
|
|
905
904
|
parser.add_listener(:header) do
|
906
905
|
code = parser.status_code
|
907
906
|
message = parser.message
|
908
|
-
headers = parser.header
|
909
907
|
end
|
910
908
|
parser.add_listener(:stream) {|chunk| body << chunk}
|
911
909
|
parser.add_listener(:finish) {remainder = parser.rest}
|
@@ -928,7 +926,6 @@ class ParserResponseTest < Test::Unit::TestCase
|
|
928
926
|
parser.add_listener(:header) do
|
929
927
|
code = parser.status_code
|
930
928
|
message = parser.message
|
931
|
-
headers = parser.header
|
932
929
|
end
|
933
930
|
parser.add_listener(:stream) {|chunk| body << chunk}
|
934
931
|
parser.add_listener(:finish) {remainder = parser.rest}
|
data/test/runner.rb
CHANGED
@@ -1,10 +1 @@
|
|
1
|
-
|
2
|
-
if defined? RUBY_DESCRIPTION
|
3
|
-
puts RUBY_DESCRIPTION
|
4
|
-
elsif defined? RUBY_ENGINE
|
5
|
-
puts "#{RUBY_ENGINE} #{RUBY_VERSION} (#{RELEASE_DATE} patchlevel #{RUBY_PATCHLEVEL}) [#{RUBY_PLATFORM}]"
|
6
|
-
else
|
7
|
-
puts "ruby #{RUBY_VERSION} (#{RELEASE_DATE} patchlevel #{RUBY_PATCHLEVEL}) [#{RUBY_PLATFORM}]"
|
8
|
-
end
|
9
|
-
|
10
|
-
Dir["**/*_test.rb"].each {|test| require File.expand_path(test)}
|
1
|
+
Dir[File.expand_path("../**/*_test.rb", __FILE__)].each {|test| require test}
|
metadata
CHANGED
@@ -1,33 +1,24 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: http_tools
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 4
|
9
|
-
- 1
|
10
|
-
version: 0.4.1
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.2
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Matthew Sadler
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2011-06-27 00:00:00 +01:00
|
19
|
-
default_executable:
|
12
|
+
date: 2011-09-25 00:00:00.000000000 Z
|
20
13
|
dependencies: []
|
21
|
-
|
22
|
-
|
14
|
+
description: A fast-as-possible pure Ruby HTTP parser plus associated lower level
|
15
|
+
utilities to aid working with HTTP and the web.
|
23
16
|
email: mat@sourcetagsandcodes.com
|
24
17
|
executables: []
|
25
|
-
|
26
18
|
extensions: []
|
27
|
-
|
28
|
-
extra_rdoc_files:
|
19
|
+
extra_rdoc_files:
|
29
20
|
- README.rdoc
|
30
|
-
files:
|
21
|
+
files:
|
31
22
|
- lib/http_tools/builder.rb
|
32
23
|
- lib/http_tools/encoding.rb
|
33
24
|
- lib/http_tools/parser.rb
|
@@ -53,42 +44,32 @@ files:
|
|
53
44
|
- example/websocket_client.rb
|
54
45
|
- example/websocket_server.rb
|
55
46
|
- README.rdoc
|
56
|
-
has_rdoc: true
|
57
47
|
homepage: http://github.com/matsadler/http_tools
|
58
48
|
licenses: []
|
59
|
-
|
60
49
|
post_install_message:
|
61
|
-
rdoc_options:
|
50
|
+
rdoc_options:
|
62
51
|
- --main
|
63
52
|
- README.rdoc
|
64
53
|
- --charset
|
65
54
|
- utf-8
|
66
|
-
require_paths:
|
55
|
+
require_paths:
|
67
56
|
- lib
|
68
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
58
|
none: false
|
70
|
-
requirements:
|
71
|
-
- -
|
72
|
-
- !ruby/object:Gem::Version
|
73
|
-
|
74
|
-
|
75
|
-
- 0
|
76
|
-
version: "0"
|
77
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
64
|
none: false
|
79
|
-
requirements:
|
80
|
-
- -
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
|
83
|
-
segments:
|
84
|
-
- 0
|
85
|
-
version: "0"
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
86
69
|
requirements: []
|
87
|
-
|
88
70
|
rubyforge_project:
|
89
|
-
rubygems_version: 1.
|
71
|
+
rubygems_version: 1.8.10
|
90
72
|
signing_key:
|
91
73
|
specification_version: 3
|
92
74
|
summary: Pure Ruby HTTP parser and friends
|
93
75
|
test_files: []
|
94
|
-
|