minhttp 0.0.8 → 0.0.9

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