kronk 1.6.2 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/History.rdoc +29 -1
  2. data/Manifest.txt +6 -1
  3. data/README.rdoc +74 -28
  4. data/Rakefile +4 -3
  5. data/TODO.rdoc +7 -5
  6. data/bin/kronk +2 -11
  7. data/lib/kronk/async/em_ext.rb +34 -0
  8. data/lib/kronk/async/request.rb +73 -0
  9. data/lib/kronk/async/response.rb +70 -0
  10. data/lib/kronk/async.rb +118 -0
  11. data/lib/kronk/cmd.rb +111 -43
  12. data/lib/kronk/constants.rb +1 -0
  13. data/lib/kronk/core_ext.rb +1 -1
  14. data/lib/kronk/data_string.rb +251 -0
  15. data/lib/kronk/diff/output.rb +132 -100
  16. data/lib/kronk/diff.rb +20 -24
  17. data/lib/kronk/path/matcher.rb +8 -4
  18. data/lib/kronk/path/path_match.rb +48 -4
  19. data/lib/kronk/path/transaction.rb +74 -53
  20. data/lib/kronk/path.rb +11 -6
  21. data/lib/kronk/player/benchmark.rb +11 -12
  22. data/lib/kronk/player/input_reader.rb +40 -3
  23. data/lib/kronk/player/request_parser.rb +4 -1
  24. data/lib/kronk/player/stream.rb +2 -2
  25. data/lib/kronk/player/suite.rb +16 -9
  26. data/lib/kronk/player.rb +93 -143
  27. data/lib/kronk/queue_runner.rb +238 -0
  28. data/lib/kronk/request.rb +25 -20
  29. data/lib/kronk/response.rb +39 -10
  30. data/lib/kronk/test/assertions.rb +2 -2
  31. data/lib/kronk/test/helper_methods.rb +1 -1
  32. data/lib/kronk.rb +56 -24
  33. data/test/test_assertions.rb +4 -4
  34. data/test/test_cmd.rb +38 -10
  35. data/test/test_data_string.rb +242 -1
  36. data/test/test_diff.rb +8 -303
  37. data/test/test_helper.rb +1 -1
  38. data/test/test_kronk.rb +21 -28
  39. data/test/test_path.rb +29 -0
  40. data/test/test_path_match.rb +47 -2
  41. data/test/test_path_matcher.rb +42 -1
  42. data/test/test_player.rb +71 -72
  43. data/test/test_request.rb +31 -6
  44. data/test/test_request_parser.rb +7 -1
  45. data/test/test_response.rb +1 -1
  46. data/test/test_transaction.rb +78 -30
  47. metadata +64 -8
  48. data/lib/kronk/data_renderer.rb +0 -219
data/lib/kronk/player.rb CHANGED
@@ -6,33 +6,57 @@ class Kronk
6
6
  # Kronk includes a Suite (test-like) output, a Stream (chunked) output,
7
7
  # and a Benchmark output.
8
8
 
9
- class Player
9
+ class Player < QueueRunner
10
10
 
11
- attr_accessor :number, :concurrency, :queue, :count, :input,
12
- :output, :mutex, :threads, :reader_thread
11
+ RESCUABLE = [Kronk::Exception, Errno::ECONNRESET, URI::InvalidURIError]
12
+
13
+ attr_accessor :input, :output
13
14
 
14
15
  ##
15
16
  # Create a new Player for batch diff or response validation.
16
17
  # Supported options are:
17
- # :concurrency:: Fixnum - The maximum number of concurrent requests to make
18
- # :number:: Fixnum - The number of requests to make
19
18
  # :io:: IO - The IO instance to read from
20
19
  # :output:: Class - The output class to use (see Player::Output)
21
20
  # :parser:: Class - The IO parser to use.
22
21
 
23
22
  def initialize opts={}
24
- @number = opts[:number]
25
- @concurrency = opts[:concurrency]
26
- @concurrency = 1 if !@concurrency || @concurrency <= 0
23
+ super
27
24
  self.output_from opts[:output] || Suite
28
25
 
29
- @count = 0
30
- @queue = []
31
- @threads = []
32
- @input = InputReader.new opts[:io], opts[:parser]
33
- @last_req = nil
26
+ @input = InputReader.new opts[:io], opts[:parser]
27
+ @use_output = true
28
+ @last_req = nil
29
+
30
+ @on_input = Proc.new do
31
+ stop_input! if !@number && @input.eof?
32
+ @last_req = @input.get_next || @queue.last || @last_req || {}
33
+ end
34
+
35
+ @on_result = Proc.new do |kronk, err, mutex|
36
+ err ? @output.error(err, kronk, mutex) :
37
+ @output.result(kronk, mutex)
38
+ end
34
39
 
35
- @mutex = Mutex.new
40
+ on(:input, &@on_input)
41
+ on(:interrupt){
42
+ @output.completed if @use_output
43
+ exit 2
44
+ }
45
+ on(:start){ @output.start if @use_output }
46
+ on(:complete){ @output.completed if @use_output }
47
+ end
48
+
49
+
50
+ ##
51
+ # Populate the queue by reading from the given IO instance and
52
+ # parsing it into kronk options.
53
+ #
54
+ # Default parser is RequestParser. See InputReader for parser requirements.
55
+
56
+ def from_io io, parser=nil
57
+ @input.io = io
58
+ @input.parser = parser if parser
59
+ @input
36
60
  end
37
61
 
38
62
 
@@ -56,37 +80,17 @@ class Kronk
56
80
  end
57
81
 
58
82
 
59
- ##
60
- # Adds kronk request hash options to queue.
61
- # See Kronk#compare for supported options.
62
-
63
- def queue_req kronk_opts
64
- @queue << kronk_opts
65
- end
66
-
67
-
68
- ##
69
- # Populate the queue by reading from the given IO instance and
70
- # parsing it into kronk options.
71
- #
72
- # Default parser is RequestParser. See InputReader for parser requirements.
73
-
74
- def from_io io, parser=nil
75
- @input.io = io
76
- @input.parser = parser if parser
77
- @input
78
- end
79
-
80
-
81
83
  ##
82
84
  # Process the queue to compare two uris.
83
85
  # If options are given, they are merged into every request.
84
86
 
85
- def compare uri1, uri2, opts={}
87
+ def compare uri1, uri2, opts={}, &block
86
88
  return Cmd.compare uri1, uri2, @queue.shift.merge(opts) if single_request?
87
89
 
88
- process_queue do |kronk_opts|
89
- process_compare uri1, uri2, kronk_opts.merge(opts)
90
+ method = self.class.async ? :process_one_async : :process_one
91
+
92
+ run do |kronk_opts, mutex|
93
+ send method, kronk_opts.merge(opts), 'compare', uri1, uri2, &block
90
94
  end
91
95
  end
92
96
 
@@ -95,139 +99,85 @@ class Kronk
95
99
  # Process the queue to request uris.
96
100
  # If options are given, they are merged into every request.
97
101
 
98
- def request uri, opts={}
99
- return Cmd.request(uri, @queue.shift.merge(opts)) if single_request?
102
+ def request uri, opts={}, &block
103
+ return Cmd.request uri, @queue.shift.merge(opts) if single_request?
100
104
 
101
- process_queue do |kronk_opts|
102
- process_request uri, kronk_opts.merge(opts)
103
- end
104
- end
105
+ method = self.class.async ? :process_one_async : :process_one
105
106
 
106
-
107
- ##
108
- # Check if we're only processing a single case.
109
- # If so, yield a single item and return immediately.
110
-
111
- def single_request?
112
- @queue << next_request if @queue.empty? && (!@number || @number <= 1)
113
- @queue.length == 1 && @input.eof?
107
+ run do |kronk_opts, mutex|
108
+ send method, kronk_opts.merge(opts), 'request', uri, &block
109
+ end
114
110
  end
115
111
 
116
112
 
117
113
  ##
118
- # Start processing the queue and reading from IO if available.
119
- # Calls Output#start method and returns the value of Output#completed
120
- # once processing is finished.
114
+ # Run a single compare or request and call the Output#result or
115
+ # Output#error method.
121
116
  #
122
- # Yields queue item until queue and io (if available) are empty and the
123
- # totaly number of requests to run is met (if number is set).
124
-
125
- def process_queue
126
- @reader_thread = try_fill_queue
127
-
128
- trap 'INT' do
129
- @threads.each{|t| t.kill}
130
- @threads.clear
131
- @reader_thread.kill
132
- output_results
133
- exit 2
134
- end
135
-
136
- @output.start
137
- @count = 0
138
-
139
- until finished?
140
- @threads.delete_if{|t| !t.alive? }
141
- next if @threads.length >= @concurrency || @queue.empty?
117
+ # If given a block, will yield the Kronk instance and error. If
118
+ # a third argument is given, mutex will also be passed and the
119
+ # block won't be called from a mutex lock.
120
+ #
121
+ # Returns the result of the block or of the called Output method.
142
122
 
143
- @threads << Thread.new(@queue.shift) do |kronk_opts|
144
- yield kronk_opts if block_given?
145
- end
123
+ def process_one opts={}, *args, &block
124
+ err = nil
125
+ kronk = Kronk.new opts
146
126
 
147
- @count += 1
127
+ begin
128
+ kronk.send(*args)
129
+ rescue *RESCUABLE => e
130
+ err = e
148
131
  end
149
132
 
150
- @threads.each{|t| t.join}
151
- @threads.clear
152
-
153
- @reader_thread.kill
154
-
155
- output_results
133
+ trigger_result kronk, err, &block
156
134
  end
157
135
 
158
136
 
159
137
  ##
160
- # Attempt to fill the queue by reading from the IO instance.
161
- # Starts a new thread and returns the thread instance.
162
-
163
- def try_fill_queue
164
- Thread.new do
165
- loop do
166
- break if !@number && @input.eof?
167
- next if @queue.length >= @concurrency * 2
138
+ # Run a single compare or request and call the Output#result or
139
+ # Output#error method using EventMachine.
140
+ #
141
+ # If given a block, will yield the Kronk instance and error. If
142
+ # a third argument is given, mutex will also be passed and the
143
+ # block won't be called from a mutex lock.
144
+ #
145
+ # Returns either a EM::MultiRequest or an EM::Connection handler.
168
146
 
169
- max_new = @concurrency * 2 - @queue.length
147
+ def process_one_async opts={}, *args, &block
148
+ kronk = Kronk.new opts
149
+ method = args.shift.to_s + '_async'
170
150
 
171
- max_new.times do
172
- @queue << next_request
173
- break if !@number && @input.eof?
174
- end
175
- end
151
+ kronk.send(method, *args) do |obj, err|
152
+ raise err if err && !RESCUABLE.find{|eclass| eclass === err}
153
+ trigger_result kronk, err, &block
176
154
  end
177
155
  end
178
156
 
179
157
 
180
158
  ##
181
- # Gets the next request to perform and always returns a Hash.
182
- # Tries from input first, then from the last item in the queue.
183
- # If both fail, returns an empty Hash.
184
-
185
- def next_request
186
- @last_req = @input.get_next || @queue.last || @last_req || Hash.new
187
- end
159
+ # Trigger a single kronk result callback.
188
160
 
161
+ def trigger_result kronk, err, &block
162
+ block ||= @on_result
189
163
 
190
- ##
191
- # Returns true if processing queue should be stopped, otherwise false.
192
-
193
- def finished?
194
- (@number && @count >= @number) || @queue.empty? &&
195
- @input.eof? && @count > 0 && !@reader_thread.alive?
196
- end
197
-
198
-
199
- ##
200
- # Process and output the results.
201
- # Calls Output#completed method.
202
-
203
- def output_results
204
- @output.completed
205
- end
206
-
207
-
208
- ##
209
- # Run a single compare and call the Output#result or Output#error method.
210
-
211
- def process_compare uri1, uri2, opts={}
212
- kronk = Kronk.new opts
213
- kronk.compare uri1, uri2
214
- @output.result kronk, @mutex
215
-
216
- rescue Kronk::Exception, Response::MissingParser, Errno::ECONNRESET => e
217
- @output.error e, kronk, @mutex
164
+ if block.arity > 2 || block.arity < 0
165
+ block.call kronk, err, @mutex
166
+ else
167
+ @mutex.synchronize do
168
+ block.call kronk, err
169
+ end
170
+ end
218
171
  end
219
172
 
220
173
 
221
174
  ##
222
- # Run a single request and call the Output#result or Output#error method.
223
-
224
- def process_request uri, opts={}
225
- kronk = Kronk.new opts
226
- kronk.retrieve uri
227
- @output.result kronk, @mutex
175
+ # Check if w6ce5e2ce're only processing a single case.
176
+ # If so, yield a single item and return immediately.
228
177
 
229
- rescue Kronk::Exception, Response::MissingParser, Errno::ECONNRESET => e
230
- @output.error e, kronk, @mutex
178
+ def single_request?
179
+ @queue << trigger(:input) if @queue.empty? && (!@number || @number <= 1)
180
+ @queue.length == 1 && @triggers[:input] == @on_input && @input.eof?
231
181
  end
232
182
  end
233
183
  end
@@ -0,0 +1,238 @@
1
+ class Kronk
2
+
3
+ class QueueRunner
4
+
5
+ ##
6
+ # Define whether to use the EventMachine or the threaded behavior.
7
+
8
+ def self.async= value
9
+ @async = !!value
10
+ end
11
+
12
+
13
+ ##
14
+ # Returns true if EventMachine is enabled
15
+
16
+ def self.async
17
+ @async
18
+ end
19
+
20
+ self.async = false
21
+
22
+
23
+ attr_accessor :number, :concurrency, :queue, :count,
24
+ :mutex, :threads, :reader_thread
25
+
26
+ ##
27
+ # Create a new QueueRunner for batch multi-threaded processing.
28
+ # Supported options are:
29
+ # :concurrency:: Fixnum - Maximum number of concurrent items to process
30
+ # :number:: Fixnum - Total number of items to process
31
+
32
+ def initialize opts={}
33
+ @number = opts[:number]
34
+ @concurrency = opts[:concurrency]
35
+ @concurrency = 1 if !@concurrency || @concurrency <= 0
36
+
37
+ @count = 0
38
+ @queue = []
39
+ @threads = []
40
+
41
+ @reader_thread = nil
42
+
43
+ @triggers = {}
44
+
45
+ @mutex = Mutex.new
46
+ end
47
+
48
+
49
+ ##
50
+ # Returns true if processing queue should be stopped, otherwise false.
51
+
52
+ def finished?
53
+ return true if @number && @count >= @number
54
+
55
+ @queue.empty? && @count > 0 &&
56
+ (!@reader_thread || !@reader_thread.alive?)
57
+ end
58
+
59
+
60
+ ##
61
+ # Immediately end all runner processing and threads.
62
+
63
+ def kill
64
+ stop_input!
65
+ EM.stop if defined?(EM) && EM.reactor_running?
66
+ @threads.each{|t| t.kill}
67
+ @threads.clear
68
+ end
69
+
70
+
71
+ ##
72
+ # Specify a block to run for a given trigger name.
73
+ # Supported triggers are:
74
+ # :complete:: Called after queue and input have been fully processed.
75
+ # :input:: Called every time the queue needs populating.
76
+ # :interrupt:: Called when SIGINT is captured.
77
+ # :start:: Called before queue starts being processed.
78
+
79
+ def on trigger_name, &block
80
+ @triggers[trigger_name] = block
81
+ end
82
+
83
+
84
+ ##
85
+ # Start processing the queue and reading from IO if available.
86
+ #
87
+ # Yields queue item until queue and io (if available) are empty and the
88
+ # totaly number of requests to run is met (if number is set).
89
+
90
+ def process_queue
91
+ start_input!
92
+ @count = 0
93
+
94
+ until finished?
95
+ @threads.delete_if{|t| !t.alive? }
96
+
97
+ if @threads.length >= @concurrency || @queue.empty?
98
+ Thread.pass
99
+ next
100
+ end
101
+
102
+ @threads << Thread.new(@queue.shift) do |q_item|
103
+ yield q_item if block_given?
104
+ end
105
+
106
+ @count += 1
107
+ end
108
+
109
+ @threads.each{|t| t.join}
110
+ @threads.clear
111
+
112
+ stop_input!
113
+ end
114
+
115
+
116
+ ##
117
+ # Start processing the queue and reading from IO if available.
118
+ #
119
+ # Yields queue item until queue and io (if available) are empty and the
120
+ # totaly number of requests to run is met (if number is set).
121
+ #
122
+ # Uses EventMachine to run asynchronously.
123
+ #
124
+ # Note: If the block given doesn't use EM, it will be blocking.
125
+
126
+ def process_queue_async &block
127
+ # TODO: Make input use EM from QueueRunner and Player IO.
128
+ require 'kronk/async' unless defined?(EM::HttpRequest)
129
+ Cmd.verbose "Running async"
130
+
131
+ start_input!
132
+
133
+ @count = 0
134
+
135
+ EM.run do
136
+ EM.add_periodic_timer do
137
+ if finished?
138
+ next if EM.connection_count > 0
139
+ kill
140
+ next
141
+ end
142
+
143
+ if @queue.empty? || EM.connection_count >= @concurrency
144
+ Thread.pass
145
+ next
146
+ end
147
+
148
+ yield @queue.shift
149
+ @count += 1
150
+ end
151
+ end
152
+ end
153
+
154
+
155
+ ##
156
+ # Runs the queue and reads from input until it's exhausted or
157
+ # @number is reached. Yields a queue item and a mutex when to passed
158
+ # block:
159
+ #
160
+ # runner = QueueRunner.new :concurrency => 10
161
+ # runner.queue.concat %w{item1 item2 item3}
162
+ #
163
+ # runner.run do |q_item, mutex|
164
+ # # This block is run in its own thread.
165
+ # mutex.synchronize{ do_something_with q_item }
166
+ # end
167
+ #
168
+ # Calls the :start trigger before execution begins, calls :complete
169
+ # when the execution has ended or is interrupted, also calls :interrupt
170
+ # when execution is interrupted.
171
+
172
+ def run
173
+ trap 'INT' do
174
+ kill
175
+ (trigger(:interrupt) || exit(1))
176
+ end
177
+
178
+ trigger :start
179
+
180
+ method = self.class.async ? :process_queue_async : :process_queue
181
+
182
+ send method do |q_item|
183
+ yield q_item, @mutex if block_given?
184
+ end
185
+
186
+ trigger :complete
187
+ end
188
+
189
+
190
+ ##
191
+ # Attempt to fill the queue by reading from the IO instance.
192
+ # Starts a new thread and returns the thread instance.
193
+
194
+ def start_input!
195
+ return unless @triggers[:input]
196
+
197
+ max_queue_size = @concurrency * 2
198
+
199
+ @reader_thread = Thread.new do
200
+ begin
201
+ loop do
202
+ if @queue.length >= max_queue_size
203
+ Thread.pass
204
+ next
205
+ end
206
+
207
+ while @queue.length < max_queue_size
208
+ @queue << trigger(:input)
209
+ end
210
+ Thread.pass
211
+ end
212
+
213
+ rescue => e
214
+ Thread.main.raise e
215
+ end
216
+ end
217
+ end
218
+
219
+
220
+ ##
221
+ # Permanently stop input reading by killing the reader thread for a given
222
+ # QueueRunner#run or QueueRunner#process_queue session.
223
+
224
+ def stop_input!
225
+ Thread.pass
226
+ @reader_thread && @reader_thread.kill
227
+ end
228
+
229
+
230
+ ##
231
+ # Run a previously defined callback. See QueueRunner#on.
232
+
233
+ def trigger name
234
+ t = @triggers[name]
235
+ t && t.call
236
+ end
237
+ end
238
+ end
data/lib/kronk/request.rb CHANGED
@@ -1,15 +1,17 @@
1
1
  class Kronk
2
2
 
3
3
  ##
4
- # Performs HTTP requests or retrieves HTTP responses.
4
+ # Performs HTTP requests and returns a Kronk::Response instance.
5
5
 
6
6
  class Request
7
7
 
8
8
  # Raised by Request.parse when parsing invalid http request string.
9
9
  class ParseError < Kronk::Exception; end
10
10
 
11
- # Matches the first line of an http request string.
12
- REQUEST_LINE_MATCHER = %r{([A-Za-z]+)?(^|[\s'"])(/[^\s'";]+)[\s"']*}
11
+ # Matches the first line of an http request string or a fully
12
+ # qualified URL.
13
+ REQUEST_LINE_MATCHER =
14
+ %r{(?:^|[\s'"])(?:([a-z]+)\s)?(?:(https?://[^/]+)(/[^\s'";]*)?|(/[^\s'";]*))}i
13
15
 
14
16
  ##
15
17
  # Creates a query string from data.
@@ -45,7 +47,7 @@ class Kronk
45
47
  # path and options.
46
48
 
47
49
  def self.build_uri uri, options={}
48
- uri ||= Kronk.config[:default_host]
50
+ uri ||= options[:host] || Kronk.config[:default_host]
49
51
  suffix = options[:uri_suffix]
50
52
 
51
53
  uri = "http://#{uri}" unless uri.to_s =~ %r{^(\w+://|/)}
@@ -64,6 +66,7 @@ class Kronk
64
66
 
65
67
  ##
66
68
  # Parses a raw HTTP request-like string into a Kronk::Request instance.
69
+ # Options passed are used as default values for Request#new.
67
70
 
68
71
  def self.parse str, opts={}
69
72
  opts = parse_to_hash str, opts
@@ -75,7 +78,8 @@ class Kronk
75
78
 
76
79
  ##
77
80
  # Parses a raw HTTP request-like string into a Kronk::Request options hash.
78
- # Also parses most single access log entries.
81
+ # Also parses most single access log entries. Options passed are used
82
+ # as default values for Request#new.
79
83
 
80
84
  def self.parse_to_hash str, opts={}
81
85
  lines = str.split("\n")
@@ -86,7 +90,9 @@ class Kronk
86
90
  opts[:headers] ||= {}
87
91
 
88
92
  lines.shift.strip =~ REQUEST_LINE_MATCHER
89
- opts[:http_method], opts[:uri_suffix] = $1, $3
93
+ opts.merge! :http_method => $1,
94
+ :host => $2,
95
+ :uri_suffix => ($3 || $4)
90
96
 
91
97
  lines.each_with_index do |line, i|
92
98
  case line
@@ -105,6 +111,7 @@ class Kronk
105
111
 
106
112
  opts[:data] = lines[body_start..-1].join("\n") if body_start
107
113
 
114
+ opts.delete(:host) if !opts[:host]
108
115
  opts.delete(:uri_suffix) if !opts[:uri_suffix]
109
116
  opts.delete(:headers) if opts[:headers].empty?
110
117
  opts.delete(:http_method) if !opts[:http_method]
@@ -178,7 +185,7 @@ class Kronk
178
185
  end
179
186
 
180
187
 
181
- attr_accessor :body, :headers, :response, :timeout
188
+ attr_accessor :body, :headers, :proxy, :response, :timeout
182
189
 
183
190
  attr_reader :http_method, :uri, :use_cookies
184
191
 
@@ -187,18 +194,16 @@ class Kronk
187
194
  # Supports the following options:
188
195
  # :data:: Hash/String - the data to pass to the http request
189
196
  # :query:: Hash/String - the data to append to the http request path
190
- # :follow_redirects:: Integer/Bool - number of times to follow redirects
191
197
  # :user_agent:: String - user agent string or alias; defaults to 'kronk'
192
198
  # :auth:: Hash - must contain :username and :password; defaults to nil
193
199
  # :headers:: Hash - extra headers to pass to the request
194
200
  # :http_method:: Symbol - the http method to use; defaults to :get
195
- # :proxy:: Hash/String - http proxy to use; defaults to nil
201
+ # :proxy:: Hash/String - http proxy to use; defaults to {}
196
202
  #
197
203
  # Note: if no http method is specified and data is given, will default
198
204
  # to using a post request.
199
205
 
200
206
  def initialize uri, options={}
201
- @HTTP = Net::HTTP
202
207
  @auth = options[:auth]
203
208
 
204
209
  @body = nil
@@ -213,18 +218,15 @@ class Kronk
213
218
 
214
219
  @uri = self.class.build_uri uri, options
215
220
 
221
+ @proxy = options[:proxy] || {}
222
+ @proxy = {:host => @proxy} unless Hash === @proxy
223
+
216
224
  self.user_agent ||= options[:user_agent]
217
225
 
218
226
  self.http_method = options[:http_method] || (@body ? "POST" : "GET")
219
227
 
220
228
  self.use_cookies = options.has_key?(:no_cookies) ?
221
229
  !options[:no_cookies] : Kronk.config[:use_cookies]
222
-
223
- if Hash === options[:proxy]
224
- self.use_proxy options[:proxy][:address], options[:proxy]
225
- else
226
- self.use_proxy options[:proxy]
227
- end
228
230
  end
229
231
 
230
232
 
@@ -278,8 +280,8 @@ class Kronk
278
280
  # The proxy_opts arg can be a uri String or a Hash with the :address key
279
281
  # and optional :username and :password keys.
280
282
 
281
- def use_proxy addr, opts={}
282
- return @HTTP = Net::HTTP unless addr
283
+ def http_proxy addr, opts={}
284
+ return Net::HTTP unless addr
283
285
 
284
286
  host, port = addr.split ":"
285
287
  port ||= opts[:port] || 8080
@@ -289,7 +291,7 @@ class Kronk
289
291
 
290
292
  Kronk::Cmd.verbose "Using proxy #{addr}\n" if host
291
293
 
292
- @HTTP = Net::HTTP::Proxy host, port, user, pass
294
+ Net::HTTP::Proxy host, port, user, pass
293
295
  end
294
296
 
295
297
 
@@ -355,7 +357,9 @@ class Kronk
355
357
  # Retrieve this requests' response.
356
358
 
357
359
  def retrieve
358
- @_req = @HTTP.new @uri.host, @uri.port
360
+ http_class = http_proxy @proxy[:host], @proxy
361
+
362
+ @_req = http_class.new @uri.host, @uri.port
359
363
 
360
364
  @_req.read_timeout = @timeout if @timeout
361
365
  @_req.use_ssl = true if @uri.scheme =~ /^https$/
@@ -424,3 +428,4 @@ class Kronk
424
428
  end
425
429
  end
426
430
  end
431
+