em-http-request 0.2.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -1
- data/.rspec +0 -0
- data/Changelog.md +54 -0
- data/Gemfile +3 -0
- data/README.md +175 -0
- data/Rakefile +11 -37
- data/em-http-request.gemspec +25 -90
- data/examples/fetch.rb +30 -30
- data/examples/fibered-http.rb +38 -38
- data/examples/oauth-tweet.rb +49 -49
- data/examples/socks5.rb +26 -0
- data/examples/websocket-handler.rb +28 -28
- data/examples/websocket-server.rb +8 -8
- data/lib/em-http/client.rb +242 -207
- data/lib/em-http/http_encoding.rb +135 -0
- data/lib/em-http/http_header.rb +71 -0
- data/lib/em-http/http_options.rb +7 -4
- data/lib/em-http/mock.rb +90 -50
- data/lib/em-http/multi.rb +55 -51
- data/lib/em-http/request.rb +2 -4
- data/lib/em-http/version.rb +5 -0
- data/lib/em-http.rb +19 -19
- data/spec/encoding_spec.rb +40 -0
- data/spec/fixtures/google.ca +20 -21
- data/spec/helper.rb +5 -4
- data/spec/mock_spec.rb +85 -36
- data/spec/multi_spec.rb +68 -51
- data/spec/request_spec.rb +422 -108
- data/spec/stallion.rb +65 -3
- metadata +111 -28
- data/LICENSE +0 -58
- data/README.rdoc +0 -138
- data/VERSION +0 -1
- data/lib/em-http/core_ext/hash.rb +0 -53
- data/spec/hash_spec.rb +0 -24
data/.gitignore
CHANGED
data/.rspec
ADDED
|
File without changes
|
data/Changelog.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.3.0 / 2011-01-15
|
|
4
|
+
|
|
5
|
+
- IMPORTANT: default to non-persistent connections (timeout => 0 now requires :keepalive => true)
|
|
6
|
+
- see: https://github.com/igrigorik/em-http-request/commit/1ca5b608e876c18fa6cfa318d0685dcf5b974e09
|
|
7
|
+
|
|
8
|
+
- added escape_utils dependency to fix slow encode on long string escapes
|
|
9
|
+
|
|
10
|
+
- bugfix: proxy authorization headers
|
|
11
|
+
- bugfix: default to Encoding.default_external on invalid encoding in response
|
|
12
|
+
- bugfix: do not normalize URI's internally
|
|
13
|
+
- bugfix: more robust Encoding detection
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## 0.2.15 / 2010-11-18
|
|
17
|
+
|
|
18
|
+
- bugfix: follow redirects on missing content-length
|
|
19
|
+
- bugfix: fixed undefined warnings when running in strict mode
|
|
20
|
+
|
|
21
|
+
## 0.2.14 / 2010-10-06
|
|
22
|
+
|
|
23
|
+
- bugfix: form-encode keys/values of ruby objects passed in as body
|
|
24
|
+
|
|
25
|
+
## 0.2.13 / 2010-09-25
|
|
26
|
+
|
|
27
|
+
- added SOCKS5 proxy support
|
|
28
|
+
- bugfix: follow redirects on HEAD requests
|
|
29
|
+
|
|
30
|
+
## 0.2.12 / 2010-09-12
|
|
31
|
+
|
|
32
|
+
- added headers callback (http.headers {|h| p h})
|
|
33
|
+
- added .close method on client obj to terminate session (accepts message)
|
|
34
|
+
|
|
35
|
+
- bugfix: report 0 for response status on 1.9 on timeouts
|
|
36
|
+
- bugfix: handle bad Location host redirects
|
|
37
|
+
- bugfix: reset host override on connect
|
|
38
|
+
|
|
39
|
+
## 0.2.11 / 2010-08-16
|
|
40
|
+
|
|
41
|
+
- all URIs are now normalized prior to dispatch (and on redirect)
|
|
42
|
+
- default to direct proxy (instead of CONNECT handshake) - better performance
|
|
43
|
+
- specify :proxy => {:tunnel => true} if you need to force CONNECT route
|
|
44
|
+
- MultiRequest accepts block syntax for dispatching parallel requests (see specs)
|
|
45
|
+
- MockHttpRequest accepts block syntax (see Mock wiki page)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
- bugfix: nullbyte frame for websockets
|
|
49
|
+
- bugfix: set @uri on DNS resolve failure
|
|
50
|
+
- bugfix: handle bad hosts in absolute redirects
|
|
51
|
+
- bugfix: reset seen content on redirects (doh!)
|
|
52
|
+
- bugfix: invalid multibyte escape in websocket regex (1.9.2+)
|
|
53
|
+
- bugfix: report etag and last_modified headers correctly
|
|
54
|
+
|
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
EM-HTTP-Request
|
|
2
|
+
===============
|
|
3
|
+
|
|
4
|
+
Asynchronous HTTP client for Ruby, based on EventMachine runtime.
|
|
5
|
+
|
|
6
|
+
- Ragel HTTP parser for speed & performance
|
|
7
|
+
- Simple interface for single & parallel requests via deferred callbacks
|
|
8
|
+
- Automatic gzip & deflate decoding
|
|
9
|
+
- Basic-Auth & OAuth support
|
|
10
|
+
- Custom timeout support
|
|
11
|
+
- Stream response processing
|
|
12
|
+
- Proxy support (with SSL Tunneling): CONNECT, direct & SOCKS5
|
|
13
|
+
- Auto-follow 3xx redirects with custom max depth
|
|
14
|
+
- Bi-directional communication with web-socket services
|
|
15
|
+
- [Native mocking support](http://wiki.github.com/igrigorik/em-http-request/mocking-httprequest) and through [Webmock](http://github.com/bblimke/webmock)
|
|
16
|
+
|
|
17
|
+
Getting started
|
|
18
|
+
---------------
|
|
19
|
+
|
|
20
|
+
gem install em-http-request
|
|
21
|
+
irb:0> require 'em-http'
|
|
22
|
+
|
|
23
|
+
Or checkout [screencast / demo](http://everburning.com/news/eventmachine-screencast-em-http-request/) of using EM-HTTP-Request.
|
|
24
|
+
|
|
25
|
+
Libraries & Applications using em-http
|
|
26
|
+
--------------------------------------
|
|
27
|
+
|
|
28
|
+
- [chirpstream](http://github.com/joshbuddy/chirpstream) - EM client for Twitters Chirpstream API
|
|
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
|
+
--------------------
|
|
88
|
+
|
|
89
|
+
For multi-part uploads, please see [this gist](https://gist.github.com/778639).
|
|
90
|
+
|
|
91
|
+
EventMachine.run {
|
|
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"
|
|
94
|
+
|
|
95
|
+
# ...
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
Streaming body processing
|
|
99
|
+
-------------------------
|
|
100
|
+
|
|
101
|
+
Allows you to consume an HTTP stream of content in real-time. Each time a new piece of content is pushed
|
|
102
|
+
to the client, it is passed to the stream callback for you to operate on.
|
|
103
|
+
|
|
104
|
+
EventMachine.run {
|
|
105
|
+
http = EventMachine::HttpRequest.new('http://www.website.com/').get
|
|
106
|
+
http.stream { |chunk| print chunk }
|
|
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
|
+
}
|
|
171
|
+
|
|
172
|
+
License
|
|
173
|
+
-------
|
|
174
|
+
|
|
175
|
+
(MIT License) - Copyright (c) 2011 Ilya Grigorik
|
data/Rakefile
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
require 'bundler'
|
|
2
|
+
|
|
3
|
+
Bundler.setup
|
|
4
|
+
Bundler.require :default, :development
|
|
5
|
+
|
|
1
6
|
require 'rake'
|
|
2
7
|
require 'rake/clean'
|
|
3
|
-
require 'rake/rdoctask'
|
|
4
8
|
require 'rake/gempackagetask'
|
|
9
|
+
require 'rspec/core/rake_task'
|
|
10
|
+
|
|
5
11
|
require 'fileutils'
|
|
6
12
|
include FileUtils
|
|
7
13
|
|
|
@@ -15,15 +21,6 @@ end
|
|
|
15
21
|
# Default Rake task is compile
|
|
16
22
|
task :default => :compile
|
|
17
23
|
|
|
18
|
-
# RDoc
|
|
19
|
-
Rake::RDocTask.new(:rdoc) do |task|
|
|
20
|
-
task.rdoc_dir = 'doc'
|
|
21
|
-
task.title = 'EventMachine::HttpRequest'
|
|
22
|
-
task.options = %w(--title HttpRequest --main README --line-numbers)
|
|
23
|
-
task.rdoc_files.include(['lib/**/*.rb'])
|
|
24
|
-
task.rdoc_files.include(['README', 'LICENSE'])
|
|
25
|
-
end
|
|
26
|
-
|
|
27
24
|
# Rebuild parser Ragel
|
|
28
25
|
task :ragel do
|
|
29
26
|
Dir.chdir "ext/http11_client" do
|
|
@@ -34,9 +31,8 @@ task :ragel do
|
|
|
34
31
|
end
|
|
35
32
|
end
|
|
36
33
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
end
|
|
34
|
+
desc "Run all RSpec tests"
|
|
35
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
40
36
|
|
|
41
37
|
def make(makedir)
|
|
42
38
|
Dir.chdir(makedir) { sh MAKE }
|
|
@@ -48,7 +44,7 @@ end
|
|
|
48
44
|
|
|
49
45
|
def setup_extension(dir, extension)
|
|
50
46
|
ext = "ext/#{dir}"
|
|
51
|
-
ext_so = "#{ext}/#{extension}.#{Config::
|
|
47
|
+
ext_so = "#{ext}/#{extension}.#{Config::MAKEFILE_CONFIG['DLEXT']}"
|
|
52
48
|
ext_files = FileList[
|
|
53
49
|
"#{ext}/*.c",
|
|
54
50
|
"#{ext}/*.h",
|
|
@@ -81,26 +77,4 @@ setup_extension("http11_client", "http11_client")
|
|
|
81
77
|
task :compile => [:em_buffer, :http11_client]
|
|
82
78
|
|
|
83
79
|
CLEAN.include ['build/*', '**/*.o', '**/*.so', '**/*.a', '**/*.log', 'pkg']
|
|
84
|
-
CLEAN.include ['ext/buffer/Makefile', 'lib/em_buffer.*', 'lib/http11_client.*']
|
|
85
|
-
|
|
86
|
-
begin
|
|
87
|
-
require 'jeweler'
|
|
88
|
-
Jeweler::Tasks.new do |gemspec|
|
|
89
|
-
gemspec.name = "em-http-request"
|
|
90
|
-
gemspec.summary = "EventMachine based, async HTTP Request interface"
|
|
91
|
-
gemspec.description = gemspec.summary
|
|
92
|
-
gemspec.email = "ilya@igvita.com"
|
|
93
|
-
gemspec.homepage = "http://github.com/igrigorik/em-http-request"
|
|
94
|
-
gemspec.authors = ["Ilya Grigorik"]
|
|
95
|
-
gemspec.required_ruby_version = ">= 1.8.6"
|
|
96
|
-
gemspec.extensions = ["ext/buffer/extconf.rb" , "ext/http11_client/extconf.rb"]
|
|
97
|
-
gemspec.add_dependency('eventmachine', '>= 0.12.9')
|
|
98
|
-
gemspec.add_dependency('addressable', '>= 2.0.0')
|
|
99
|
-
gemspec.rubyforge_project = "em-http-request"
|
|
100
|
-
gemspec.files = FileList[`git ls-files`.split]
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
Jeweler::GemcutterTasks.new
|
|
104
|
-
rescue LoadError
|
|
105
|
-
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
|
106
|
-
end
|
|
80
|
+
CLEAN.include ['ext/buffer/Makefile', 'lib/em_buffer.*', 'lib/http11_client.*']
|
data/em-http-request.gemspec
CHANGED
|
@@ -1,97 +1,32 @@
|
|
|
1
|
-
# Generated by jeweler
|
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
|
4
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
+
require "em-http/version"
|
|
5
4
|
|
|
6
5
|
Gem::Specification.new do |s|
|
|
7
|
-
s.name
|
|
8
|
-
s.version
|
|
6
|
+
s.name = "em-http-request"
|
|
7
|
+
s.version = EventMachine::HttpRequest::VERSION
|
|
8
|
+
s.platform = Gem::Platform::RUBY
|
|
9
|
+
s.authors = ["Ilya Grigorik"]
|
|
10
|
+
s.email = ["ilya@igvita.com"]
|
|
11
|
+
s.homepage = "http://github.com/igrigorik/em-http-request"
|
|
12
|
+
s.summary = "EventMachine based, async HTTP Request client"
|
|
13
|
+
s.description = s.summary
|
|
14
|
+
s.rubyforge_project = "em-http-request"
|
|
9
15
|
|
|
10
|
-
s.
|
|
11
|
-
s.
|
|
12
|
-
s.
|
|
13
|
-
s.description = %q{EventMachine based, async HTTP Request interface}
|
|
14
|
-
s.email = %q{ilya@igvita.com}
|
|
15
|
-
s.extensions = ["ext/buffer/extconf.rb", "ext/http11_client/extconf.rb"]
|
|
16
|
-
s.extra_rdoc_files = [
|
|
17
|
-
"LICENSE",
|
|
18
|
-
"README.rdoc"
|
|
19
|
-
]
|
|
20
|
-
s.files = [
|
|
21
|
-
".gitignore",
|
|
22
|
-
"LICENSE",
|
|
23
|
-
"README.rdoc",
|
|
24
|
-
"Rakefile",
|
|
25
|
-
"VERSION",
|
|
26
|
-
"em-http-request.gemspec",
|
|
27
|
-
"examples/fetch.rb",
|
|
28
|
-
"examples/fibered-http.rb",
|
|
29
|
-
"examples/oauth-tweet.rb",
|
|
30
|
-
"examples/websocket-handler.rb",
|
|
31
|
-
"examples/websocket-server.rb",
|
|
32
|
-
"ext/buffer/em_buffer.c",
|
|
33
|
-
"ext/buffer/extconf.rb",
|
|
34
|
-
"ext/http11_client/ext_help.h",
|
|
35
|
-
"ext/http11_client/extconf.rb",
|
|
36
|
-
"ext/http11_client/http11_client.c",
|
|
37
|
-
"ext/http11_client/http11_parser.c",
|
|
38
|
-
"ext/http11_client/http11_parser.h",
|
|
39
|
-
"ext/http11_client/http11_parser.rl",
|
|
40
|
-
"lib/em-http-request.rb",
|
|
41
|
-
"lib/em-http.rb",
|
|
42
|
-
"lib/em-http/client.rb",
|
|
43
|
-
"lib/em-http/core_ext/bytesize.rb",
|
|
44
|
-
"lib/em-http/core_ext/hash.rb",
|
|
45
|
-
"lib/em-http/decoders.rb",
|
|
46
|
-
"lib/em-http/http_options.rb",
|
|
47
|
-
"lib/em-http/mock.rb",
|
|
48
|
-
"lib/em-http/multi.rb",
|
|
49
|
-
"lib/em-http/request.rb",
|
|
50
|
-
"spec/fixtures/google.ca",
|
|
51
|
-
"spec/hash_spec.rb",
|
|
52
|
-
"spec/helper.rb",
|
|
53
|
-
"spec/mock_spec.rb",
|
|
54
|
-
"spec/multi_spec.rb",
|
|
55
|
-
"spec/request_spec.rb",
|
|
56
|
-
"spec/stallion.rb",
|
|
57
|
-
"spec/stub_server.rb"
|
|
58
|
-
]
|
|
59
|
-
s.homepage = %q{http://github.com/igrigorik/em-http-request}
|
|
60
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
|
61
|
-
s.require_paths = ["lib"]
|
|
62
|
-
s.required_ruby_version = Gem::Requirement.new(">= 1.8.6")
|
|
63
|
-
s.rubyforge_project = %q{em-http-request}
|
|
64
|
-
s.rubygems_version = %q{1.3.6}
|
|
65
|
-
s.summary = %q{EventMachine based, async HTTP Request interface}
|
|
66
|
-
s.test_files = [
|
|
67
|
-
"spec/hash_spec.rb",
|
|
68
|
-
"spec/helper.rb",
|
|
69
|
-
"spec/mock_spec.rb",
|
|
70
|
-
"spec/multi_spec.rb",
|
|
71
|
-
"spec/request_spec.rb",
|
|
72
|
-
"spec/stallion.rb",
|
|
73
|
-
"spec/stub_server.rb",
|
|
74
|
-
"examples/fetch.rb",
|
|
75
|
-
"examples/fibered-http.rb",
|
|
76
|
-
"examples/oauth-tweet.rb",
|
|
77
|
-
"examples/websocket-handler.rb",
|
|
78
|
-
"examples/websocket-server.rb"
|
|
79
|
-
]
|
|
16
|
+
s.add_dependency "eventmachine", ">= 0.12.9"
|
|
17
|
+
s.add_dependency "addressable", ">= 2.0.0"
|
|
18
|
+
s.add_dependency "escape_utils"
|
|
80
19
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
20
|
+
s.add_development_dependency "rspec"
|
|
21
|
+
s.add_development_dependency "rake"
|
|
22
|
+
s.add_development_dependency "em-websocket"
|
|
23
|
+
s.add_development_dependency "rack"
|
|
24
|
+
s.add_development_dependency "mongrel", "~> 1.2.0.pre2"
|
|
84
25
|
|
|
85
|
-
|
|
86
|
-
s.add_runtime_dependency(%q<eventmachine>, [">= 0.12.9"])
|
|
87
|
-
s.add_runtime_dependency(%q<addressable>, [">= 2.0.0"])
|
|
88
|
-
else
|
|
89
|
-
s.add_dependency(%q<eventmachine>, [">= 0.12.9"])
|
|
90
|
-
s.add_dependency(%q<addressable>, [">= 2.0.0"])
|
|
91
|
-
end
|
|
92
|
-
else
|
|
93
|
-
s.add_dependency(%q<eventmachine>, [">= 0.12.9"])
|
|
94
|
-
s.add_dependency(%q<addressable>, [">= 2.0.0"])
|
|
95
|
-
end
|
|
96
|
-
end
|
|
26
|
+
s.extensions = ["ext/buffer/extconf.rb", "ext/http11_client/extconf.rb"]
|
|
97
27
|
|
|
28
|
+
s.files = `git ls-files`.split("\n")
|
|
29
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
30
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
31
|
+
s.require_paths = ["lib"]
|
|
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
|