ably-em-http-request 1.1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/.github/workflows/ci.yml +22 -0
  4. data/.gitignore +9 -0
  5. data/.rspec +0 -0
  6. data/Changelog.md +78 -0
  7. data/Gemfile +14 -0
  8. data/LICENSE +21 -0
  9. data/README.md +66 -0
  10. data/Rakefile +10 -0
  11. data/ably-em-http-request.gemspec +33 -0
  12. data/benchmarks/clients.rb +170 -0
  13. data/benchmarks/em-excon.rb +87 -0
  14. data/benchmarks/em-profile.gif +0 -0
  15. data/benchmarks/em-profile.txt +65 -0
  16. data/benchmarks/server.rb +48 -0
  17. data/examples/.gitignore +1 -0
  18. data/examples/digest_auth/client.rb +25 -0
  19. data/examples/digest_auth/server.rb +28 -0
  20. data/examples/fetch.rb +30 -0
  21. data/examples/fibered-http.rb +51 -0
  22. data/examples/multi.rb +25 -0
  23. data/examples/oauth-tweet.rb +35 -0
  24. data/examples/socks5.rb +23 -0
  25. data/lib/em/io_streamer.rb +51 -0
  26. data/lib/em-http/client.rb +343 -0
  27. data/lib/em-http/core_ext/bytesize.rb +6 -0
  28. data/lib/em-http/decoders.rb +252 -0
  29. data/lib/em-http/http_client_options.rb +51 -0
  30. data/lib/em-http/http_connection.rb +408 -0
  31. data/lib/em-http/http_connection_options.rb +72 -0
  32. data/lib/em-http/http_encoding.rb +151 -0
  33. data/lib/em-http/http_header.rb +85 -0
  34. data/lib/em-http/http_status_codes.rb +59 -0
  35. data/lib/em-http/middleware/digest_auth.rb +114 -0
  36. data/lib/em-http/middleware/json_response.rb +17 -0
  37. data/lib/em-http/middleware/oauth.rb +42 -0
  38. data/lib/em-http/middleware/oauth2.rb +30 -0
  39. data/lib/em-http/multi.rb +59 -0
  40. data/lib/em-http/request.rb +25 -0
  41. data/lib/em-http/version.rb +7 -0
  42. data/lib/em-http-request.rb +1 -0
  43. data/lib/em-http.rb +20 -0
  44. data/spec/client_fiber_spec.rb +23 -0
  45. data/spec/client_spec.rb +1000 -0
  46. data/spec/digest_auth_spec.rb +48 -0
  47. data/spec/dns_spec.rb +41 -0
  48. data/spec/encoding_spec.rb +49 -0
  49. data/spec/external_spec.rb +146 -0
  50. data/spec/fixtures/google.ca +16 -0
  51. data/spec/fixtures/gzip-sample.gz +0 -0
  52. data/spec/gzip_spec.rb +91 -0
  53. data/spec/helper.rb +27 -0
  54. data/spec/http_proxy_spec.rb +268 -0
  55. data/spec/middleware/oauth2_spec.rb +15 -0
  56. data/spec/middleware_spec.rb +143 -0
  57. data/spec/multi_spec.rb +104 -0
  58. data/spec/pipelining_spec.rb +62 -0
  59. data/spec/redirect_spec.rb +430 -0
  60. data/spec/socksify_proxy_spec.rb +56 -0
  61. data/spec/spec_helper.rb +25 -0
  62. data/spec/ssl_spec.rb +67 -0
  63. data/spec/stallion.rb +334 -0
  64. data/spec/stub_server.rb +45 -0
  65. 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
@@ -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