rack-client 0.1.1 → 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.
Files changed (76) hide show
  1. data/History.txt +2 -2
  2. data/README.textile +2 -2
  3. data/Rakefile +11 -5
  4. data/demo/demo_spec.rb +3 -3
  5. data/lib/rack/client.rb +29 -25
  6. data/lib/rack/client/adapter.rb +6 -0
  7. data/lib/rack/client/adapter/base.rb +57 -0
  8. data/lib/rack/client/adapter/simple.rb +49 -0
  9. data/lib/rack/client/auth/abstract/challenge.rb +53 -0
  10. data/lib/rack/client/auth/basic.rb +57 -0
  11. data/lib/rack/client/auth/digest/challenge.rb +38 -0
  12. data/lib/rack/client/auth/digest/md5.rb +78 -0
  13. data/lib/rack/client/auth/digest/params.rb +10 -0
  14. data/lib/rack/client/body.rb +12 -0
  15. data/lib/rack/client/cache.rb +19 -0
  16. data/lib/rack/client/cache/cachecontrol.rb +195 -0
  17. data/lib/rack/client/cache/context.rb +95 -0
  18. data/lib/rack/client/cache/entitystore.rb +77 -0
  19. data/lib/rack/client/cache/key.rb +51 -0
  20. data/lib/rack/client/cache/metastore.rb +133 -0
  21. data/lib/rack/client/cache/options.rb +147 -0
  22. data/lib/rack/client/cache/request.rb +46 -0
  23. data/lib/rack/client/cache/response.rb +62 -0
  24. data/lib/rack/client/cache/storage.rb +43 -0
  25. data/lib/rack/client/cookie_jar.rb +17 -0
  26. data/lib/rack/client/cookie_jar/context.rb +59 -0
  27. data/lib/rack/client/cookie_jar/cookie.rb +59 -0
  28. data/lib/rack/client/cookie_jar/cookiestore.rb +36 -0
  29. data/lib/rack/client/cookie_jar/options.rb +43 -0
  30. data/lib/rack/client/cookie_jar/request.rb +15 -0
  31. data/lib/rack/client/cookie_jar/response.rb +16 -0
  32. data/lib/rack/client/cookie_jar/storage.rb +34 -0
  33. data/lib/rack/client/dual_band.rb +13 -0
  34. data/lib/rack/client/follow_redirects.rb +47 -20
  35. data/lib/rack/client/handler.rb +10 -0
  36. data/lib/rack/client/handler/em-http.rb +66 -0
  37. data/lib/rack/client/handler/excon.rb +50 -0
  38. data/lib/rack/client/handler/net_http.rb +85 -0
  39. data/lib/rack/client/handler/typhoeus.rb +62 -0
  40. data/lib/rack/client/headers.rb +49 -0
  41. data/lib/rack/client/parser.rb +18 -0
  42. data/lib/rack/client/parser/base.rb +25 -0
  43. data/lib/rack/client/parser/body_collection.rb +50 -0
  44. data/lib/rack/client/parser/context.rb +15 -0
  45. data/lib/rack/client/parser/json.rb +54 -0
  46. data/lib/rack/client/parser/middleware.rb +8 -0
  47. data/lib/rack/client/parser/request.rb +21 -0
  48. data/lib/rack/client/parser/response.rb +19 -0
  49. data/lib/rack/client/parser/yaml.rb +52 -0
  50. data/lib/rack/client/response.rb +9 -0
  51. data/lib/rack/client/version.rb +5 -0
  52. data/spec/apps/example.org.ru +47 -3
  53. data/spec/auth/basic_spec.rb +69 -0
  54. data/spec/auth/digest/md5_spec.rb +69 -0
  55. data/spec/cache_spec.rb +40 -0
  56. data/spec/cookie_jar_spec.rb +37 -0
  57. data/spec/endpoint_spec.rb +4 -13
  58. data/spec/follow_redirect_spec.rb +27 -0
  59. data/spec/handler/async_api_spec.rb +69 -0
  60. data/spec/handler/em_http_spec.rb +22 -0
  61. data/spec/handler/excon_spec.rb +7 -0
  62. data/spec/handler/net_http_spec.rb +8 -0
  63. data/spec/handler/sync_api_spec.rb +55 -0
  64. data/spec/handler/typhoeus_spec.rb +22 -0
  65. data/spec/middleware_helper.rb +37 -0
  66. data/spec/middleware_spec.rb +48 -5
  67. data/spec/parser/json_spec.rb +22 -0
  68. data/spec/parser/yaml_spec.rb +22 -0
  69. data/spec/server_helper.rb +72 -0
  70. data/spec/spec_helper.rb +17 -3
  71. metadata +86 -31
  72. data/lib/rack/client/auth.rb +0 -13
  73. data/lib/rack/client/http.rb +0 -77
  74. data/spec/auth_spec.rb +0 -22
  75. data/spec/core_spec.rb +0 -123
  76. data/spec/redirect_spec.rb +0 -12
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ if ''.respond_to?(:bytesize) || # String#bytesize defined by em-http-request > 0.2.7
4
+ RUBY_VERSION != '1.8.7' # em-spec is broken on 1.8.7
5
+
6
+ describe Rack::Client::Handler::EmHttp do
7
+ include EM::Spec
8
+
9
+ def client
10
+ Rack::Client.new { run Rack::Client::Handler::EmHttp.new("http://localhost:#{server.port}") }
11
+ end
12
+
13
+ def finish
14
+ done
15
+ end
16
+
17
+ before(:each) { done }
18
+ after(:each) { done }
19
+
20
+ it_should_behave_like "Asynchronous Request API"
21
+ end
22
+ end
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Rack::Client::Handler::Excon do
4
+ let(:client) { Rack::Client.new { run Rack::Client::Handler::Excon.new("http://localhost:#{server.port}") } }
5
+
6
+ it_should_behave_like "Synchronous Request API"
7
+ end
@@ -0,0 +1,8 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Rack::Client::Handler::NetHTTP do
4
+ let(:client) { Rack::Client.new("http://localhost:#{server.port}") { run Rack::Client::Handler::NetHTTP } }
5
+
6
+ it_should_behave_like "Synchronous Request API"
7
+ it_should_behave_like "Asynchronous Request API"
8
+ end
@@ -0,0 +1,55 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ share_examples_for "Synchronous Request API" do
4
+ context 'DELETE request' do
5
+ it 'can handle a No Content response' do
6
+ response = client.delete("/shelf/ctm")
7
+ response.status.should == 204
8
+ end
9
+ end
10
+
11
+ context 'GET request' do
12
+ it 'has the proper response for a basic request' do
13
+ response = client.get("/ping")
14
+ response.status.should == 200
15
+ response.body.to_s.should == 'pong'
16
+ response["Content-Type"].should == 'text/html'
17
+ response["Content-Length"].to_i.should == 4
18
+ end
19
+
20
+ it 'can handle a temporary redirect response' do
21
+ response = client.get("/redirect")
22
+ response.status.should == 302
23
+ response["Location"].should == "/after-redirect"
24
+ end
25
+
26
+ it 'can return an empty body' do
27
+ response = client.get("/empty")
28
+ response.body.should be_empty
29
+ end
30
+ end
31
+
32
+ context 'HEAD request' do
33
+ it 'can handle ETag headers' do
34
+ response = client.head("/shelf")
35
+ response.status.should == 200
36
+ response["ETag"].should == "828ef3fdfa96f00ad9f27c383fc9ac7f"
37
+ end
38
+ end
39
+
40
+ context 'POST request' do
41
+ it 'can send a request body' do
42
+ response = client.post("/posted", {}, "some data")
43
+ response.status.should == 201
44
+ response["Created"].should == "awesome"
45
+ end
46
+ end
47
+
48
+ context 'PUT request' do
49
+ it 'can send a request body' do
50
+ response = client.put("/shelf/ctm", {}, "some data")
51
+ response.status.should == 200
52
+ response["Location"].should == "/shelf/ctm"
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Rack::Client::Handler::Excon do
4
+
5
+ def client
6
+ Rack::Client::Handler::Typhoeus # manual autoload :(
7
+
8
+ hydra = self.hydra
9
+ Rack::Client.new { run Rack::Client::Handler::Typhoeus.new("http://localhost:#{server.port}", hydra) }
10
+ end
11
+
12
+ def hydra
13
+ @@hydra ||= Typhoeus::Hydra.new
14
+ end
15
+
16
+ def finish
17
+ hydra.run
18
+ end
19
+
20
+ it_should_behave_like "Synchronous Request API"
21
+ it_should_behave_like "Asynchronous Request API"
22
+ end
@@ -0,0 +1,37 @@
1
+ class LoggerCheck
2
+ def initialize(app, &block)
3
+ @app, @block = app, block
4
+ end
5
+
6
+ def call(env)
7
+ logger = env['rack.logger']
8
+
9
+ @app.call(env)
10
+ ensure
11
+ @block.call(logger)
12
+ end
13
+ end
14
+
15
+ class ETagFixed < Rack::ETag
16
+ def call(env)
17
+ status, headers, body = @app.call(env)
18
+
19
+ if !headers.has_key?('ETag')
20
+ digest, body = digest_body(body)
21
+ headers['ETag'] = %("#{digest}")
22
+ end
23
+
24
+ [status, headers, body]
25
+ end
26
+
27
+ private
28
+ def digest_body(body)
29
+ digest = Digest::MD5.new
30
+ parts = []
31
+ body.each do |part|
32
+ digest << part
33
+ parts << part
34
+ end
35
+ [digest.hexdigest, parts]
36
+ end
37
+ end
@@ -1,10 +1,53 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
3
  describe Rack::Client, "with a standard piece of Rack middleware" do
4
- it "successfully uses that middleware" do
5
- client = Rack::Client.new { use Rack::ETag }
6
- response = client.get("http://localhost:9292/no-etag")
7
- response.status.should == 200
8
- response.headers["ETag"].should_not be_empty
4
+ context "Rack::ETag" do
5
+ let(:client) do
6
+ Rack::Client.new("http://localhost:#{server.port}") do
7
+ use Rack::ETag
8
+ run Rack::Client::Handler::NetHTTP
9
+ end
10
+ end
11
+
12
+ it "successfully uses that middleware" do
13
+ pending "Rack::ETag fixes streaming bodies (http://github.com/rack/rack/commit/f10713cce876d370ee5f1018928521d4b43e0dce)"
14
+
15
+ response = client.get("http://localhost:#{server.port}/no-etag")
16
+ response.status.should == 200
17
+ response.headers["ETag"].should_not be_empty
18
+ end
19
+ end
20
+
21
+ context "Rack::ETag (fixed for streaming)" do
22
+ let(:client) do
23
+ Rack::Client.new("http://localhost:#{server.port}") do
24
+ use ETagFixed
25
+ run Rack::Client::Handler::NetHTTP
26
+ end
27
+ end
28
+
29
+ it "successfully uses that middleware" do
30
+ response = client.get("http://localhost:#{server.port}/no-etag")
31
+ response.status.should == 200
32
+ response.headers["ETag"].should_not be_empty
33
+ end
34
+ end
35
+
36
+ context "Rack::Logger" do
37
+ let(:client) do
38
+ Rack::Client.new("http://localhost:#{server.port}") do
39
+ use Rack::Logger
40
+ use LoggerCheck do |logger|
41
+ logger.class.should == Logger
42
+ end
43
+ run Rack::Client::Handler::NetHTTP
44
+ end
45
+ end
46
+
47
+ it "successfully uses that middleware" do
48
+ response = client.get("http://localhost:#{server.port}/no-etag")
49
+ response.status.should == 200
50
+ end
9
51
  end
10
52
  end
53
+
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Rack::Client::Parser::JSON do
4
+ let(:client) do
5
+ Rack::Client.new("http://localhost:#{server.port}") do
6
+ use Rack::Client::Parser
7
+ run Rack::Client::Handler::NetHTTP
8
+ end
9
+ end
10
+
11
+ context 'Synchronous API' do
12
+ it "injects the parsed body into the response" do
13
+ response = client.get("http://localhost:#{server.port}/hash.json")
14
+ response.headers['rack-client.body_collection'].should == [{'foo' => 'bar'}]
15
+ end
16
+
17
+ it "injects the dumped body into the request" do
18
+ response = client.post("http://localhost:#{server.port}/echo", {'rack-client.body_collection' => [{'foo' => 'bar'}], 'Content-Type' => 'application/json'}, {})
19
+ response.headers['rack-client.body_collection'].should == [{'foo' => 'bar'}]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Rack::Client::Parser::YAML do
4
+ let(:client) do
5
+ Rack::Client.new("http://localhost:#{server.port}") do
6
+ use Rack::Client::Parser
7
+ run Rack::Client::Handler::NetHTTP
8
+ end
9
+ end
10
+
11
+ context 'Synchronous API' do
12
+ it "injects the parsed body into the response" do
13
+ response = client.get("http://localhost:#{server.port}/hash.yml")
14
+ response.headers['rack-client.body_collection'].should == [{:foo => :bar}]
15
+ end
16
+
17
+ it "injects the dumped body into the request" do
18
+ response = client.post("http://localhost:#{server.port}/echo", {'rack-client.body_collection' => [{:foo => :bar}], 'Content-Type' => 'application/x-yaml'}, {})
19
+ response.headers['rack-client.body_collection'].should == [{:foo => :bar}]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,72 @@
1
+ class InThreadServer
2
+ def self.rackup(*a)
3
+ server = new(*a)
4
+ server.start
5
+ server
6
+ end
7
+
8
+ attr_accessor :port, :port_range, :pre_spawn_callback, :config_ru, :running
9
+
10
+ def initialize(config_ru, pre_spawn_callback = nil, port_range = 8000..10000)
11
+ @config_ru, @pre_spawn_callback, @port_range = config_ru, pre_spawn_callback, port_range
12
+ end
13
+
14
+ def start
15
+ return if running
16
+ find_port
17
+ pre_spawn
18
+ spawn_server_thread
19
+ wait_for_server
20
+ @running = true
21
+ end
22
+
23
+ def stop
24
+ @thread.kill
25
+ @running= false
26
+ end
27
+
28
+ def find_port
29
+ return if @port
30
+
31
+ @port = @port_range.min
32
+
33
+ while(system("lsof -i tcp:#{self.port} > /dev/null")) do
34
+ @port += 1
35
+ end
36
+ end
37
+
38
+ def pre_spawn
39
+ pre_spawn_callback.call(self) if pre_spawn_callback
40
+ end
41
+
42
+ def spawn_server_thread
43
+ @thread ||= Thread.new {
44
+ begin
45
+ Rack::Server.new(:Port => @port, :config => @config_ru, :server => 'mongrel').start
46
+ rescue
47
+ $stderr.puts "Failed to start server"
48
+ $stderr.puts $!.inspect
49
+ $stderr.puts $!.backtrace
50
+ abort
51
+ end
52
+ }
53
+ end
54
+
55
+ def wait_for_server
56
+ loop do
57
+ begin
58
+ Rack::Client.get("http://127.0.0.1:#{@port}/")
59
+ break
60
+ rescue Errno::ECONNREFUSED
61
+ sleep 1
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ class DigestServer < Rack::Auth::Digest::MD5
68
+ def initialize(*)
69
+ super
70
+ self.opaque = '12345'
71
+ end
72
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,20 @@
1
+ $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+ require 'rack/client'
3
+
1
4
  require 'rubygems'
2
5
  require 'spec'
3
- require 'rack/contrib'
4
- gem 'rack-test'
6
+ require 'em-spec/rspec'
7
+
8
+ dir = File.expand_path(File.dirname(__FILE__))
9
+ require dir + '/server_helper'
10
+ require dir + '/middleware_helper'
11
+ require dir + '/handler/sync_api_spec'
12
+ require dir + '/handler/async_api_spec'
13
+
14
+ Spec::Runner.configure do |config|
15
+ def server
16
+ @@server ||= InThreadServer.rackup(File.expand_path(File.dirname(__FILE__) + '/apps/example.org.ru'))
17
+ end
5
18
 
6
- require File.expand_path(File.dirname(__FILE__) + "/../lib/rack/client")
19
+ def finish() end
20
+ end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 3
8
+ - 0
9
+ version: 0.3.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - Tim Carey-Smith
@@ -9,29 +14,23 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2009-07-31 00:00:00 -07:00
17
+ date: 2010-06-24 00:00:00 -07:00
13
18
  default_executable:
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
- name: rack
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
21
+ version_requirements: &id001 !ruby/object:Gem::Requirement
20
22
  requirements:
21
- - - ~>
23
+ - - ">="
22
24
  - !ruby/object:Gem::Version
23
- version: "1"
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: rack-test
25
+ segments:
26
+ - 1
27
+ - 0
28
+ - 0
29
+ version: 1.0.0
30
+ requirement: *id001
31
+ prerelease: false
27
32
  type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ~>
32
- - !ruby/object:Gem::Version
33
- version: "0"
34
- version:
33
+ name: rack
35
34
  description: A client wrapper around a Rack app or HTTP
36
35
  email: tim@spork.in
37
36
  executables: []
@@ -45,18 +44,61 @@ files:
45
44
  - LICENSE
46
45
  - README.textile
47
46
  - Rakefile
48
- - lib/rack
49
- - lib/rack/client
50
- - lib/rack/client/auth.rb
47
+ - lib/rack/client/adapter/base.rb
48
+ - lib/rack/client/adapter/simple.rb
49
+ - lib/rack/client/adapter.rb
50
+ - lib/rack/client/auth/abstract/challenge.rb
51
+ - lib/rack/client/auth/basic.rb
52
+ - lib/rack/client/auth/digest/challenge.rb
53
+ - lib/rack/client/auth/digest/md5.rb
54
+ - lib/rack/client/auth/digest/params.rb
55
+ - lib/rack/client/body.rb
56
+ - lib/rack/client/cache/cachecontrol.rb
57
+ - lib/rack/client/cache/context.rb
58
+ - lib/rack/client/cache/entitystore.rb
59
+ - lib/rack/client/cache/key.rb
60
+ - lib/rack/client/cache/metastore.rb
61
+ - lib/rack/client/cache/options.rb
62
+ - lib/rack/client/cache/request.rb
63
+ - lib/rack/client/cache/response.rb
64
+ - lib/rack/client/cache/storage.rb
65
+ - lib/rack/client/cache.rb
66
+ - lib/rack/client/cookie_jar/context.rb
67
+ - lib/rack/client/cookie_jar/cookie.rb
68
+ - lib/rack/client/cookie_jar/cookiestore.rb
69
+ - lib/rack/client/cookie_jar/options.rb
70
+ - lib/rack/client/cookie_jar/request.rb
71
+ - lib/rack/client/cookie_jar/response.rb
72
+ - lib/rack/client/cookie_jar/storage.rb
73
+ - lib/rack/client/cookie_jar.rb
74
+ - lib/rack/client/dual_band.rb
51
75
  - lib/rack/client/follow_redirects.rb
52
- - lib/rack/client/http.rb
76
+ - lib/rack/client/handler/em-http.rb
77
+ - lib/rack/client/handler/excon.rb
78
+ - lib/rack/client/handler/net_http.rb
79
+ - lib/rack/client/handler/typhoeus.rb
80
+ - lib/rack/client/handler.rb
81
+ - lib/rack/client/headers.rb
82
+ - lib/rack/client/parser/base.rb
83
+ - lib/rack/client/parser/body_collection.rb
84
+ - lib/rack/client/parser/context.rb
85
+ - lib/rack/client/parser/json.rb
86
+ - lib/rack/client/parser/middleware.rb
87
+ - lib/rack/client/parser/request.rb
88
+ - lib/rack/client/parser/response.rb
89
+ - lib/rack/client/parser/yaml.rb
90
+ - lib/rack/client/parser.rb
91
+ - lib/rack/client/response.rb
92
+ - lib/rack/client/version.rb
53
93
  - lib/rack/client.rb
54
94
  - demo/client.rb
55
95
  - demo/config.ru
56
96
  - demo/demo.rb
57
97
  - demo/demo_spec.rb
58
- has_rdoc: false
98
+ has_rdoc: true
59
99
  homepage: http://github.com/halorgium/rack-client
100
+ licenses: []
101
+
60
102
  post_install_message:
61
103
  rdoc_options: []
62
104
 
@@ -66,27 +108,40 @@ required_ruby_version: !ruby/object:Gem::Requirement
66
108
  requirements:
67
109
  - - ">="
68
110
  - !ruby/object:Gem::Version
111
+ segments:
112
+ - 0
69
113
  version: "0"
70
- version:
71
114
  required_rubygems_version: !ruby/object:Gem::Requirement
72
115
  requirements:
73
116
  - - ">="
74
117
  - !ruby/object:Gem::Version
118
+ segments:
119
+ - 0
75
120
  version: "0"
76
- version:
77
121
  requirements: []
78
122
 
79
123
  rubyforge_project: rack-client
80
- rubygems_version: 1.3.1
124
+ rubygems_version: 1.3.6
81
125
  signing_key:
82
- specification_version: 2
126
+ specification_version: 3
83
127
  summary: A client wrapper around a Rack app or HTTP
84
128
  test_files:
85
- - spec/apps
86
129
  - spec/apps/example.org.ru
87
- - spec/auth_spec.rb
88
- - spec/core_spec.rb
130
+ - spec/auth/basic_spec.rb
131
+ - spec/auth/digest/md5_spec.rb
132
+ - spec/cache_spec.rb
133
+ - spec/cookie_jar_spec.rb
89
134
  - spec/endpoint_spec.rb
135
+ - spec/follow_redirect_spec.rb
136
+ - spec/handler/async_api_spec.rb
137
+ - spec/handler/em_http_spec.rb
138
+ - spec/handler/excon_spec.rb
139
+ - spec/handler/net_http_spec.rb
140
+ - spec/handler/sync_api_spec.rb
141
+ - spec/handler/typhoeus_spec.rb
142
+ - spec/middleware_helper.rb
90
143
  - spec/middleware_spec.rb
91
- - spec/redirect_spec.rb
144
+ - spec/parser/json_spec.rb
145
+ - spec/parser/yaml_spec.rb
146
+ - spec/server_helper.rb
92
147
  - spec/spec_helper.rb