-
Notifications
You must be signed in to change notification settings - Fork 221
Issuing Requests
All requests must be dispatched from within the EventMachine run loop. If you need to stop EventMachine after your request has finished, you need to explicitly terminate the runloop by calling EM.stop
– which is the pattern you will see in the following. Let’s do a simple GET request to google.com:
EventMachine.run {
http = EventMachine::HttpRequest.new('http://google.com/').get :query => {'keyname' => 'value'}
http.errback { p 'Uh oh'; EM.stop }
http.callback {
p http.response_header.status
p http.response_header
p http.response
EventMachine.stop
}
}
When you call HttpRequest.new(URL)
, em-http will resolve the destination of the URL (perform the DNS lookup and connect to the server). By default, no request is dispatched when you call new, only the connection is established. Then, we call .get
on the connection to issue the request. In this case, .get
does not specify a path and em-http will default to the path originally specified in the initializer. Note that we can customize the query string by passing in an arbitrary Ruby hash.
Once the request is dispatched, we setup a callback
, and an errback
– these functions will be called by EventMachine when the request is complete. Errback function is invoked only in the case of a failed connection such as a timeout or bad DNS hostname. As long as the connection is established, EventMachine will call the callback
and pass you the returned http response.
Optionally, you can also specify stream
and headers
callbacks. When you specify a headers
callback, once em-http successfully parses the HTTP header (and before any body data is processed), it will call your function with the hash of the response headers for you to inspect. Following that, if you specify a stream
callback, then all data received by em-http after the headers will be passed in chunks to your function right as it arrives on the wire.
EventMachine.run do
http = EventMachine::HttpRequest.new('http://google.com/').get
http.headers { |hash| p [:headers, hash] }
http.stream { |chunk| p [:data, chunk] }
end
EventMachine.run {
http = EventMachine::HttpRequest.new('http://google.com/').get
http = EventMachine::HttpRequest.new('http://google.com/').post
http = EventMachine::HttpRequest.new('http://google.com/').head
http = EventMachine::HttpRequest.new('http://google.com/').put
http = EventMachine::HttpRequest.new('http://google.com/').delete
# ...
}
EventMachine.run {
http1 = EventMachine::HttpRequest.new('http://google.com/?q=paramA').get
http2 = EventMachine::HttpRequest.new('http://google.com/?q=paramA').get :query => {'q2' => 'paramB'}
http3 = EventMachine::HttpRequest.new('http://google.com/'?q=paramA).get :query => 'q2=paramB'
# ...
}
You can customize your request query string in a variety of ways:
- pass it in directly as part of the URL
- provide a ruby hash (which will be URL encoded for you)
- provide a string
- mix any of the above approaches: em-http will merge the parameters of your original URL with your custom parameters
EventMachine.run {
http1 = EventMachine::HttpRequest.new('http://google.com/search').get
http2 = EventMachine::HttpRequest.new('http://google.com/').get :path => '/search'
# ...
}
Both of the above approaches will result in the same request. If you’re wondering why em-http supports both.. hint: keep-alive & pipelining.
EventMachine.run {
http = EventMachine::HttpRequest.new('http://google.com/').post :body => "string"
http = EventMachine::HttpRequest.new('http://google.com/').post :body => {:string => [:value1, :value2]}
# ...
}
If you provide a Ruby string, then make sure to specify the correct encoding headers such that the upstream servers knows how to parse your data. Alternatively, you can provide a Ruby hash, in which case em-http will form-encode the data for you, set it as the POST body, and set the proper form-encoding HTTP headers within the request.
EventMachine.run {
http = EventMachine::HttpRequest.new('http://google.com/').get :head => {"connection" => "close"}
# ...
}
You can specify your own custom HTTP headers by providing a ruby hash of key-value pairs to em-http.
Available connection specific settings with em-http:
EventMachine.run {
options = {
:connect_timeout => 5, # default connection setup timeout
:inactivity_timeout => 10, # default connection inactivity (post-setup) timeout
:ssl => {
:private_key_file => '/tmp/server.key',
:cert_chain_file => '/tmp/server.crt',
:verify_peer => false
},
:bind => {
:host => '123.123.123.123', # use a specific interface for outbound request
:port => '123'
}
:proxy => {
:host => '127.0.0.1', # proxy address
:port => 9000, # proxy port
:type => :socks5 # default proxy mode is HTTP proxy, change to :socks5 if required
:authorization => ['user', 'pass'] # proxy authorization header
}
}
http = EventMachine::HttpRequest.new('http://google.com/', options).get
# ...
}
Available request specific settings with em-http:
EventMachine.run {
connection_options = { ... }
request_options = {
:redirects => 5, # follow 3XX redirects up to depth 5
:keepalive => true, # enable keep-alive (don't send Connection:close header)
:file => 'path/to/file', # stream data off disk through EM's fast file stream
:path => '/string', # request path (will override one in host)
:query => 'key=val' || {}, # query string, can be passed as string or as a ruby hash
:body => 'string' || {}, # string, or ruby hash (which will be form encoded)
:head => {
'authorization' => ['user', 'pass'] # basic auth will be automatically encoded
'x-header' => 'string', # list of request headers
}
}
http = EventMachine::HttpRequest.new('http://google.com/', connection_options).get request_options
# ...
}