minhttp 0.0.8 → 0.0.9

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.8
1
+ 0.0.9
@@ -0,0 +1,32 @@
1
+ module MinHttp
2
+ class Chunk
3
+ def initialize(body)
4
+ @body = body
5
+ @newbody = ""
6
+ end
7
+
8
+ def read_chunk_size
9
+ chunk_info, @body = @body.split("\r\n", 2)
10
+ chunk_info.to_i(16)
11
+ end
12
+
13
+ def read_chunk
14
+ @newbody << @body[0, @chunk_size]
15
+ new_body_len = @body.length - @chunk_size
16
+ @body = @body[@chunk_size+2, new_body_len-2]
17
+ end
18
+
19
+ def parse
20
+ @length = 0
21
+ @chunk_size = read_chunk_size
22
+
23
+ while (@chunk_size > 0)
24
+ read_chunk
25
+ @length = @length + @chunk_size
26
+ @chunk_size = read_chunk_size
27
+ end
28
+
29
+ return @newbody
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ module MinHttp
2
+
3
+ class Chunk
4
+ def initialize(header, body)
5
+ @header = header
6
+ @body = body
7
+ @newbody = ""
8
+ end
9
+
10
+ def read_chunk_size
11
+ chunk_info, @body = @body.split("\r\n", 2)
12
+ chunk_info.to_i(16)
13
+ end
14
+
15
+ def read_chunk
16
+ @newbody << @body[0, @chunk_size]
17
+ new_body_len = @body.length - @chunk_size
18
+ @body = @body[@chunk_size+2, new_body_len-2]
19
+ end
20
+
21
+ def parse
22
+ @length = 0
23
+ @chunk_size = read_chunk_size
24
+ while (@chunk_size > 0)
25
+ read_chunk
26
+ @length = @length + @chunk_size
27
+ @chunk_size = read_chunk_size
28
+ end
29
+
30
+ return @header, @newbody
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,4 @@
1
+ module MinHttp
2
+ class PersistentConnectionException < Exception
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module MinHTTP
2
+ class PersistentConnectionException < Exception
3
+ end
4
+ end
@@ -2,6 +2,8 @@ require 'http/parser'
2
2
  require 'eventmachine'
3
3
  require 'logger'
4
4
  require_relative "ssl_validator"
5
+ require_relative "chunk"
6
+ require_relative "exception"
5
7
 
6
8
  #
7
9
  # The minimal HTTP client
@@ -32,6 +34,9 @@ module Http
32
34
 
33
35
  def self.connect(host, data, port=80, ssl=false, &callback)
34
36
  configure unless configured?
37
+ unless (data =~ /\A[^\r\n]+HTTP\/1\.0/ || data =~ /Connection[^\r\n]+close/)
38
+ raise MinHttp::PersistentConnectionException.new("MinHTTP does not support persistent connections, so the request data must indicate HTTP 1.0 or it must include a 'Connection: close' header")
39
+ end
35
40
 
36
41
  EventMachine.connect(host, port, self) do |c|
37
42
  # this code runs after 'post_init', before 'connection_completed'
@@ -81,6 +86,14 @@ module Http
81
86
  def unbind
82
87
  begin
83
88
  @@connections -= 1
89
+
90
+ # combine the chunks of a chunked response
91
+ if @parser.headers["Transfer-Encoding"] == "chunked"
92
+ headers, body = @response_data.split("\r\n\r\n", 2)
93
+ body = MinHttp::Chunk.new(body).parse
94
+ @response_data = "#{headers}\r\n\r\n#{body}"
95
+ end
96
+
84
97
  @callback.call(@response_data, @parser)
85
98
  rescue Exception => e
86
99
  @@logger.error("Error in unbind: #{e}")
@@ -2,6 +2,7 @@ require 'minitest/autorun'
2
2
  require_relative "../lib/minhttp"
3
3
 
4
4
  class SimpleTest < MiniTest::Unit::TestCase
5
+
5
6
  def test_simple_google
6
7
  data = <<-HTTP
7
8
  GET / HTTP/1.0\r
@@ -12,11 +13,68 @@ HTTP
12
13
  EventMachine::run do
13
14
  Http::Min.connect("www.google.com", data) do |raw_response, parsed_response|
14
15
  assert(parsed_response.status_code == 200, "Response from google should be 200 but is #{parsed_response.status_code}")
15
- assert(raw_response.length > 0, "Raw response from google should be have size larger than 0")
16
+ assert(raw_response.length > 0, "Raw response from google should have size larger than 0")
16
17
  EM::stop
17
18
  end
18
19
  end
20
+ end
19
21
 
22
+ def test_chunked
23
+ data = <<-HTTP
24
+ GET /httpgallery/chunked/ HTTP/1.1\r
25
+ Host: www.httpwatch.com\r
26
+ Connection: close
27
+
28
+ HTTP
29
+
30
+ EventMachine::run do
31
+ Http::Min.connect("www.httpwatch.com", data) do |raw_response, parsed_response|
32
+ assert(parsed_response.status_code == 200, "Response from httpwatch should be 200 but is #{parsed_response.status_code}")
33
+ assert(raw_response.length > 0, "Raw response from httpwatch should have size larger than 0")
34
+ EM::stop
35
+ end
36
+ end
20
37
  end
38
+
39
+
40
+ # MinHttp does not support persistent HTTP connections
41
+ def test_http11_with_connection_close
42
+ data = <<-HTTP
43
+ GET / HTTP/1.1\r
44
+ Host: www.google.com\r
45
+ Connection: close
46
+
47
+ HTTP
48
+
49
+ EventMachine::run do
50
+ Http::Min.connect("www.google.com", data) do |raw_response, parsed_response|
51
+ assert(parsed_response.status_code == 200, "Response from google should be 200 but is #{parsed_response.status_code}")
52
+ assert(raw_response.length > 0, "Raw response from google should have size larger than 0")
53
+ EM::stop
54
+ end
55
+ end
56
+ end
57
+
58
+
59
+ # When the 'connection: close' header is not present, the
60
+ # connection is presumed to be persistent. MinHTTP does
61
+ # not support persistent connections so it throws an
62
+ # exception
63
+ def test_http11_without_connection_close
64
+ data = <<-HTTP
65
+ GET / HTTP/1.1\r
66
+ Host: www.google.com\r
67
+
68
+ HTTP
69
+
70
+ assert_raises(MinHttp::PersistentConnectionException) do
71
+ EventMachine::run do
72
+ Http::Min.connect("www.google.com", data) do |raw_response, parsed_response|
73
+ EM::stop
74
+ end
75
+ end
76
+ end
77
+ end
78
+
21
79
  end
22
80
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minhttp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-07-01 00:00:00.000000000Z
12
+ date: 2011-10-21 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: http_parser.rb
16
- requirement: &13044100 !ruby/object:Gem::Requirement
16
+ requirement: &70258984044100 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *13044100
24
+ version_requirements: *70258984044100
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: eventmachine
27
- requirement: &13043560 !ruby/object:Gem::Requirement
27
+ requirement: &70258984043140 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *13043560
35
+ version_requirements: *70258984043140
36
36
  description: MinHTTP allows one to send and receive raw HTTP requests. It's a very
37
37
  thin wrapper around EventMachine's connect method with some SSL validation added.
38
38
  email:
@@ -46,14 +46,14 @@ files:
46
46
  - Gemfile
47
47
  - Rakefile
48
48
  - cacert.pem
49
- - examples/synchronous_example.rb
50
- - examples/synchronous_example.rb~
51
49
  - examples/readme_example.rb
52
- - lib/ssl_validator.rb
53
- - lib/minparser.rb~
50
+ - examples/synchronous_example.rb
51
+ - lib/chunk.rb
52
+ - lib/chunk.rb~
53
+ - lib/exception.rb
54
+ - lib/exception.rb~
54
55
  - lib/minhttp.rb
55
- - lib/rawparser.rb~
56
- - test/simple_test.rb~
56
+ - lib/ssl_validator.rb
57
57
  - test/simple_test.rb
58
58
  homepage: http://github.com/ahfarmer/minhttp
59
59
  licenses: []
@@ -75,10 +75,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
75
  version: '0'
76
76
  requirements: []
77
77
  rubyforge_project: minhttp
78
- rubygems_version: 1.8.5
78
+ rubygems_version: 1.8.11
79
79
  signing_key:
80
80
  specification_version: 3
81
81
  summary: An HTTP library for the minimalist.
82
82
  test_files:
83
- - test/simple_test.rb~
84
83
  - test/simple_test.rb
@@ -1,20 +0,0 @@
1
- require_relative '../lib/minhttp'
2
- require 'em-synchrony'
3
-
4
- data = <<-HTTP
5
- GET / HTTP/1.0\r
6
- Host: www.google.com\r
7
-
8
- HTTP
9
-
10
- EventMachine::run do
11
- Http::Min.connect("www.google.com", data) do |raw_response, parsed_response|
12
- puts "Received #{parsed_response.status_code} status from Google"
13
- puts "First 100 characters of raw HTTP response:"
14
- puts raw_response[0..100]
15
- # EM::stop
16
- Fiber.yield
17
- end
18
- end
19
-
20
- fiber.resume
@@ -1,20 +0,0 @@
1
- require 'http/parser'
2
- require 'eventmachine'
3
- require 'logger'
4
- require_relative "ssl_validator"
5
-
6
- #
7
- # The minimal HTTP client
8
- # Sends a raw http request (bytes)
9
- # Parses the response and provides both the parsed and the raw response
10
- # Supports ssl
11
- #
12
- module Http
13
- class MinParser
14
-
15
-
16
- parser = Http::Parser.new
17
- parser.on_headers_complete = proc{ :stop }
18
-
19
- offset = parser << request_data
20
- body = request_data[offset..-1]
@@ -1,23 +0,0 @@
1
- require 'http/parser'
2
- require 'eventmachine'
3
- require 'logger'
4
- require_relative "ssl_validator"
5
-
6
- #
7
- # The minimal HTTP parser
8
- # Simple wrapper around http_parser.rb that supplies access to the raw
9
- #
10
- module Http
11
- class RawParser
12
- def initialize
13
-
14
- end
15
-
16
- def <<
17
-
18
-
19
- parser = Http::Parser.new
20
- parser.on_headers_complete = proc{ :stop }
21
-
22
- offset = parser << request_data
23
- body = request_data[offset..-1]
@@ -1,10 +0,0 @@
1
- require 'minitest/autorun'
2
-
3
- class SimpleTest < MiniTest::Unit::TestCase
4
- #TEST_DIR = File.dirname(__FILE__)
5
-
6
- def simple_test(test_name)
7
-
8
- end
9
- end
10
-