def http(urls_with_config, multi_options={}, &blk)
m = Curl::Multi.new
multi_options[:max_connects] = max_connects = multi_options.key?(:max_connects) ? multi_options[:max_connects] : 10
free_handles = []
multi_options.each { |k,v| m.send("#{k}=", v) }
callbacks = [:on_progress,:on_debug,:on_failure,:on_success,:on_body,:on_header]
add_free_handle = proc do|conf, easy|
c = conf.dup
url = c.delete(:url)
method = c.delete(:method)
headers = c.delete(:headers)
easy = Curl::Easy.new if easy.nil?
easy.url = url
callbacks.each do |cb|
cbproc = c.delete(cb)
easy.send(cb,&cbproc) if cbproc
end
case method
when :post
fields = c.delete(:post_fields)
easy.post_body = fields.map{|f,k| "#{easy.escape(f)}=#{easy.escape(k)}"}.join('&')
when :put
easy.put_data = c.delete(:put_data)
when :head
easy.head = true
when :delete
easy.delete = true
when :get
else
end
headers.each {|k,v| easy.headers[k] = v } if headers
c.each { |k,v| easy.send("#{k}=",v) }
easy.on_complete {|curl,code|
free_handles << curl
blk.call(curl,code,method) if blk
}
m.add(easy)
end
max_connects.times do
conf = urls_with_config.pop
add_free_handle.call conf, nil
break if urls_with_config.empty?
end
consume_free_handles = proc do
if urls_with_config.size > 0 && free_handles.size > 0
easy = free_handles.pop
conf = urls_with_config.pop
add_free_handle.call conf, easy
end
end
if urls_with_config.empty?
m.perform
else
until urls_with_config.empty?
m.perform do
consume_free_handles.call
end
consume_free_handles.call
end
free_handles = nil
end
end