http_tools 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|