EzDevInfo.com

em-http-request

Asynchronous HTTP Client (EventMachine + Ruby)

How to make certain (limited) number of api requests using rubys em-http-request?

I have an API with limited number of calls per sec (100 requests per 100 sec). How can I utilize em-http-request (ideally with Redis) to make such calls at the fastest rate possible (to not exceed api rate limit?).


Source: (StackOverflow)

Get only response headers in em_http_request

How can I get only response headers in an em_http_request?

I tried to use this code:

EventMachine.run do
  http = EventMachine::HttpRequest.new('my_url').get
  http.headers do |headers|
    Fiber.current.resume headers
  end
end

but I don't want to receive the whole body. How I can stop the request's execution? http.close doesn't work.

UPD
http.instance_variable_get(:'@conn').close helps me, but may be you know more interesting solution


Source: (StackOverflow)

Advertisements

em-synchrony using http.get and iterators causing can't yield in root Fiber error

A very simple case where I get the root Fiber error.

require 'em-synchrony'
require 'em-synchrony/em-http'

urls = %w{http://www.google.com http://www.google.com http://www.google.com http://www.google.com http://www.google.com http://www.google.com}
EM.synchrony do

  EM::Synchrony::Iterator.new(urls, 2).each(
      proc { |url, iter|

        EM::HttpRequest.new(url).get
        iter.next
      }
  )
end

I can use async here, but not a sync http request.


Source: (StackOverflow)

Using EventMachine to make multiple request using same connection?

I have an EventMachine running that is listening for UDP packets. Every time a UDP packet is received, I would like to forward the data to some database using a REST call. I have created an EM::Connection subclass in which the receive_data method forwards the data through a REST call.

Since the frequency of data is quite high, I would like to reuse the connection between requests (using "keep-alive") and if possible also use pipelining. What would be a good way to share the connection between different calls?

Currently my UDPHandler looks something like the following:

module Udp
  module Collector
    class UDPHandler < EM::Connection
      def receive_data(data)
        http = EventMachine::HttpRequest.new('http://databaseurl.com/').post body: data
      end
    end
  end
end

This class is called as follows:

EM.run do
  EM.open_datagram_socket('0.0.0.0', 9000, Udp::Collector::UDPHandler)
end

I thought of making the request object a class variable but I don't think that is a good idea in the context of eventmachines. Or is it?


Source: (StackOverflow)

em-http-request unexpected result when using tor as proxy

I've created a gist which shows exactly what happens.
https://gist.github.com/4418148
I've tested a version which used ruby's 'net/http' library and 'socksify/http' and it worked perfect but if the EventMachine version returns an unexpected result.
The response in Tor Browser is correct but using EventMachine is not!

It return a response but it's not the same as returned response when you send the request via browser, net/http with or without proxy.

For convenience, I will also paste it here.

require 'em-http-request'

DEL = '-'*40
@results = 0

def run_with_proxy
  connection_opts = {:proxy => {:host => '127.0.0.1', :port => 9050, :type => :socks5}}
  conn = EM::HttpRequest.new("http://www.apolista.de/tegernsee/kloster-apotheke",       connection_opts)
  http = conn.get
  http.callback {
    if http.response.include? "Oops"
      puts "#{DEL}failed with proxy#{DEL}", http.response
    else
      puts "#{DEL}success with proxy#{DEL}", http.response
    end
    @results+=1
    EM.stop_event_loop if @results == 2
  }
end

def run_without_proxy
  conn = EM::HttpRequest.new("http://www.apolista.de/tegernsee/kloster-apotheke")
  http = conn.get
  http.callback {
    if http.response.include? "Oops"
      puts "#{DEL}failed without proxy#{DEL}", http.response
    else
      puts "#{DEL}success without proxy#{DEL}", http.response
    end
    @results+=1
    EM.stop_event_loop if @results == 2
  }
end

EM.run do
  run_with_proxy
  run_without_proxy
end

Appreciate any clarification.


Source: (StackOverflow)

EM-HTTP-REQUEST and SINATRA - combining/merging multiple api request into one result?

My first time dealing with sinatra and parallel em-http-request. And i dont know how to combine/merge into one results and when to EventMachine.stop? . Consider this:

get '/data/:query' do
  content_type :json

  EventMachine.run do
    http1 = EventMachine::HttpRequest.new('v1/').get
    http2 = EventMachine::HttpRequest.new('v2/').get

    http1.errback { p 'Uh oh nooooooo'; EventMachine.stop }

    http1.callback {
     // do some operation http1.repsonse
     Crack::XML.parse(http1.response).to_json
      EventMachine.stop
    }

    http2.callback {
     // do some operation http2.response
     Crack::XML.parse(http2.response).to_json
     EventMachine.stop
    } 

  end

  somehow merge 
  return merged_result

end

Source: (StackOverflow)

Simple POST request failing with em-http-request

The following query works with requestmaker:

URI:

http://www.cleverbot.com/webservicemin/

Query:

start=y&icognoid=wsf&fno=0&sub=Say&islearning=1&cleanslate=false&stimulus=!!!%20there%20was%20an%20error%20!!!&icognocheck=af71393ce00d9126a247df2f53948e79

But it does not work with em-http-request:

require 'eventmachine'
require 'em-http-request'


uri  = 'http://www.cleverbot.com/webservicemin/'
query = 'start=y&icognoid=wsf&fno=0&sub=Say&islearning=1&cleanslate=false&stimulus=!!!%20there%20was%20an%20error%20!!!&icognocheck=af71393ce00d9126a247df2f53948e79'

EM.run do

  http = EM::HttpRequest.new(uri).post(query: query)
  http.callback { puts http.response; EM.stop }
  http.errback { puts 'There was an error'; EM.stop }
end

which prints There was an error. I feel stumped because this simple example works with any other method of sending a request and I've checked around to see if my usage was wrong but it doesn't seem to be.

Edit: Just for reference, this is not the correct way to use cleverbot. I made a second mistake by sending the data under :query. If you use http.post(body: query) it will work


Source: (StackOverflow)

How to test for asynchronous HTTP requests in ruby using EventMachine

I'm getting messages of a RabbitMQ queue and each message is a URL that I want to make a request to. Now I'm using the AMQP gem to subscribe to the queue and that uses EventMachine, so I'm using the the em-http-request library to make the http requests. According to the documentation here: https://github.com/igrigorik/em-http-request/wiki/Parallel-Requests The following will issue asynchronous http-requests:

EventMachine.run {
    http1 = EventMachine::HttpRequest.new('http://google.com/').get
    http2 = EventMachine::HttpRequest.new('http://yahoo.com/').get
    http1.callback { }
    http2.callback { } 
end

So when I subscribe to the RabbitMQ queue I have the following code:

x = 0
EventMachine.run do
    connection = AMQP.connect(:host => '127.0.0.1')
    channel  = AMQP::Channel.new(connection)
    channel.prefetch(50)
    queue    = channel.queue("http.requests")
    exchange = channel.direct("")

    queue.subscribe do |metadata, payload|
        url = payload.inspect
        eval "
        @http#{x} = EventMachine::HttpRequest.new(url).get
        @http#{x}.callback do
            puts \"got a response\"
            puts @http#{x}.response
        end
        x = x+1
        "
    end
end

This dynamically creates new variables and creates new http requests, similar to the way described in the em-http-request documentation. But is there a way to test whether the requests are actually being made asynchronously? Is it possible to write to the console every time a get request is fired off so I can see they are fired off one after the other without waiting for a response?


Source: (StackOverflow)

How to complete HTTP requests without stopping EventMachine?

I want to use Ruby EventMachine and em-http-request to run parallel HTTP synchronous requests triggered from different threads.

The idea is to run a single reactor in its own thread and push HTTP requests to complete on its event queue thanks to EM.next_tick.

The pattern for every call could be

def complete_request(url, options)
  Thread.new { EM.run } unless EM.reactor_running?
  EM.run do
    EM.next_tick do
      con = EventMachine::HttpRequest.new(url, options[:connection_headers])
      http = com.setup_request(verb, head: options[:headers], body: options[:body])
      http.errback { }
      http.callback { }
    end
  end
  # wait for request completion (but how?)
  ...
end

reqs = []
responses = []
reqs << Thread.new { responses << complete_request('http://www.stackoverflow.com', verb: get) }
reqs << Thread.new { responses << complete_request('http://www.flickr.com', verb: get) }
reqs.each { |req| req.join }    

To make the requests synchronous, I tried to use Fibers but unsuccessfully. Either the request fails to connect or it completes but never exits the event loop.

I don't want to call EM.stop in the callbacks because it would screw up other requests being executed in parallel I guess, and would also stop the reactor while I want it to run until I decide no more requests should be treated.

Does anyone already try to use EventMachine and em-http-request this way ? Can EventMachine support this use case ?


Source: (StackOverflow)

Most efficient way to perform ruby http async post

I'm new in Ruby. I need to fetch some info using post request. The number of requests can be till 1 000 000. So I want to perform it async, handling callbacks. I found some approaches that uses EventMachine, but there is no obvious way to perform multi http post request, so now I use following function:

def fetchFriends(  )
    EM.run do   

        1.upto(1000) do |x|

            http = ( EM::HttpRequest.new('https://api.vk.com/method/friends.get', :connect_timeout => 10, :inactivity_timeout => 10 ).post :body => {:user_id => x } )

            http.errback { 
                p "Oops"; 
                EM.stop if counter == 1
                counter-=1;
            } 
            http.callback {
                puts "succeed"
                EM.stop if counter == 1
                counter-=1;
            }
        end
    end
end

But in this case only first request performs correctly, other requests returns 0 as response from server, and empty body, so it looks like some error in EM.

So, can anyone advice me how to write some ruby.async( "request", callback, errorback )?


Source: (StackOverflow)