em-http-request 0.2.10 → 0.2.11

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of em-http-request might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
- # bytesize was introduced in 1.8.7+
2
- if RUBY_VERSION <= "1.8.6"
3
- class String
4
- def bytesize; self.size; end
5
- end
1
+ # bytesize was introduced in 1.8.7+
2
+ if RUBY_VERSION <= "1.8.6"
3
+ class String
4
+ def bytesize; self.size; end
5
+ end
6
6
  end
@@ -1,53 +1,53 @@
1
- class Hash
2
- # Stolen partially from Merb : http://noobkit.com/show/ruby/gems/development/merb/hash/to_params.html
3
- # Convert this hash to a query string:
4
- #
5
- # { :name => "Bob",
6
- # :address => {
7
- # :street => '111 Ruby Ave.',
8
- # :city => 'Ruby Central',
9
- # :phones => ['111-111-1111', '222-222-2222']
10
- # }
11
- # }.to_params
12
- # #=> "name=Bob&address[city]=Ruby Central&address[phones]=111-111-1111222-222-2222&address[street]=111 Ruby Ave."
13
- #
14
- def to_params
15
- params = ''
16
- stack = []
17
-
18
- each do |k, v|
19
- if v.is_a?(Hash)
20
- stack << [k,v]
21
- elsif v.is_a?(Array)
22
- stack << [k,Hash.from_array(v)]
23
- else
24
- params << "#{k}=#{v}&"
25
- end
26
- end
27
-
28
- stack.each do |parent, hash|
29
- hash.each do |k, v|
30
- if v.is_a?(Hash)
31
- stack << ["#{parent}[#{k}]", v]
32
- else
33
- params << "#{parent}[#{k}]=#{v}&"
34
- end
35
- end
36
- end
37
-
38
- params.chop! # trailing &
39
- params
40
- end
41
-
42
- ##
43
- # Builds a hash from an array with keys as array indices.
44
- def self.from_array(array = [])
45
- h = Hash.new
46
- array.size.times do |t|
47
- h[t] = array[t]
48
- end
49
- h
50
- end
51
-
52
- end
53
-
1
+ class Hash
2
+ # Stolen partially from Merb : http://noobkit.com/show/ruby/gems/development/merb/hash/to_params.html
3
+ # Convert this hash to a query string:
4
+ #
5
+ # { :name => "Bob",
6
+ # :address => {
7
+ # :street => '111 Ruby Ave.',
8
+ # :city => 'Ruby Central',
9
+ # :phones => ['111-111-1111', '222-222-2222']
10
+ # }
11
+ # }.to_params
12
+ # #=> "name=Bob&address[city]=Ruby Central&address[phones]=111-111-1111222-222-2222&address[street]=111 Ruby Ave."
13
+ #
14
+ def to_params
15
+ params = ''
16
+ stack = []
17
+
18
+ each do |k, v|
19
+ if v.is_a?(Hash)
20
+ stack << [k,v]
21
+ elsif v.is_a?(Array)
22
+ stack << [k,Hash.from_array(v)]
23
+ else
24
+ params << "#{k}=#{v}&"
25
+ end
26
+ end
27
+
28
+ stack.each do |parent, hash|
29
+ hash.each do |k, v|
30
+ if v.is_a?(Hash)
31
+ stack << ["#{parent}[#{k}]", v]
32
+ else
33
+ params << "#{parent}[#{k}]=#{v}&"
34
+ end
35
+ end
36
+ end
37
+
38
+ params.chop! # trailing &
39
+ params
40
+ end
41
+
42
+ ##
43
+ # Builds a hash from an array with keys as array indices.
44
+ def self.from_array(array = [])
45
+ h = Hash.new
46
+ array.size.times do |t|
47
+ h[t] = array[t]
48
+ end
49
+ h
50
+ end
51
+
52
+ end
53
+
@@ -1,122 +1,122 @@
1
- require 'zlib'
2
- require 'stringio'
3
-
4
- ##
5
- # Provides a unified callback interface to decompression libraries.
6
- module EventMachine::HttpDecoders
7
-
8
- class DecoderError < StandardError
9
- end
10
-
11
- class << self
12
- def accepted_encodings
13
- DECODERS.inject([]) { |r,d| r + d.encoding_names }
14
- end
15
-
16
- def decoder_for_encoding(encoding)
17
- DECODERS.each { |d|
18
- return d if d.encoding_names.include? encoding
19
- }
20
- nil
21
- end
22
- end
23
-
24
- class Base
25
- def self.encoding_names
26
- name = to_s.split('::').last.downcase
27
- [name]
28
- end
29
-
30
- ##
31
- # chunk_callback:: [Block] To handle a decompressed chunk
32
- def initialize(&chunk_callback)
33
- @chunk_callback = chunk_callback
34
- end
35
-
36
- def <<(compressed)
37
- return unless compressed && compressed.size > 0
38
-
39
- decompressed = decompress(compressed)
40
- receive_decompressed decompressed
41
- end
42
-
43
- def finalize!
44
- decompressed = finalize
45
- receive_decompressed decompressed
46
- end
47
-
48
- private
49
-
50
- def receive_decompressed(decompressed)
51
- if decompressed && decompressed.size > 0
52
- @chunk_callback.call(decompressed)
53
- end
54
- end
55
-
56
- protected
57
-
58
- ##
59
- # Must return a part of decompressed
60
- def decompress(compressed)
61
- nil
62
- end
63
-
64
- ##
65
- # May return last part
66
- def finalize
67
- nil
68
- end
69
- end
70
-
71
- class Deflate < Base
72
- def decompress(compressed)
73
- begin
74
- @zstream ||= Zlib::Inflate.new(nil)
75
- @zstream.inflate(compressed)
76
- rescue Zlib::Error
77
- raise DecoderError
78
- end
79
- end
80
-
81
- def finalize
82
- return nil unless @zstream
83
-
84
- begin
85
- r = @zstream.inflate(nil)
86
- @zstream.close
87
- r
88
- rescue Zlib::Error
89
- raise DecoderError
90
- end
91
- end
92
- end
93
-
94
- ##
95
- # Oneshot decompressor, due to lack of a streaming Gzip reader
96
- # implementation. We may steal code from Zliby to improve this.
97
- #
98
- # For now, do not put `gzip' or `compressed' in your accept-encoding
99
- # header if you expect much data through the :on_response interface.
100
- class GZip < Base
101
- def self.encoding_names
102
- %w(gzip compressed)
103
- end
104
-
105
- def decompress(compressed)
106
- @buf ||= ''
107
- @buf += compressed
108
- nil
109
- end
110
-
111
- def finalize
112
- begin
113
- Zlib::GzipReader.new(StringIO.new(@buf.to_s)).read
114
- rescue Zlib::Error
115
- raise DecoderError
116
- end
117
- end
118
- end
119
-
120
- DECODERS = [Deflate, GZip]
121
-
122
- end
1
+ require 'zlib'
2
+ require 'stringio'
3
+
4
+ ##
5
+ # Provides a unified callback interface to decompression libraries.
6
+ module EventMachine::HttpDecoders
7
+
8
+ class DecoderError < StandardError
9
+ end
10
+
11
+ class << self
12
+ def accepted_encodings
13
+ DECODERS.inject([]) { |r,d| r + d.encoding_names }
14
+ end
15
+
16
+ def decoder_for_encoding(encoding)
17
+ DECODERS.each { |d|
18
+ return d if d.encoding_names.include? encoding
19
+ }
20
+ nil
21
+ end
22
+ end
23
+
24
+ class Base
25
+ def self.encoding_names
26
+ name = to_s.split('::').last.downcase
27
+ [name]
28
+ end
29
+
30
+ ##
31
+ # chunk_callback:: [Block] To handle a decompressed chunk
32
+ def initialize(&chunk_callback)
33
+ @chunk_callback = chunk_callback
34
+ end
35
+
36
+ def <<(compressed)
37
+ return unless compressed && compressed.size > 0
38
+
39
+ decompressed = decompress(compressed)
40
+ receive_decompressed decompressed
41
+ end
42
+
43
+ def finalize!
44
+ decompressed = finalize
45
+ receive_decompressed decompressed
46
+ end
47
+
48
+ private
49
+
50
+ def receive_decompressed(decompressed)
51
+ if decompressed && decompressed.size > 0
52
+ @chunk_callback.call(decompressed)
53
+ end
54
+ end
55
+
56
+ protected
57
+
58
+ ##
59
+ # Must return a part of decompressed
60
+ def decompress(compressed)
61
+ nil
62
+ end
63
+
64
+ ##
65
+ # May return last part
66
+ def finalize
67
+ nil
68
+ end
69
+ end
70
+
71
+ class Deflate < Base
72
+ def decompress(compressed)
73
+ begin
74
+ @zstream ||= Zlib::Inflate.new(nil)
75
+ @zstream.inflate(compressed)
76
+ rescue Zlib::Error
77
+ raise DecoderError
78
+ end
79
+ end
80
+
81
+ def finalize
82
+ return nil unless @zstream
83
+
84
+ begin
85
+ r = @zstream.inflate(nil)
86
+ @zstream.close
87
+ r
88
+ rescue Zlib::Error
89
+ raise DecoderError
90
+ end
91
+ end
92
+ end
93
+
94
+ ##
95
+ # Oneshot decompressor, due to lack of a streaming Gzip reader
96
+ # implementation. We may steal code from Zliby to improve this.
97
+ #
98
+ # For now, do not put `gzip' or `compressed' in your accept-encoding
99
+ # header if you expect much data through the :on_response interface.
100
+ class GZip < Base
101
+ def self.encoding_names
102
+ %w(gzip compressed)
103
+ end
104
+
105
+ def decompress(compressed)
106
+ @buf ||= ''
107
+ @buf += compressed
108
+ nil
109
+ end
110
+
111
+ def finalize
112
+ begin
113
+ Zlib::GzipReader.new(StringIO.new(@buf.to_s)).read
114
+ rescue Zlib::Error
115
+ raise DecoderError
116
+ end
117
+ end
118
+ end
119
+
120
+ DECODERS = [Deflate, GZip]
121
+
122
+ end
@@ -1,32 +1,34 @@
1
- class HttpOptions
2
- attr_reader :uri, :method, :host, :port, :options
3
-
4
- def initialize(method, uri, options)
5
- raise ArgumentError, "invalid request path" unless /^\// === uri.path
6
-
7
- @options = options
8
- @method = method.to_s.upcase
9
- @uri = uri
10
-
11
- if proxy = options[:proxy]
12
- @host = proxy[:host]
13
- @port = proxy[:port]
14
- else
15
- @host = uri.host
16
- @port = uri.port
17
- end
18
-
19
- @options[:timeout] ||= 10 # default connect & inactivity timeouts
20
- @options[:redirects] ||= 0 # default number of redirects to follow
21
-
22
- # Make sure the ports are set as Addressable::URI doesn't
23
- # set the port if it isn't there
24
- if uri.scheme == "https"
25
- @uri.port ||= 443
26
- @port ||= 443
27
- else
28
- @uri.port ||= 80
29
- @port ||= 80
30
- end
31
- end
1
+ class HttpOptions
2
+ attr_reader :uri, :method, :host, :port, :options
3
+
4
+ def initialize(method, uri, options)
5
+ uri.normalize!
6
+
7
+ @options = options
8
+ @method = method.to_s.upcase
9
+ @uri = uri
10
+
11
+ if proxy = options[:proxy]
12
+ @host = proxy[:host]
13
+ @port = proxy[:port]
14
+ else
15
+ # optional host for cases where you may have
16
+ # pre-resolved the host, or you need an override
17
+ @host = options[:host] || uri.host
18
+ @port = uri.port
19
+ end
20
+
21
+ @options[:timeout] ||= 10 # default connect & inactivity timeouts
22
+ @options[:redirects] ||= 0 # default number of redirects to follow
23
+
24
+ # Make sure the ports are set as Addressable::URI doesn't
25
+ # set the port if it isn't there
26
+ if uri.scheme == "https"
27
+ @uri.port ||= 443
28
+ @port ||= 443
29
+ else
30
+ @uri.port ||= 80
31
+ @port ||= 80
32
+ end
33
+ end
32
34
  end
@@ -1,91 +1,131 @@
1
1
  module EventMachine
2
+ OriginalHttpRequest = HttpRequest unless const_defined?(:OriginalHttpRequest)
3
+
2
4
  class MockHttpRequest < EventMachine::HttpRequest
3
-
5
+
4
6
  include HttpEncoding
5
-
6
- class FakeHttpClient < EventMachine::HttpClient
7
7
 
8
+ class RegisteredRequest < Struct.new(:uri, :method, :headers)
9
+ def self.build(uri, method, headers)
10
+ new(uri, method.to_s.upcase, headers || {})
11
+ end
12
+ end
13
+
14
+ class FakeHttpClient < EventMachine::HttpClient
15
+ attr_writer :response
16
+ attr_reader :data
8
17
  def setup(response, uri)
9
18
  @uri = uri
10
19
  if response == :fail
11
20
  fail(self)
12
21
  else
13
- receive_data(response)
14
- succeed(self)
22
+ if response.respond_to?(:call)
23
+ response.call(self)
24
+ @state = :body
25
+ else
26
+ receive_data(response)
27
+ end
28
+ @state == :body ? succeed(self) : fail(self)
15
29
  end
16
30
  end
17
-
31
+
18
32
  def unbind
19
33
  end
20
-
21
34
  end
22
-
23
- @@registry = nil
24
- @@registry_count = nil
25
-
35
+
36
+ @@registry = Hash.new
37
+ @@registry_count = Hash.new{|h,k| h[k] = 0}
38
+
39
+ def self.use
40
+ activate!
41
+ yield
42
+ ensure
43
+ deactivate!
44
+ end
45
+
46
+ def self.activate!
47
+ EventMachine.send(:remove_const, :HttpRequest)
48
+ EventMachine.send(:const_set, :HttpRequest, MockHttpRequest)
49
+ end
50
+
51
+ def self.deactivate!
52
+ EventMachine.send(:remove_const, :HttpRequest)
53
+ EventMachine.send(:const_set, :HttpRequest, OriginalHttpRequest)
54
+ end
55
+
26
56
  def self.reset_counts!
27
- @@registry_count = Hash.new do |registry,query|
28
- registry[query] = Hash.new{|h,k| h[k] = Hash.new(0)}
29
- end
57
+ @@registry_count.clear
30
58
  end
31
-
59
+
32
60
  def self.reset_registry!
33
- @@registry = Hash.new do |registry,query|
34
- registry[query] = Hash.new{|h,k| h[k] = {}}
35
- end
61
+ @@registry.clear
36
62
  end
37
-
38
- reset_counts!
39
- reset_registry!
40
-
63
+
41
64
  @@pass_through_requests = true
42
65
 
43
66
  def self.pass_through_requests=(pass_through_requests)
44
67
  @@pass_through_requests = pass_through_requests
45
68
  end
46
-
69
+
47
70
  def self.pass_through_requests
48
71
  @@pass_through_requests
49
72
  end
50
-
51
- def self.register(uri, method, headers, data)
52
- method = method.to_s.upcase
53
- headers = headers.to_s
54
- @@registry[uri][method][headers] = data
73
+
74
+ def self.parse_register_args(args, &proc)
75
+ args << proc{|client| proc.call(client); ''} if proc
76
+ headers, data = case args.size
77
+ when 3
78
+ args[2].is_a?(Hash) ?
79
+ [args[2][:headers], args[2][:data]] :
80
+ [{}, args[2]]
81
+ when 4
82
+ [args[2], args[3]]
83
+ else
84
+ raise
85
+ end
86
+
87
+ url = args[0]
88
+ method = args[1]
89
+ [headers, url, method, data]
55
90
  end
56
-
57
- def self.register_file(uri, method, headers, file)
58
- register(uri, method, headers, File.read(file))
91
+
92
+ def self.register(*args, &proc)
93
+ headers, url, method, data = parse_register_args(args, &proc)
94
+ @@registry[RegisteredRequest.build(url, method, headers)] = data
59
95
  end
60
-
61
- def self.count(uri, method, headers)
62
- method = method.to_s.upcase
63
- headers = headers.to_s
64
- @@registry_count[uri][method][headers] rescue 0
96
+
97
+ def self.register_file(*args)
98
+ headers, url, method, data = parse_register_args(args)
99
+ @@registry[RegisteredRequest.build(url, method, headers)] = File.read(data)
100
+ end
101
+
102
+ def self.count(url, method, headers = {})
103
+ @@registry_count[RegisteredRequest.build(url, method, headers)]
65
104
  end
66
-
67
- def self.registered?(query, method, headers)
68
- @@registry[query] and @@registry[query][method] and @@registry[query][method][headers]
105
+
106
+ def self.registered?(url, method, headers = {})
107
+ @@registry.key?(RegisteredRequest.build(url, method, headers))
69
108
  end
70
-
71
- def self.registered_content(query, method, headers)
72
- @@registry[query][method][headers]
109
+
110
+ def self.registered_content(url, method, headers = {})
111
+ @@registry[RegisteredRequest.build(url, method, headers)]
73
112
  end
74
-
75
- def self.increment_access(query, method, headers)
76
- @@registry_count[query][method][headers] += 1
113
+
114
+ def self.increment_access(url, method, headers = {})
115
+ @@registry_count[RegisteredRequest.build(url, method, headers)] += 1
77
116
  end
78
-
117
+
79
118
  alias_method :real_send_request, :send_request
80
-
119
+
81
120
  protected
82
121
  def send_request(&blk)
83
- query = "#{@req.uri.scheme}://#{@req.uri.host}:#{@req.uri.port}#{encode_query(@req.uri.path, @req.options[:query], @req.uri.query)}"
84
- headers = @req.options[:head].to_s
122
+ query = "#{@req.uri.scheme}://#{@req.uri.host}:#{@req.uri.port}#{encode_query(@req.uri, @req.options[:query])}"
123
+ headers = @req.options[:head]
85
124
  if self.class.registered?(query, @req.method, headers)
86
125
  self.class.increment_access(query, @req.method, headers)
87
126
  client = FakeHttpClient.new(nil)
88
- client.setup(self.class.registered_content(query, @req.method, headers), @req.uri)
127
+ content = self.class.registered_content(query, @req.method, headers)
128
+ client.setup(content, @req.uri)
89
129
  client
90
130
  elsif @@pass_through_requests
91
131
  real_send_request