astro-em-http-request 0.1.15 → 0.2.2
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/README.rdoc +12 -1
- data/Rakefile +20 -0
- data/VERSION +1 -0
- data/examples/fetch.rb +30 -0
- data/examples/fibered-http.rb +39 -0
- data/lib/em-http/client.rb +7 -2
- data/lib/em-http/request.rb +4 -1
- data/test/stallion.rb +10 -2
- data/test/test_request.rb +55 -1
- metadata +23 -14
- data/.autotest +0 -1
- data/em-http-request.gemspec +0 -44
data/README.rdoc
CHANGED
@@ -7,7 +7,18 @@ EventMachine based HTTP Request interface. Supports streaming response processin
|
|
7
7
|
- Custom timeouts
|
8
8
|
|
9
9
|
Screencast / Demo of using EM-HTTP-Request:
|
10
|
-
|
10
|
+
- http://everburning.com/news/eventmachine-screencast-em-http-request/
|
11
|
+
|
12
|
+
== Getting started
|
13
|
+
|
14
|
+
# install & configure gemcutter repos
|
15
|
+
gem update --system
|
16
|
+
gem install gemcutter
|
17
|
+
gem tumble
|
18
|
+
|
19
|
+
gem install em-http-request
|
20
|
+
|
21
|
+
irb:0> require 'em-http'
|
11
22
|
|
12
23
|
== Simple client example
|
13
24
|
|
data/Rakefile
CHANGED
@@ -82,3 +82,23 @@ task :compile => [:em_buffer, :http11_client]
|
|
82
82
|
|
83
83
|
CLEAN.include ['build/*', '**/*.o', '**/*.so', '**/*.a', '**/*.log', 'pkg']
|
84
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 = "astro-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", "Stephan Maka"]
|
95
|
+
gemspec.extensions = ["ext/buffer/extconf.rb" , "ext/http11_client/extconf.rb"]
|
96
|
+
gemspec.add_dependency('eventmachine', '>= 0.12.2')
|
97
|
+
gemspec.add_dependency('addressable', '>= 2.0.0')
|
98
|
+
gemspec.rubyforge_project = "em-http-request"
|
99
|
+
end
|
100
|
+
|
101
|
+
Jeweler::GemcutterTasks.new
|
102
|
+
rescue LoadError
|
103
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
104
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.2
|
data/examples/fetch.rb
ADDED
@@ -0,0 +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.errors.join("\n")
|
25
|
+
|
26
|
+
pending -= 1
|
27
|
+
EM.stop if pending < 1
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +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
|
39
|
+
# Done
|
data/lib/em-http/client.rb
CHANGED
@@ -256,6 +256,11 @@ module EventMachine
|
|
256
256
|
head['cookie'] = encode_cookie(cookie)
|
257
257
|
end
|
258
258
|
|
259
|
+
# Set content-type header if missing and body is a Ruby hash
|
260
|
+
if not head['content-type'] and options[:body].is_a? Hash
|
261
|
+
head['content-type'] = "application/x-www-form-urlencoded"
|
262
|
+
end
|
263
|
+
|
259
264
|
# Build the request
|
260
265
|
request_header = encode_request(@method, @uri.path, query)
|
261
266
|
request_header << encode_headers(head)
|
@@ -361,9 +366,9 @@ module EventMachine
|
|
361
366
|
# correct location header - some servers will incorrectly give a relative URI
|
362
367
|
if @response_header.location
|
363
368
|
begin
|
364
|
-
location = URI.parse @response_header.location
|
369
|
+
location = Addressable::URI.parse @response_header.location
|
365
370
|
if location.relative?
|
366
|
-
location = (@uri.
|
371
|
+
location = (@uri.join location).to_s
|
367
372
|
@response_header[LOCATION] = location
|
368
373
|
end
|
369
374
|
rescue
|
data/lib/em-http/request.rb
CHANGED
@@ -58,6 +58,9 @@ module EventMachine
|
|
58
58
|
def send_request(method, options)
|
59
59
|
raise ArgumentError, "invalid request path" unless /^\// === @uri.path
|
60
60
|
|
61
|
+
# default connect & inactivity timeouts
|
62
|
+
options[:timeout] = 5 if not options[:timeout]
|
63
|
+
|
61
64
|
# Make sure the port is set as Addressable::URI doesn't set the
|
62
65
|
# port if it isn't there.
|
63
66
|
@uri.port = @uri.port ? @uri.port : 80
|
@@ -86,4 +89,4 @@ module EventMachine
|
|
86
89
|
end
|
87
90
|
end
|
88
91
|
end
|
89
|
-
end
|
92
|
+
end
|
data/test/stallion.rb
CHANGED
@@ -87,7 +87,11 @@ Stallion.saddle :spec do |stable|
|
|
87
87
|
stable.response.status = 200
|
88
88
|
|
89
89
|
elsif stable.request.post?
|
90
|
-
|
90
|
+
if stable.request.path_info == '/echo_content_type'
|
91
|
+
stable.response.write stable.request.env["CONTENT_TYPE"]
|
92
|
+
else
|
93
|
+
stable.response.write stable.request.body.read
|
94
|
+
end
|
91
95
|
|
92
96
|
elsif stable.request.path_info == '/set_cookie'
|
93
97
|
stable.response["Set-Cookie"] = "id=1; expires=Tue, 09-Aug-2011 17:53:39 GMT; path=/;"
|
@@ -126,6 +130,10 @@ Stallion.saddle :spec do |stable|
|
|
126
130
|
stable.response.status = 401
|
127
131
|
end
|
128
132
|
|
133
|
+
elsif stable.request.path_info == '/relative-location'
|
134
|
+
stable.response.status = 301
|
135
|
+
stable.response["Location"] = '/forwarded'
|
136
|
+
|
129
137
|
elsif
|
130
138
|
stable.response.write 'Hello, World!'
|
131
139
|
end
|
@@ -141,4 +149,4 @@ Thread.new do
|
|
141
149
|
end
|
142
150
|
end
|
143
151
|
|
144
|
-
sleep(1)
|
152
|
+
sleep(1)
|
data/test/test_request.rb
CHANGED
@@ -22,7 +22,7 @@ describe EventMachine::HttpRequest do
|
|
22
22
|
|
23
23
|
it "should fail GET on invalid host" do
|
24
24
|
EventMachine.run {
|
25
|
-
http = EventMachine::HttpRequest.new('http://
|
25
|
+
http = EventMachine::HttpRequest.new('http://somethinglocal/').get :timeout => 1
|
26
26
|
http.callback { failed }
|
27
27
|
http.errback {
|
28
28
|
http.response_header.status.should == 0
|
@@ -390,4 +390,58 @@ describe EventMachine::HttpRequest do
|
|
390
390
|
}
|
391
391
|
end
|
392
392
|
end
|
393
|
+
|
394
|
+
context "body content-type encoding" do
|
395
|
+
it "should not set content type on string in body" do
|
396
|
+
EventMachine.run {
|
397
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_type').post :body => "data"
|
398
|
+
|
399
|
+
http.errback { failed }
|
400
|
+
http.callback {
|
401
|
+
http.response_header.status.should == 200
|
402
|
+
http.response.should be_empty
|
403
|
+
EventMachine.stop
|
404
|
+
}
|
405
|
+
}
|
406
|
+
end
|
407
|
+
|
408
|
+
it "should set content-type automatically when passed a ruby hash/array for body" do
|
409
|
+
EventMachine.run {
|
410
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_type').post :body => {:a => :b}
|
411
|
+
|
412
|
+
http.errback { failed }
|
413
|
+
http.callback {
|
414
|
+
http.response_header.status.should == 200
|
415
|
+
http.response.should match("application/x-www-form-urlencoded")
|
416
|
+
EventMachine.stop
|
417
|
+
}
|
418
|
+
}
|
419
|
+
end
|
420
|
+
|
421
|
+
it "should not override content-type when passing in ruby hash/array for body" do
|
422
|
+
EventMachine.run {
|
423
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/echo_content_type').post({
|
424
|
+
:body => {:a => :b}, :head => {'content-type' => 'text'}})
|
425
|
+
|
426
|
+
http.errback { failed }
|
427
|
+
http.callback {
|
428
|
+
http.response_header.status.should == 200
|
429
|
+
http.response.should match("text")
|
430
|
+
EventMachine.stop
|
431
|
+
}
|
432
|
+
}
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
it "should complete a Location: with a relative path" do
|
437
|
+
EventMachine.run {
|
438
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8080/relative-location').get
|
439
|
+
|
440
|
+
http.errback { failed }
|
441
|
+
http.callback {
|
442
|
+
http.response_header['LOCATION'].should == 'http://127.0.0.1:8080/forwarded'
|
443
|
+
EventMachine.stop
|
444
|
+
}
|
445
|
+
}
|
446
|
+
end
|
393
447
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: astro-em-http-request
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ilya Grigorik
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-10-
|
13
|
+
date: 2009-10-31 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -33,22 +33,24 @@ dependencies:
|
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: 2.0.0
|
35
35
|
version:
|
36
|
-
description: EventMachine based HTTP Request interface
|
37
|
-
email:
|
36
|
+
description: EventMachine based, async HTTP Request interface
|
37
|
+
email: ilya@igvita.com
|
38
38
|
executables: []
|
39
39
|
|
40
40
|
extensions:
|
41
41
|
- ext/buffer/extconf.rb
|
42
42
|
- ext/http11_client/extconf.rb
|
43
|
-
extra_rdoc_files:
|
44
|
-
|
43
|
+
extra_rdoc_files:
|
44
|
+
- LICENSE
|
45
|
+
- README.rdoc
|
45
46
|
files:
|
46
|
-
- .autotest
|
47
47
|
- .gitignore
|
48
48
|
- LICENSE
|
49
49
|
- README.rdoc
|
50
50
|
- Rakefile
|
51
|
-
-
|
51
|
+
- VERSION
|
52
|
+
- examples/fetch.rb
|
53
|
+
- examples/fibered-http.rb
|
52
54
|
- ext/buffer/em_buffer.c
|
53
55
|
- ext/buffer/extconf.rb
|
54
56
|
- ext/http11_client/ext_help.h
|
@@ -63,10 +65,10 @@ files:
|
|
63
65
|
- lib/em-http/decoders.rb
|
64
66
|
- lib/em-http/multi.rb
|
65
67
|
- lib/em-http/request.rb
|
66
|
-
- test/test_hash.rb
|
67
68
|
- test/helper.rb
|
68
69
|
- test/stallion.rb
|
69
70
|
- test/stub_server.rb
|
71
|
+
- test/test_hash.rb
|
70
72
|
- test/test_multi.rb
|
71
73
|
- test/test_request.rb
|
72
74
|
has_rdoc: true
|
@@ -74,8 +76,8 @@ homepage: http://github.com/igrigorik/em-http-request
|
|
74
76
|
licenses: []
|
75
77
|
|
76
78
|
post_install_message:
|
77
|
-
rdoc_options:
|
78
|
-
|
79
|
+
rdoc_options:
|
80
|
+
- --charset=UTF-8
|
79
81
|
require_paths:
|
80
82
|
- lib
|
81
83
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -96,6 +98,13 @@ rubyforge_project: em-http-request
|
|
96
98
|
rubygems_version: 1.3.5
|
97
99
|
signing_key:
|
98
100
|
specification_version: 3
|
99
|
-
summary: EventMachine based HTTP Request interface
|
100
|
-
test_files:
|
101
|
-
|
101
|
+
summary: EventMachine based, async HTTP Request interface
|
102
|
+
test_files:
|
103
|
+
- test/helper.rb
|
104
|
+
- test/test_hash.rb
|
105
|
+
- test/test_multi.rb
|
106
|
+
- test/stub_server.rb
|
107
|
+
- test/stallion.rb
|
108
|
+
- test/test_request.rb
|
109
|
+
- examples/fibered-http.rb
|
110
|
+
- examples/fetch.rb
|
data/.autotest
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'autotest/redgreen'
|
data/em-http-request.gemspec
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
spec = Gem::Specification.new do |s|
|
2
|
-
s.name = 'em-http-request'
|
3
|
-
s.version = '0.1.9'
|
4
|
-
s.date = '2009-10-17'
|
5
|
-
s.summary = 'EventMachine based HTTP Request interface'
|
6
|
-
s.description = s.summary
|
7
|
-
s.email = 'ilya@igvita.com'
|
8
|
-
s.homepage = "http://github.com/igrigorik/em-http-request"
|
9
|
-
s.has_rdoc = true
|
10
|
-
s.authors = ["Ilya Grigorik"]
|
11
|
-
s.add_dependency('eventmachine', '>= 0.12.9')
|
12
|
-
s.add_dependency('addressable', '>= 2.0.0')
|
13
|
-
s.extensions = ["ext/buffer/extconf.rb" , "ext/http11_client/extconf.rb"]
|
14
|
-
s.rubyforge_project = "em-http-request"
|
15
|
-
|
16
|
-
# ruby -rpp -e' pp `git ls-files`.split("\n") '
|
17
|
-
s.files = [
|
18
|
-
".autotest",
|
19
|
-
".gitignore",
|
20
|
-
"LICENSE",
|
21
|
-
"README.rdoc",
|
22
|
-
"Rakefile",
|
23
|
-
"em-http-request.gemspec",
|
24
|
-
"ext/buffer/em_buffer.c",
|
25
|
-
"ext/buffer/extconf.rb",
|
26
|
-
"ext/http11_client/ext_help.h",
|
27
|
-
"ext/http11_client/extconf.rb",
|
28
|
-
"ext/http11_client/http11_client.c",
|
29
|
-
"ext/http11_client/http11_parser.c",
|
30
|
-
"ext/http11_client/http11_parser.h",
|
31
|
-
"ext/http11_client/http11_parser.rl",
|
32
|
-
"lib/em-http.rb",
|
33
|
-
"lib/em-http/client.rb",
|
34
|
-
"lib/em-http/core_ext/hash.rb",
|
35
|
-
"lib/em-http/decoders.rb",
|
36
|
-
"lib/em-http/multi.rb",
|
37
|
-
"lib/em-http/request.rb",
|
38
|
-
"test/test_hash.rb",
|
39
|
-
"test/helper.rb",
|
40
|
-
"test/stallion.rb",
|
41
|
-
"test/stub_server.rb",
|
42
|
-
"test/test_multi.rb",
|
43
|
-
"test/test_request.rb"]
|
44
|
-
end
|