em-http-request 0.3.0 → 1.0.0.beta.1
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.
- data/.gitignore +1 -0
- data/Changelog.md +10 -0
- data/README.md +43 -160
- data/Rakefile +2 -73
- data/em-http-request.gemspec +7 -7
- data/examples/fetch.rb +30 -30
- data/examples/fibered-http.rb +38 -38
- data/examples/oauth-tweet.rb +49 -49
- data/lib/em-http.rb +4 -6
- data/lib/em-http/client.rb +101 -522
- data/lib/em-http/http_connection.rb +125 -0
- data/lib/em-http/http_encoding.rb +19 -12
- data/lib/em-http/http_header.rb +2 -17
- data/lib/em-http/http_options.rb +37 -19
- data/lib/em-http/request.rb +33 -66
- data/lib/em-http/version.rb +2 -2
- data/spec/client_spec.rb +575 -0
- data/spec/dns_spec.rb +41 -0
- data/spec/encoding_spec.rb +6 -6
- data/spec/external_spec.rb +99 -0
- data/spec/fixtures/google.ca +13 -17
- data/spec/helper.rb +17 -8
- data/spec/http_proxy_spec.rb +53 -0
- data/spec/middleware_spec.rb +114 -0
- data/spec/multi_spec.rb +11 -38
- data/spec/pipelining_spec.rb +38 -0
- data/spec/redirect_spec.rb +114 -0
- data/spec/socksify_proxy_spec.rb +24 -0
- data/spec/ssl_spec.rb +20 -0
- data/spec/stallion.rb +7 -63
- metadata +59 -39
- data/examples/websocket-handler.rb +0 -28
- data/examples/websocket-server.rb +0 -8
- data/ext/buffer/em_buffer.c +0 -639
- data/ext/buffer/extconf.rb +0 -53
- data/ext/http11_client/ext_help.h +0 -14
- data/ext/http11_client/extconf.rb +0 -6
- data/ext/http11_client/http11_client.c +0 -328
- data/ext/http11_client/http11_parser.c +0 -418
- data/ext/http11_client/http11_parser.h +0 -48
- data/ext/http11_client/http11_parser.rl +0 -170
- data/lib/em-http/mock.rb +0 -137
- data/spec/mock_spec.rb +0 -166
- data/spec/request_spec.rb +0 -1003
data/.gitignore
CHANGED
data/Changelog.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.0.0.beta.1 / 2011-02-20 - The big rewrite
|
4
|
+
|
5
|
+
- Switched parser from Ragel to http_parser.rb
|
6
|
+
- Removed em_buffer C extension
|
7
|
+
- Added support for HTTP keepalive
|
8
|
+
- Added support for HTTP pipelining
|
9
|
+
- ~60% performance improvement across the board: less GC time!
|
10
|
+
- Refactored & split all tests
|
11
|
+
- Basic 100-Continue handling on POST/PUT
|
12
|
+
|
3
13
|
## 0.3.0 / 2011-01-15
|
4
14
|
|
5
15
|
- IMPORTANT: default to non-persistent connections (timeout => 0 now requires :keepalive => true)
|
data/README.md
CHANGED
@@ -1,175 +1,58 @@
|
|
1
|
-
EM-HTTP-Request
|
2
|
-
===============
|
1
|
+
# EM-HTTP-Request
|
3
2
|
|
4
|
-
|
3
|
+
Async (EventMachine) HTTP client, with support for:
|
5
4
|
|
6
|
-
-
|
7
|
-
-
|
5
|
+
- Asynchronous HTTP API for single & parallel request execution
|
6
|
+
- Keep-Alive and HTTP pipelining support
|
7
|
+
- Auto-follow 3xx redirects with max depth
|
8
8
|
- Automatic gzip & deflate decoding
|
9
|
-
-
|
10
|
-
-
|
11
|
-
-
|
12
|
-
-
|
13
|
-
-
|
14
|
-
-
|
15
|
-
-
|
9
|
+
- Streaming response processing
|
10
|
+
- Streaming file uploads
|
11
|
+
- HTTP proxy and SOCKS5 support
|
12
|
+
- Basic Auth & OAuth
|
13
|
+
- Connection-level & Global middleware support
|
14
|
+
- Ryan Dahl's HTTP parser via [http_parser.rb](https://github.com/tmm1/http_parser.rb)
|
15
|
+
- Works wherever EventMachine runs
|
16
16
|
|
17
|
-
Getting started
|
18
|
-
---------------
|
17
|
+
## Getting started
|
19
18
|
|
20
|
-
|
21
|
-
irb:0> require 'em-http'
|
19
|
+
gem install em-http-request
|
22
20
|
|
23
|
-
|
21
|
+
- Introductory [screencast](http://everburning.com/news/eventmachine-screencast-em-http-request/)
|
22
|
+
- [Issuing GET/POST/etc requests](https://github.com/igrigorik/em-http-request/wiki/Issuing-Requests)
|
23
|
+
- [Issuing parallel requests with Multi interface](https://github.com/igrigorik/em-http-request/wiki/Parallel-Requests)
|
24
|
+
- [Handling Redirects & Timeouts](https://github.com/igrigorik/em-http-request/wiki/Redirects-and-Timeouts)
|
25
|
+
- [Keep-Alive and HTTP Pipelining](https://github.com/igrigorik/em-http-request/wiki/Keep-Alive-and-HTTP-Pipelining)
|
26
|
+
- [Stream processing responses & uploads](https://github.com/igrigorik/em-http-request/wiki/Streaming)
|
27
|
+
- [Issuing requests through HTTP & SOCKS5 proxies](https://github.com/igrigorik/em-http-request/wiki/Proxy)
|
28
|
+
- [Basic Auth & OAuth](https://github.com/igrigorik/em-http-request/wiki/Basic-Auth-and-OAuth)
|
29
|
+
- [GZIP & Deflate decoding](https://github.com/igrigorik/em-http-request/wiki/Compression)
|
30
|
+
- [EM-HTTP Middleware](https://github.com/igrigorik/em-http-request/wiki/Middleware)
|
24
31
|
|
25
|
-
|
26
|
-
--------------------------------------
|
32
|
+
## Extensions
|
27
33
|
|
28
|
-
-
|
29
|
-
- [RDaneel](http://github.com/hasmanydevelopers/RDaneel) - Ruby crawler which respects robots.txt
|
30
|
-
- [rsolr-async](http://github.com/mwmitchell/rsolr-async) - An asynchronus connection adapter for RSolr
|
31
|
-
- [PubSubHubbub](http://github.com/igrigorik/PubSubHubbub) - Asynchronous PubSubHubbub ruby client
|
32
|
-
- [Firering](http://github.com/EmmanuelOga/firering) - Eventmachine powered Campfire API
|
33
|
-
- and many others.. drop me a link if you want yours included!
|
34
|
-
|
35
|
-
Simple client example
|
36
|
-
---------------------
|
37
|
-
|
38
|
-
EventMachine.run {
|
39
|
-
http = EventMachine::HttpRequest.new('http://127.0.0.1/').get :query => {'keyname' => 'value'}, :timeout => 10
|
40
|
-
|
41
|
-
http.callback {
|
42
|
-
p http.response_header.status
|
43
|
-
p http.response_header
|
44
|
-
p http.response
|
45
|
-
|
46
|
-
EventMachine.stop
|
47
|
-
}
|
48
|
-
}
|
49
|
-
|
50
|
-
Multi-request example
|
51
|
-
---------------------
|
52
|
-
|
53
|
-
Fire and wait for multiple requests to complete via the MultiRequest interface.
|
54
|
-
|
55
|
-
EventMachine.run {
|
56
|
-
multi = EventMachine::MultiRequest.new
|
57
|
-
|
58
|
-
# add multiple requests to the multi-handler
|
59
|
-
multi.add(EventMachine::HttpRequest.new('http://www.google.com/').get)
|
60
|
-
multi.add(EventMachine::HttpRequest.new('http://www.yahoo.com/').get)
|
61
|
-
|
62
|
-
multi.callback {
|
63
|
-
p multi.responses[:succeeded]
|
64
|
-
p multi.responses[:failed]
|
65
|
-
|
66
|
-
EventMachine.stop
|
67
|
-
}
|
68
|
-
}
|
69
|
-
|
70
|
-
Basic-Auth example
|
71
|
-
------------------
|
72
|
-
|
73
|
-
Full basic author support. For OAuth, check examples/oauth-tweet.rb file.
|
74
|
-
|
75
|
-
EventMachine.run {
|
76
|
-
http = EventMachine::HttpRequest.new('http://www.website.com/').get :head => {'authorization' => ['user', 'pass']}
|
77
|
-
|
78
|
-
http.errback { failed }
|
79
|
-
http.callback {
|
80
|
-
p http.response_header
|
81
|
-
EventMachine.stop
|
82
|
-
}
|
83
|
-
}
|
84
|
-
|
85
|
-
|
86
|
-
POSTing data example
|
87
|
-
--------------------
|
34
|
+
Several higher-order Ruby projects have incorporated em-http and other Ruby HTTP clients:
|
88
35
|
|
89
|
-
|
36
|
+
- [EM-Synchrony](https://github.com/igrigorik/em-synchrony) - Collection of convenience classes and primitives to help untangle evented code (Ruby 1.9 + Fibers).
|
37
|
+
- [Rack-Client](https://github.com/halorgium/rack-client) - Use Rack API for server, test, and client side. Supports Rack middleware!
|
38
|
+
- [Example in action](https://gist.github.com/802391)
|
39
|
+
- [Faraday](https://github.com/technoweenie/faraday) - Modular HTTP client library using middleware heavily inspired by Rack.
|
40
|
+
- [Example in action](https://gist.github.com/802395)
|
90
41
|
|
91
|
-
|
92
|
-
http1 = EventMachine::HttpRequest.new('http://www.website.com/').post :body => {"key1" => 1, "key2" => [2,3]}
|
93
|
-
http2 = EventMachine::HttpRequest.new('http://www.website.com/').post :body => "some data"
|
42
|
+
## Testing
|
94
43
|
|
95
|
-
|
96
|
-
|
44
|
+
- [WebMock](https://github.com/bblimke/webmock) - Library for stubbing and setting expectations on HTTP requests in Ruby.
|
45
|
+
- Example of [using WebMock, VCR & EM-HTTP](https://gist.github.com/802553)
|
97
46
|
|
98
|
-
|
99
|
-
-------------------------
|
47
|
+
## Other libraries & applications using EM-HTTP
|
100
48
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
}
|
108
|
-
|
109
|
-
Streaming files from disk
|
110
|
-
-------------------------
|
111
|
-
Allows you to efficiently stream a (large) file from disk via EventMachine's FileStream interface.
|
112
|
-
|
113
|
-
EventMachine.run {
|
114
|
-
http = EventMachine::HttpRequest.new('http://www.website.com/').post :file => 'largefile.txt'
|
115
|
-
http.callback { |chunk| puts "Upload finished!" }
|
116
|
-
}
|
117
|
-
|
118
|
-
Proxy example
|
119
|
-
-------------
|
120
|
-
Full transparent proxy support with support for SSL tunneling.
|
121
|
-
|
122
|
-
EventMachine.run {
|
123
|
-
http = EventMachine::HttpRequest.new('http://www.website.com/').get :proxy => {
|
124
|
-
:host => 'www.myproxy.com',
|
125
|
-
:port => 8080,
|
126
|
-
:authorization => ['username', 'password'] # authorization is optional
|
127
|
-
}
|
128
|
-
|
129
|
-
SOCKS5 Proxy example
|
130
|
-
-------------
|
131
|
-
Tunnel your requests via connect via SOCKS5 proxies (ssh -D port somehost).
|
132
|
-
|
133
|
-
EventMachine.run {
|
134
|
-
http = EventMachine::HttpRequest.new('http://www.website.com/').get :proxy => {
|
135
|
-
:host => 'www.myproxy.com',
|
136
|
-
:port => 8080,
|
137
|
-
:type => :socks
|
138
|
-
}
|
139
|
-
|
140
|
-
Auto-follow 3xx redirects
|
141
|
-
-------------------------
|
142
|
-
|
143
|
-
Specify the max depth of redirects to follow, default is 0.
|
144
|
-
|
145
|
-
EventMachine.run {
|
146
|
-
http = EventMachine::HttpRequest.new('http://www.google.com/').get :redirects => 1
|
147
|
-
http.callback { p http.last_effective_url }
|
148
|
-
}
|
149
|
-
|
150
|
-
WebSocket example
|
151
|
-
-----------------
|
152
|
-
|
153
|
-
[Bi-directional communication with WebSockets](http://www.igvita.com/2009/12/22/ruby-websockets-tcp-for-the-browser/): simply pass in a ws:// resource and the client will negotiate the connection upgrade for you. On successful handshake the callback is invoked, and any incoming messages will be passed to the stream callback. The client can also send data to the server at will by calling the "send" method!
|
154
|
-
|
155
|
-
EventMachine.run {
|
156
|
-
http = EventMachine::HttpRequest.new("ws://yourservice.com/websocket").get :timeout => 0
|
157
|
-
|
158
|
-
http.errback { puts "oops" }
|
159
|
-
http.callback {
|
160
|
-
puts "WebSocket connected!"
|
161
|
-
http.send("Hello client")
|
162
|
-
}
|
163
|
-
|
164
|
-
http.stream { |msg|
|
165
|
-
puts "Recieved: #{msg}"
|
166
|
-
http.send "Pong: #{msg}"
|
167
|
-
}
|
168
|
-
|
169
|
-
http.disconnect { puts "oops, dropped connection?" }
|
170
|
-
}
|
49
|
+
- [chirpstream](http://github.com/joshbuddy/chirpstream) - EM client for Twitters Chirpstream API
|
50
|
+
- [rsolr-async](http://github.com/mwmitchell/rsolr-async) - An asynchronus connection adapter for RSolr
|
51
|
+
- [PubSubHubbub](http://github.com/igrigorik/PubSubHubbub) - Asynchronous PubSubHubbub ruby client
|
52
|
+
- [Firering](http://github.com/EmmanuelOga/firering) - Eventmachine powered Campfire API
|
53
|
+
- [RDaneel](http://github.com/hasmanydevelopers/RDaneel) - Ruby crawler which respects robots.txt
|
54
|
+
- and many others.. drop me a link if you want yours included!
|
171
55
|
|
172
|
-
License
|
173
|
-
-------
|
56
|
+
### License
|
174
57
|
|
175
|
-
(MIT License) - Copyright (c) 2011 Ilya Grigorik
|
58
|
+
(MIT License) - Copyright (c) 2011 Ilya Grigorik
|
data/Rakefile
CHANGED
@@ -1,80 +1,9 @@
|
|
1
1
|
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
2
3
|
|
3
|
-
Bundler.setup
|
4
|
-
Bundler.require :default, :development
|
5
|
-
|
6
|
-
require 'rake'
|
7
|
-
require 'rake/clean'
|
8
|
-
require 'rake/gempackagetask'
|
9
4
|
require 'rspec/core/rake_task'
|
10
5
|
|
11
|
-
require 'fileutils'
|
12
|
-
include FileUtils
|
13
|
-
|
14
|
-
# copied from EventMachine.
|
15
|
-
MAKE = ENV['MAKE'] || if RUBY_PLATFORM =~ /mswin/ # mingw uses make.
|
16
|
-
'nmake'
|
17
|
-
else
|
18
|
-
'make'
|
19
|
-
end
|
20
|
-
|
21
|
-
# Default Rake task is compile
|
22
|
-
task :default => :compile
|
23
|
-
|
24
|
-
# Rebuild parser Ragel
|
25
|
-
task :ragel do
|
26
|
-
Dir.chdir "ext/http11_client" do
|
27
|
-
target = "http11_parser.c"
|
28
|
-
File.unlink target if File.exist? target
|
29
|
-
sh "ragel http11_parser.rl | rlgen-cd -G2 -o #{target}"
|
30
|
-
raise "Failed to build C source" unless File.exist? target
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
6
|
desc "Run all RSpec tests"
|
35
7
|
RSpec::Core::RakeTask.new(:spec)
|
36
8
|
|
37
|
-
|
38
|
-
Dir.chdir(makedir) { sh MAKE }
|
39
|
-
end
|
40
|
-
|
41
|
-
def extconf(dir)
|
42
|
-
Dir.chdir(dir) { ruby "extconf.rb" }
|
43
|
-
end
|
44
|
-
|
45
|
-
def setup_extension(dir, extension)
|
46
|
-
ext = "ext/#{dir}"
|
47
|
-
ext_so = "#{ext}/#{extension}.#{Config::MAKEFILE_CONFIG['DLEXT']}"
|
48
|
-
ext_files = FileList[
|
49
|
-
"#{ext}/*.c",
|
50
|
-
"#{ext}/*.h",
|
51
|
-
"#{ext}/extconf.rb",
|
52
|
-
"#{ext}/Makefile",
|
53
|
-
"lib"
|
54
|
-
]
|
55
|
-
|
56
|
-
task "lib" do
|
57
|
-
directory "lib"
|
58
|
-
end
|
59
|
-
|
60
|
-
desc "Builds just the #{extension} extension"
|
61
|
-
|
62
|
-
mf = (extension + '_makefile').to_sym
|
63
|
-
|
64
|
-
task mf do |t|
|
65
|
-
extconf "#{ext}"
|
66
|
-
end
|
67
|
-
|
68
|
-
task extension.to_sym => [mf] do
|
69
|
-
make "#{ext}"
|
70
|
-
cp ext_so, "lib"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
setup_extension("buffer", "em_buffer")
|
75
|
-
setup_extension("http11_client", "http11_client")
|
76
|
-
|
77
|
-
task :compile => [:em_buffer, :http11_client]
|
78
|
-
|
79
|
-
CLEAN.include ['build/*', '**/*.o', '**/*.so', '**/*.a', '**/*.log', 'pkg']
|
80
|
-
CLEAN.include ['ext/buffer/Makefile', 'lib/em_buffer.*', 'lib/http11_client.*']
|
9
|
+
task :default => :spec
|
data/em-http-request.gemspec
CHANGED
@@ -5,6 +5,7 @@ require "em-http/version"
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "em-http-request"
|
7
7
|
s.version = EventMachine::HttpRequest::VERSION
|
8
|
+
|
8
9
|
s.platform = Gem::Platform::RUBY
|
9
10
|
s.authors = ["Ilya Grigorik"]
|
10
11
|
s.email = ["ilya@igvita.com"]
|
@@ -13,20 +14,19 @@ Gem::Specification.new do |s|
|
|
13
14
|
s.description = s.summary
|
14
15
|
s.rubyforge_project = "em-http-request"
|
15
16
|
|
16
|
-
s.add_dependency "eventmachine"
|
17
|
-
s.add_dependency "addressable", ">= 2.
|
18
|
-
s.add_dependency "
|
17
|
+
s.add_dependency "eventmachine"
|
18
|
+
s.add_dependency "addressable", ">= 2.2.3"
|
19
|
+
s.add_dependency "http_parser.rb", ">= 0.5.1"
|
20
|
+
s.add_dependency "em-socksify"
|
19
21
|
|
20
22
|
s.add_development_dependency "rspec"
|
21
23
|
s.add_development_dependency "rake"
|
22
|
-
s.add_development_dependency "em-websocket"
|
23
24
|
s.add_development_dependency "rack"
|
25
|
+
s.add_development_dependency "yajl-ruby"
|
24
26
|
s.add_development_dependency "mongrel", "~> 1.2.0.pre2"
|
25
27
|
|
26
|
-
s.extensions = ["ext/buffer/extconf.rb", "ext/http11_client/extconf.rb"]
|
27
|
-
|
28
28
|
s.files = `git ls-files`.split("\n")
|
29
29
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
30
30
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
31
31
|
s.require_paths = ["lib"]
|
32
|
-
end
|
32
|
+
end
|
data/examples/fetch.rb
CHANGED
@@ -1,30 +1,30 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'eventmachine'
|
3
|
-
require '../lib/em-http'
|
4
|
-
|
5
|
-
urls = ARGV
|
6
|
-
if urls.size < 1
|
7
|
-
puts "Usage: #{$0} <url> <url> <...>"
|
8
|
-
exit
|
9
|
-
end
|
10
|
-
|
11
|
-
pending = urls.size
|
12
|
-
|
13
|
-
EM.run do
|
14
|
-
urls.each do |url|
|
15
|
-
http = EM::HttpRequest.new(url).get
|
16
|
-
http.callback {
|
17
|
-
puts "#{url}\n#{http.response_header.status} - #{http.response.length} bytes\n"
|
18
|
-
puts http.response
|
19
|
-
|
20
|
-
pending -= 1
|
21
|
-
EM.stop if pending < 1
|
22
|
-
}
|
23
|
-
http.errback {
|
24
|
-
puts "#{url}\n" + http.error
|
25
|
-
|
26
|
-
pending -= 1
|
27
|
-
EM.stop if pending < 1
|
28
|
-
}
|
29
|
-
end
|
30
|
-
end
|
1
|
+
require 'rubygems'
|
2
|
+
require 'eventmachine'
|
3
|
+
require '../lib/em-http'
|
4
|
+
|
5
|
+
urls = ARGV
|
6
|
+
if urls.size < 1
|
7
|
+
puts "Usage: #{$0} <url> <url> <...>"
|
8
|
+
exit
|
9
|
+
end
|
10
|
+
|
11
|
+
pending = urls.size
|
12
|
+
|
13
|
+
EM.run do
|
14
|
+
urls.each do |url|
|
15
|
+
http = EM::HttpRequest.new(url).get
|
16
|
+
http.callback {
|
17
|
+
puts "#{url}\n#{http.response_header.status} - #{http.response.length} bytes\n"
|
18
|
+
puts http.response
|
19
|
+
|
20
|
+
pending -= 1
|
21
|
+
EM.stop if pending < 1
|
22
|
+
}
|
23
|
+
http.errback {
|
24
|
+
puts "#{url}\n" + http.error
|
25
|
+
|
26
|
+
pending -= 1
|
27
|
+
EM.stop if pending < 1
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
data/examples/fibered-http.rb
CHANGED
@@ -1,39 +1,39 @@
|
|
1
|
-
require 'eventmachine'
|
2
|
-
require 'em-http'
|
3
|
-
require 'fiber'
|
4
|
-
|
5
|
-
# Using Fibers in Ruby 1.9 to simulate blocking IO / IO scheduling
|
6
|
-
# while using the async EventMachine API's
|
7
|
-
|
8
|
-
def async_fetch(url)
|
9
|
-
f = Fiber.current
|
10
|
-
http = EventMachine::HttpRequest.new(url).get :timeout => 10
|
11
|
-
|
12
|
-
http.callback { f.resume(http) }
|
13
|
-
http.errback { f.resume(http) }
|
14
|
-
|
15
|
-
return Fiber.yield
|
16
|
-
end
|
17
|
-
|
18
|
-
EventMachine.run do
|
19
|
-
Fiber.new{
|
20
|
-
|
21
|
-
puts "Setting up HTTP request #1"
|
22
|
-
data = async_fetch('http://www.google.com/')
|
23
|
-
puts "Fetched page #1: #{data.response_header.status}"
|
24
|
-
|
25
|
-
puts "Setting up HTTP request #2"
|
26
|
-
data = async_fetch('http://www.yahoo.com/')
|
27
|
-
puts "Fetched page #2: #{data.response_header.status}"
|
28
|
-
|
29
|
-
EventMachine.stop
|
30
|
-
}.resume
|
31
|
-
end
|
32
|
-
|
33
|
-
puts "Done"
|
34
|
-
|
35
|
-
# Setting up HTTP request #1
|
36
|
-
# Fetched page #1: 302
|
37
|
-
# Setting up HTTP request #2
|
38
|
-
# Fetched page #2: 200
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'em-http'
|
3
|
+
require 'fiber'
|
4
|
+
|
5
|
+
# Using Fibers in Ruby 1.9 to simulate blocking IO / IO scheduling
|
6
|
+
# while using the async EventMachine API's
|
7
|
+
|
8
|
+
def async_fetch(url)
|
9
|
+
f = Fiber.current
|
10
|
+
http = EventMachine::HttpRequest.new(url).get :timeout => 10
|
11
|
+
|
12
|
+
http.callback { f.resume(http) }
|
13
|
+
http.errback { f.resume(http) }
|
14
|
+
|
15
|
+
return Fiber.yield
|
16
|
+
end
|
17
|
+
|
18
|
+
EventMachine.run do
|
19
|
+
Fiber.new{
|
20
|
+
|
21
|
+
puts "Setting up HTTP request #1"
|
22
|
+
data = async_fetch('http://www.google.com/')
|
23
|
+
puts "Fetched page #1: #{data.response_header.status}"
|
24
|
+
|
25
|
+
puts "Setting up HTTP request #2"
|
26
|
+
data = async_fetch('http://www.yahoo.com/')
|
27
|
+
puts "Fetched page #2: #{data.response_header.status}"
|
28
|
+
|
29
|
+
EventMachine.stop
|
30
|
+
}.resume
|
31
|
+
end
|
32
|
+
|
33
|
+
puts "Done"
|
34
|
+
|
35
|
+
# Setting up HTTP request #1
|
36
|
+
# Fetched page #1: 302
|
37
|
+
# Setting up HTTP request #2
|
38
|
+
# Fetched page #2: 200
|
39
39
|
# Done
|