ably-em-http-request 1.1.8
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.
- checksums.yaml +7 -0
- data/.gemtest +0 -0
- data/.github/workflows/ci.yml +22 -0
- data/.gitignore +9 -0
- data/.rspec +0 -0
- data/Changelog.md +78 -0
- data/Gemfile +14 -0
- data/LICENSE +21 -0
- data/README.md +66 -0
- data/Rakefile +10 -0
- data/ably-em-http-request.gemspec +33 -0
- data/benchmarks/clients.rb +170 -0
- data/benchmarks/em-excon.rb +87 -0
- data/benchmarks/em-profile.gif +0 -0
- data/benchmarks/em-profile.txt +65 -0
- data/benchmarks/server.rb +48 -0
- data/examples/.gitignore +1 -0
- data/examples/digest_auth/client.rb +25 -0
- data/examples/digest_auth/server.rb +28 -0
- data/examples/fetch.rb +30 -0
- data/examples/fibered-http.rb +51 -0
- data/examples/multi.rb +25 -0
- data/examples/oauth-tweet.rb +35 -0
- data/examples/socks5.rb +23 -0
- data/lib/em/io_streamer.rb +51 -0
- data/lib/em-http/client.rb +343 -0
- data/lib/em-http/core_ext/bytesize.rb +6 -0
- data/lib/em-http/decoders.rb +252 -0
- data/lib/em-http/http_client_options.rb +51 -0
- data/lib/em-http/http_connection.rb +408 -0
- data/lib/em-http/http_connection_options.rb +72 -0
- data/lib/em-http/http_encoding.rb +151 -0
- data/lib/em-http/http_header.rb +85 -0
- data/lib/em-http/http_status_codes.rb +59 -0
- data/lib/em-http/middleware/digest_auth.rb +114 -0
- data/lib/em-http/middleware/json_response.rb +17 -0
- data/lib/em-http/middleware/oauth.rb +42 -0
- data/lib/em-http/middleware/oauth2.rb +30 -0
- data/lib/em-http/multi.rb +59 -0
- data/lib/em-http/request.rb +25 -0
- data/lib/em-http/version.rb +7 -0
- data/lib/em-http-request.rb +1 -0
- data/lib/em-http.rb +20 -0
- data/spec/client_fiber_spec.rb +23 -0
- data/spec/client_spec.rb +1000 -0
- data/spec/digest_auth_spec.rb +48 -0
- data/spec/dns_spec.rb +41 -0
- data/spec/encoding_spec.rb +49 -0
- data/spec/external_spec.rb +146 -0
- data/spec/fixtures/google.ca +16 -0
- data/spec/fixtures/gzip-sample.gz +0 -0
- data/spec/gzip_spec.rb +91 -0
- data/spec/helper.rb +27 -0
- data/spec/http_proxy_spec.rb +268 -0
- data/spec/middleware/oauth2_spec.rb +15 -0
- data/spec/middleware_spec.rb +143 -0
- data/spec/multi_spec.rb +104 -0
- data/spec/pipelining_spec.rb +62 -0
- data/spec/redirect_spec.rb +430 -0
- data/spec/socksify_proxy_spec.rb +56 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/ssl_spec.rb +67 -0
- data/spec/stallion.rb +334 -0
- data/spec/stub_server.rb +45 -0
- metadata +269 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
describe EventMachine::AblyHttpRequest::Middleware::OAuth2 do
|
2
|
+
it "should add an access token to a URI with no query parameters" do
|
3
|
+
middleware = EventMachine::AblyHttpRequest::Middleware::OAuth2.new(:access_token => "fedcba9876543210")
|
4
|
+
uri = Addressable::URI.parse("https://graph.facebook.com/me")
|
5
|
+
middleware.update_uri! uri
|
6
|
+
uri.to_s.should == "https://graph.facebook.com/me?access_token=fedcba9876543210"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should add an access token to a URI with query parameters" do
|
10
|
+
middleware = EventMachine::AblyHttpRequest::Middleware::OAuth2.new(:access_token => "fedcba9876543210")
|
11
|
+
uri = Addressable::URI.parse("https://graph.facebook.com/me?fields=photo")
|
12
|
+
middleware.update_uri! uri
|
13
|
+
uri.to_s.should == "https://graph.facebook.com/me?fields=photo&access_token=fedcba9876543210"
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe EventMachine::AblyHttpRequest::HttpRequest do
|
4
|
+
|
5
|
+
class EmptyMiddleware; end
|
6
|
+
|
7
|
+
class GlobalMiddleware
|
8
|
+
def response(resp)
|
9
|
+
resp.response_header['X-Global'] = 'middleware'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should accept middleware" do
|
14
|
+
EventMachine.run {
|
15
|
+
lambda {
|
16
|
+
conn = EM::AblyHttpRequest::HttpRequest.new('http://127.0.0.1:8090')
|
17
|
+
conn.use ResponseMiddleware
|
18
|
+
conn.use EmptyMiddleware
|
19
|
+
|
20
|
+
EM.stop
|
21
|
+
}.should_not raise_error
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
context "configuration" do
|
26
|
+
class ConfigurableMiddleware
|
27
|
+
def initialize(conf, &block)
|
28
|
+
@conf = conf
|
29
|
+
@block = block
|
30
|
+
end
|
31
|
+
|
32
|
+
def response(resp)
|
33
|
+
resp.response_header['X-Conf'] = @conf
|
34
|
+
resp.response_header['X-Block'] = @block.call
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should accept middleware initialization parameters" do
|
39
|
+
EventMachine.run {
|
40
|
+
conn = EM::AblyHttpRequest::HttpRequest.new('http://127.0.0.1:8090')
|
41
|
+
conn.use ConfigurableMiddleware, 'conf-value' do
|
42
|
+
'block-value'
|
43
|
+
end
|
44
|
+
|
45
|
+
req = conn.get
|
46
|
+
req.callback {
|
47
|
+
req.response_header['X-Conf'].should match('conf-value')
|
48
|
+
req.response_header['X-Block'].should match('block-value')
|
49
|
+
EM.stop
|
50
|
+
}
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "request" do
|
56
|
+
class ResponseMiddleware
|
57
|
+
def response(resp)
|
58
|
+
resp.response_header['X-Header'] = 'middleware'
|
59
|
+
resp.response = 'Hello, Middleware!'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should execute response middleware before user callbacks" do
|
64
|
+
EventMachine.run {
|
65
|
+
conn = EM::AblyHttpRequest::HttpRequest.new('http://127.0.0.1:8090')
|
66
|
+
conn.use ResponseMiddleware
|
67
|
+
|
68
|
+
req = conn.get
|
69
|
+
req.callback {
|
70
|
+
req.response_header['X-Header'].should match('middleware')
|
71
|
+
req.response.should match('Hello, Middleware!')
|
72
|
+
EM.stop
|
73
|
+
}
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should execute global response middleware before user callbacks" do
|
78
|
+
EventMachine.run {
|
79
|
+
EM::AblyHttpRequest::HttpRequest.use GlobalMiddleware
|
80
|
+
|
81
|
+
conn = EM::AblyHttpRequest::HttpRequest.new('http://127.0.0.1:8090')
|
82
|
+
|
83
|
+
req = conn.get
|
84
|
+
req.callback {
|
85
|
+
req.response_header['X-Global'].should match('middleware')
|
86
|
+
EM.stop
|
87
|
+
}
|
88
|
+
}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "request" do
|
93
|
+
class RequestMiddleware
|
94
|
+
def request(client, head, body)
|
95
|
+
head['X-Middleware'] = 'middleware' # insert new header
|
96
|
+
body += ' modified' # modify post body
|
97
|
+
|
98
|
+
[head, body]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should execute request middleware before dispatching request" do
|
103
|
+
EventMachine.run {
|
104
|
+
conn = EventMachine::AblyHttpRequest::HttpRequest.new('http://127.0.0.1:8090/')
|
105
|
+
conn.use RequestMiddleware
|
106
|
+
|
107
|
+
req = conn.post :body => "data"
|
108
|
+
req.callback {
|
109
|
+
req.response_header.status.should == 200
|
110
|
+
req.response.should match(/data modified/)
|
111
|
+
EventMachine.stop
|
112
|
+
}
|
113
|
+
}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "jsonify" do
|
118
|
+
class JSONify
|
119
|
+
def request(client, head, body)
|
120
|
+
[head, MultiJson.dump(body)]
|
121
|
+
end
|
122
|
+
|
123
|
+
def response(resp)
|
124
|
+
resp.response = MultiJson.load(resp.response)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should use middleware to JSON encode and JSON decode the body" do
|
129
|
+
EventMachine.run {
|
130
|
+
conn = EventMachine::AblyHttpRequest::HttpRequest.new('http://127.0.0.1:8090/')
|
131
|
+
conn.use JSONify
|
132
|
+
|
133
|
+
req = conn.post :body => {:ruby => :hash}
|
134
|
+
req.callback {
|
135
|
+
req.response_header.status.should == 200
|
136
|
+
req.response.should == {"ruby" => "hash"}
|
137
|
+
EventMachine.stop
|
138
|
+
}
|
139
|
+
}
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
data/spec/multi_spec.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'stallion'
|
3
|
+
|
4
|
+
describe EventMachine::AblyHttpRequest::MultiRequest do
|
5
|
+
|
6
|
+
let(:multi) { EventMachine::AblyHttpRequest::MultiRequest.new }
|
7
|
+
let(:url) { 'http://127.0.0.1:8090/' }
|
8
|
+
|
9
|
+
it "should submit multiple requests in parallel and return once all of them are complete" do
|
10
|
+
EventMachine.run {
|
11
|
+
multi.add :a, EventMachine::AblyHttpRequest::HttpRequest.new(url).get
|
12
|
+
multi.add :b, EventMachine::AblyHttpRequest::HttpRequest.new(url).post
|
13
|
+
multi.add :c, EventMachine::AblyHttpRequest::HttpRequest.new(url).head
|
14
|
+
multi.add :d, EventMachine::AblyHttpRequest::HttpRequest.new(url).delete
|
15
|
+
multi.add :e, EventMachine::AblyHttpRequest::HttpRequest.new(url).put
|
16
|
+
|
17
|
+
multi.callback {
|
18
|
+
multi.responses[:callback].size.should == 5
|
19
|
+
multi.responses[:callback].each { |name, response|
|
20
|
+
[ :a, :b, :c, :d, :e ].should include(name)
|
21
|
+
response.response_header.status.should == 200
|
22
|
+
}
|
23
|
+
multi.responses[:errback].size.should == 0
|
24
|
+
|
25
|
+
EventMachine.stop
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should require unique keys for each deferrable" do
|
31
|
+
lambda do
|
32
|
+
multi.add :df1, EM::DefaultDeferrable.new
|
33
|
+
multi.add :df1, EM::DefaultDeferrable.new
|
34
|
+
end.should raise_error("Duplicate Multi key")
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
describe "#requests" do
|
39
|
+
it "should return the added requests" do
|
40
|
+
request1 = double('request1', :callback => nil, :errback => nil)
|
41
|
+
request2 = double('request2', :callback => nil, :errback => nil)
|
42
|
+
|
43
|
+
multi.add :a, request1
|
44
|
+
multi.add :b, request2
|
45
|
+
|
46
|
+
multi.requests.should == {:a => request1, :b => request2}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#responses" do
|
51
|
+
it "should have an empty :callback hash" do
|
52
|
+
multi.responses[:callback].should be_a(Hash)
|
53
|
+
multi.responses[:callback].size.should == 0
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should have an empty :errback hash" do
|
57
|
+
multi.responses[:errback].should be_a(Hash)
|
58
|
+
multi.responses[:errback].size.should == 0
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should provide access to the requests by name" do
|
62
|
+
EventMachine.run {
|
63
|
+
request1 = EventMachine::AblyHttpRequest::HttpRequest.new(url).get
|
64
|
+
request2 = EventMachine::AblyHttpRequest::HttpRequest.new(url).post
|
65
|
+
multi.add :a, request1
|
66
|
+
multi.add :b, request2
|
67
|
+
|
68
|
+
multi.callback {
|
69
|
+
multi.responses[:callback][:a].should equal(request1)
|
70
|
+
multi.responses[:callback][:b].should equal(request2)
|
71
|
+
|
72
|
+
EventMachine.stop
|
73
|
+
}
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#finished?" do
|
79
|
+
it "should be true when no requests have been added" do
|
80
|
+
multi.should be_finished
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should be false while the requests are not finished" do
|
84
|
+
EventMachine.run {
|
85
|
+
multi.add :a, EventMachine::AblyHttpRequest::HttpRequest.new(url).get
|
86
|
+
multi.should_not be_finished
|
87
|
+
|
88
|
+
EventMachine.stop
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should be finished when all requests are finished" do
|
93
|
+
EventMachine.run {
|
94
|
+
multi.add :a, EventMachine::AblyHttpRequest::HttpRequest.new(url).get
|
95
|
+
multi.callback {
|
96
|
+
multi.should be_finished
|
97
|
+
|
98
|
+
EventMachine.stop
|
99
|
+
}
|
100
|
+
}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe EventMachine::AblyHttpRequest::HttpRequest do
|
4
|
+
|
5
|
+
it "should perform successful pipelined GETs" do
|
6
|
+
EventMachine.run do
|
7
|
+
|
8
|
+
# Mongrel doesn't support pipelined requests - bah!
|
9
|
+
conn = EventMachine::AblyHttpRequest::HttpRequest.new('http://www.bing.com/')
|
10
|
+
|
11
|
+
pipe1 = conn.get :keepalive => true
|
12
|
+
pipe2 = conn.get :path => '/news', :keepalive => true
|
13
|
+
|
14
|
+
processed = 0
|
15
|
+
stop = proc { EM.stop if processed == 2}
|
16
|
+
|
17
|
+
pipe1.errback { failed(conn) }
|
18
|
+
pipe1.callback {
|
19
|
+
processed += 1
|
20
|
+
pipe1.response_header.status.should == 200
|
21
|
+
stop.call
|
22
|
+
}
|
23
|
+
|
24
|
+
pipe2.errback { failed(conn) }
|
25
|
+
pipe2.callback {
|
26
|
+
processed += 1
|
27
|
+
pipe2.response_header.status.should == 200
|
28
|
+
pipe2.response.should match(/html/i)
|
29
|
+
stop.call
|
30
|
+
}
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should perform successful pipelined HEAD requests" do
|
36
|
+
EventMachine.run do
|
37
|
+
conn = EventMachine::AblyHttpRequest::HttpRequest.new('http://www.bing.com/')
|
38
|
+
|
39
|
+
pipe1 = conn.head :keepalive => true
|
40
|
+
pipe2 = conn.head :path => '/news', :keepalive => true
|
41
|
+
|
42
|
+
processed = 0
|
43
|
+
stop = proc { EM.stop if processed == 2}
|
44
|
+
|
45
|
+
pipe1.errback { failed(conn) }
|
46
|
+
pipe1.callback {
|
47
|
+
processed += 1
|
48
|
+
pipe1.response_header.status.should == 200
|
49
|
+
stop.call
|
50
|
+
}
|
51
|
+
|
52
|
+
pipe2.errback { failed(conn) }
|
53
|
+
pipe2.callback {
|
54
|
+
processed += 1
|
55
|
+
pipe2.response_header.status.should == 200
|
56
|
+
stop.call
|
57
|
+
}
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|