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 CHANGED
@@ -1,4 +1,5 @@
1
1
  *.bundle
2
2
  *.o
3
3
  Makefile
4
- mkmf.log
4
+ mkmf.log
5
+ Gemfile.lock
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
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
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
- task :spec do
38
- sh 'spec spec/*_spec.rb'
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::CONFIG['DLEXT']}"
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.*']
@@ -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 = %q{em-http-request}
8
- s.version = "0.2.9"
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.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Ilya Grigorik"]
12
- s.date = %q{2010-07-07}
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
- if s.respond_to? :specification_version then
82
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
83
- s.specification_version = 3
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
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
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
@@ -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