resourceful 0.5.4 → 0.6.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/History.txt +18 -0
- data/Manifest +11 -1
- data/README.markdown +11 -2
- data/Rakefile +38 -18
- data/lib/resourceful.rb +6 -2
- data/lib/resourceful/abstract_form_data.rb +18 -0
- data/lib/resourceful/header.rb +228 -97
- data/lib/resourceful/http_accessor.rb +32 -26
- data/lib/resourceful/multipart_form_data.rb +46 -0
- data/lib/resourceful/net_http_adapter.rb +19 -5
- data/lib/resourceful/options_interpretation.rb +72 -0
- data/lib/resourceful/request.rb +6 -2
- data/lib/resourceful/resource.rb +25 -9
- data/lib/resourceful/response.rb +5 -5
- data/lib/resourceful/urlencoded_form_data.rb +17 -0
- data/resourceful.gemspec +7 -7
- data/spec/acceptance/caching_spec.rb +6 -8
- data/spec/acceptance/header_spec.rb +1 -1
- data/spec/acceptance/resource_spec.rb +3 -3
- data/spec/caching_spec.rb +89 -0
- data/spec/resourceful/header_spec.rb +8 -0
- data/spec/resourceful/multipart_form_data_spec.rb +77 -0
- data/spec/resourceful/resource_spec.rb +20 -0
- data/spec/resourceful/urlencoded_form_data_spec.rb +44 -0
- data/spec/simple_sinatra_server.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- metadata +18 -6
- data/lib/resourceful/options_interpreter.rb +0 -78
@@ -30,9 +30,7 @@ describe Resourceful do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def uri_for_code(code, params = {})
|
33
|
-
|
34
|
-
uri = template.expand("code" => code.to_s)
|
35
|
-
|
33
|
+
uri = Addressable::Template.new("http://localhost:42682/code/{code}").expand("code" => code.to_s)
|
36
34
|
uri_plus_params(uri, params)
|
37
35
|
end
|
38
36
|
|
@@ -106,7 +104,7 @@ describe Resourceful do
|
|
106
104
|
|
107
105
|
it 'should revalidate the cached response if the response is expired' do
|
108
106
|
in_the_past = (Time.now - 60).httpdate
|
109
|
-
resource = @http.resource(uri_for_code(200, "
|
107
|
+
resource = @http.resource(uri_for_code(200, "Expires" => in_the_past))
|
110
108
|
|
111
109
|
resp = resource.get
|
112
110
|
resp.should be_expired
|
@@ -121,7 +119,7 @@ describe Resourceful do
|
|
121
119
|
|
122
120
|
it "should be authoritative if the response is directly from the server" do
|
123
121
|
resource = @http.resource(
|
124
|
-
uri_plus_params('http://localhost:
|
122
|
+
uri_plus_params('http://localhost:42682/', "Cache-Control" => 'max-age=10')
|
125
123
|
)
|
126
124
|
|
127
125
|
response = resource.get
|
@@ -131,7 +129,7 @@ describe Resourceful do
|
|
131
129
|
it "should be authoritative if a cached response was revalidated with the server" do
|
132
130
|
now = Time.now.httpdate
|
133
131
|
resource = @http.resource(
|
134
|
-
uri_plus_params('http://localhost:
|
132
|
+
uri_plus_params('http://localhost:42682/cached',
|
135
133
|
"modified" => now,
|
136
134
|
"Cache-Control" => 'max-age=0')
|
137
135
|
)
|
@@ -144,7 +142,7 @@ describe Resourceful do
|
|
144
142
|
it "should not be authoritative if the cached response was not revalidated" do
|
145
143
|
now = Time.now.httpdate
|
146
144
|
resource = @http.resource(
|
147
|
-
uri_plus_params('http://localhost:
|
145
|
+
uri_plus_params('http://localhost:42682/cached',
|
148
146
|
"modified" => now,
|
149
147
|
"Cache-Control" => 'max-age=10')
|
150
148
|
)
|
@@ -162,7 +160,7 @@ describe Resourceful do
|
|
162
160
|
now = Time.now.httpdate
|
163
161
|
|
164
162
|
resource = @http.resource(
|
165
|
-
uri_plus_params('http://localhost:
|
163
|
+
uri_plus_params('http://localhost:42682/cached',
|
166
164
|
"modified" => now,
|
167
165
|
"Cache-Control" => 'max-age=0')
|
168
166
|
)
|
@@ -6,7 +6,7 @@ describe Resourceful do
|
|
6
6
|
describe 'setting headers' do
|
7
7
|
before do
|
8
8
|
@http = Resourceful::HttpAccessor.new
|
9
|
-
@resource = @http.resource("http://localhost:
|
9
|
+
@resource = @http.resource("http://localhost:42682/header")
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'should handle "Content-Type"' do
|
@@ -7,12 +7,12 @@ describe Resourceful do
|
|
7
7
|
describe "working with a resource" do
|
8
8
|
before do
|
9
9
|
@http = Resourceful::HttpAccessor.new
|
10
|
-
@resource = @http.resource('http://localhost:
|
10
|
+
@resource = @http.resource('http://localhost:42682/')
|
11
11
|
end
|
12
12
|
|
13
13
|
it 'should make the original uri available' do
|
14
|
-
@resource.effective_uri.should == 'http://localhost:
|
15
|
-
@resource.uri.should == 'http://localhost:
|
14
|
+
@resource.effective_uri.should == 'http://localhost:42682/'
|
15
|
+
@resource.uri.should == 'http://localhost:42682/'
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'should set the user agent string on the default header' do
|
@@ -0,0 +1,89 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'fakeweb'
|
4
|
+
|
5
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), "..", "lib")
|
6
|
+
require 'resourceful'
|
7
|
+
|
8
|
+
describe "Caching" do
|
9
|
+
|
10
|
+
before do
|
11
|
+
FakeWeb.allow_net_connect = false
|
12
|
+
FakeWeb.clean_registry
|
13
|
+
|
14
|
+
@http = Resourceful::HttpAccessor.new(:cache_manager => Resourceful::InMemoryCacheManager.new)
|
15
|
+
if ENV['SPEC_LOGGING']
|
16
|
+
@http.logger = Resourceful::StdOutLogger.new
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "should cache" do
|
21
|
+
|
22
|
+
before do
|
23
|
+
FakeWeb.register_uri(:get, "http://example.com/cache",
|
24
|
+
[{:body => "Original response", :cache_control => "private,max-age=15"},
|
25
|
+
{:body => "Overrode cached response"}]
|
26
|
+
)
|
27
|
+
|
28
|
+
@resource = @http.resource("http://example.com/cache")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should cache the response" do
|
32
|
+
resp = @resource.get
|
33
|
+
resp.body.should == "Original response"
|
34
|
+
|
35
|
+
resp = @resource.get
|
36
|
+
resp.body.should == "Original response"
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "updating headers" do
|
42
|
+
before do
|
43
|
+
FakeWeb.register_uri(:get, "http://example.com/override",
|
44
|
+
[{:body => "Original response", :cache_control => "private,max-age=0", :x_updateme => "foo"},
|
45
|
+
{:body => "Overrode cached response", :status => 304, :x_updateme => "bar"} ]
|
46
|
+
)
|
47
|
+
|
48
|
+
@resource = @http.resource("http://example.com/override")
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should update headers from the 304" do
|
52
|
+
resp = @resource.get
|
53
|
+
resp.headers['X-Updateme'].should == ["foo"]
|
54
|
+
|
55
|
+
resp = @resource.get
|
56
|
+
resp.headers['X-Updateme'].should == ["bar"]
|
57
|
+
resp.headers['Cache-Control'].should == ["private,max-age=0"]
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "updating expiration" do
|
63
|
+
before do
|
64
|
+
FakeWeb.register_uri(:get, "http://example.com/timeout",
|
65
|
+
[{:body => "Original response", :cache_control => "private,max-age=1"},
|
66
|
+
{:body => "cached response", :cache_control => "private,max-age=1"}]
|
67
|
+
)
|
68
|
+
|
69
|
+
@resource = @http.resource("http://example.com/timeout")
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should refresh the expiration timer" do
|
73
|
+
resp = @resource.get
|
74
|
+
resp.should_not be_stale
|
75
|
+
|
76
|
+
sleep 2
|
77
|
+
|
78
|
+
resp.should be_stale
|
79
|
+
|
80
|
+
resp = @resource.get
|
81
|
+
resp.should_not be_stale
|
82
|
+
|
83
|
+
resp = @resource.get
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../spec_helper"
|
2
|
+
require 'tempfile'
|
3
|
+
require "resourceful/multipart_form_data.rb"
|
4
|
+
|
5
|
+
describe Resourceful::MultipartFormData do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@form_data = Resourceful::MultipartFormData.new
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should know its content-type" do
|
12
|
+
@form_data.content_type.should match(/^multipart\/form-data/i)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should know its boundary string" do
|
16
|
+
@form_data.content_type.should match(/; boundary=[0-9A-Za-z]{10,}/i)
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
describe "with simple parameters" do
|
21
|
+
|
22
|
+
it "should all simple parameters to be added" do
|
23
|
+
@form_data.add(:foo, "testing")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should render a multipart form-data document when #read is called" do
|
27
|
+
@form_data.add('foo', 'bar')
|
28
|
+
@form_data.add('baz', 'this')
|
29
|
+
|
30
|
+
boundary = /boundary=(\w+)/.match(@form_data.content_type)[1]
|
31
|
+
@form_data.read.should eql(<<MPFD[0..-2])
|
32
|
+
--#{boundary}\r
|
33
|
+
Content-Disposition: form-data; name="foo"\r
|
34
|
+
\r
|
35
|
+
bar\r
|
36
|
+
--#{boundary}\r
|
37
|
+
Content-Disposition: form-data; name="baz"\r
|
38
|
+
\r
|
39
|
+
this\r
|
40
|
+
--#{boundary}--
|
41
|
+
MPFD
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "with file parameter" do
|
46
|
+
it "should add file parameters to be added" do
|
47
|
+
Tempfile.open('resourceful-post-file-tests') do |file_to_upload|
|
48
|
+
file_to_upload << "This is a test"
|
49
|
+
file_to_upload.flush
|
50
|
+
|
51
|
+
@form_data.add_file(:foo, file_to_upload.path)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should render a multipart form-data document when #read is called" do
|
56
|
+
Tempfile.open('resourceful-post-file-tests') do |file_to_upload|
|
57
|
+
file_to_upload << "This is a test"
|
58
|
+
file_to_upload.flush
|
59
|
+
|
60
|
+
@form_data.add_file(:foo, file_to_upload.path)
|
61
|
+
|
62
|
+
boundary = /boundary=(\w+)/.match(@form_data.content_type)[1]
|
63
|
+
@form_data.read.should eql(<<MPFD[0..-2])
|
64
|
+
--#{boundary}\r
|
65
|
+
Content-Disposition: form-data; name="foo"; filename="#{File.basename(file_to_upload.path)}"\r
|
66
|
+
Content-Type: application/octet-stream\r
|
67
|
+
\r
|
68
|
+
This is a test\r
|
69
|
+
--#{boundary}--
|
70
|
+
MPFD
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../spec_helper"
|
2
|
+
|
3
|
+
module Resourceful
|
4
|
+
describe Resource do
|
5
|
+
before do
|
6
|
+
@http_adapter = stub(:http_adapter)
|
7
|
+
http = Resourceful::HttpAccessor.new(:http_adapter => @http_adapter)
|
8
|
+
@resource = http.resource('http://foo.example')
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "POSTing" do
|
12
|
+
it "should use bodies content type as the request content-type if it is known" do
|
13
|
+
@http_adapter.should_receive(:make_request).with(anything, anything, anything, hash_including('Content-Type' => 'application/x-special-type')).and_return([200, {}, ""])
|
14
|
+
body = stub(:body, :content_type => 'application/x-special-type', :read => "hello there")
|
15
|
+
@resource.post(body)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../spec_helper"
|
2
|
+
require 'tempfile'
|
3
|
+
require "resourceful/urlencoded_form_data.rb"
|
4
|
+
|
5
|
+
describe Resourceful::UrlencodedFormData do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@form_data = Resourceful::UrlencodedFormData.new
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should know its content-type" do
|
12
|
+
@form_data.content_type.should match(/^application\/x-www-form-urlencoded$/i)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "instantiation" do
|
16
|
+
it "should be creatable with hash" do
|
17
|
+
Resourceful::UrlencodedFormData.new(:foo => 'testing').read.should eql("foo=testing")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "with simple parameters" do
|
22
|
+
it "should all simple parameters to be added" do
|
23
|
+
@form_data.add(:foo, "testing")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should render a multipart form-data document when #read is called" do
|
27
|
+
@form_data.add('foo', 'bar')
|
28
|
+
@form_data.add('baz', 'this')
|
29
|
+
|
30
|
+
@form_data.read.should eql("foo=bar&baz=this")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should escape character in values that are unsafe" do
|
34
|
+
@form_data.add('foo', 'this & that')
|
35
|
+
|
36
|
+
@form_data.read.should eql("foo=this+%26+that")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should escape character in names that are unsafe" do
|
40
|
+
@form_data.add('foo=bar', 'this')
|
41
|
+
@form_data.read.should eql("foo%3Dbar=this")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resourceful
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Sadauskas
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-08-
|
12
|
+
date: 2009-08-14 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version:
|
23
|
+
version: 2.1.0
|
24
24
|
version:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: httpauth
|
@@ -81,34 +81,42 @@ extensions: []
|
|
81
81
|
extra_rdoc_files:
|
82
82
|
- lib/resourceful.rb
|
83
83
|
- lib/resourceful/net_http_adapter.rb
|
84
|
+
- lib/resourceful/options_interpretation.rb
|
84
85
|
- lib/resourceful/stubbed_resource_proxy.rb
|
86
|
+
- lib/resourceful/urlencoded_form_data.rb
|
85
87
|
- lib/resourceful/header.rb
|
86
88
|
- lib/resourceful/memcache_cache_manager.rb
|
87
89
|
- lib/resourceful/response.rb
|
88
90
|
- lib/resourceful/util.rb
|
89
|
-
- lib/resourceful/
|
91
|
+
- lib/resourceful/abstract_form_data.rb
|
90
92
|
- lib/resourceful/cache_manager.rb
|
91
93
|
- lib/resourceful/request.rb
|
92
94
|
- lib/resourceful/resource.rb
|
93
95
|
- lib/resourceful/exceptions.rb
|
96
|
+
- lib/resourceful/multipart_form_data.rb
|
94
97
|
- lib/resourceful/http_accessor.rb
|
95
98
|
- lib/resourceful/authentication_manager.rb
|
96
99
|
- README.markdown
|
97
100
|
files:
|
98
101
|
- lib/resourceful.rb
|
99
102
|
- lib/resourceful/net_http_adapter.rb
|
103
|
+
- lib/resourceful/options_interpretation.rb
|
100
104
|
- lib/resourceful/stubbed_resource_proxy.rb
|
105
|
+
- lib/resourceful/urlencoded_form_data.rb
|
101
106
|
- lib/resourceful/header.rb
|
102
107
|
- lib/resourceful/memcache_cache_manager.rb
|
103
108
|
- lib/resourceful/response.rb
|
104
109
|
- lib/resourceful/util.rb
|
105
|
-
- lib/resourceful/
|
110
|
+
- lib/resourceful/abstract_form_data.rb
|
106
111
|
- lib/resourceful/cache_manager.rb
|
107
112
|
- lib/resourceful/request.rb
|
108
113
|
- lib/resourceful/resource.rb
|
109
114
|
- lib/resourceful/exceptions.rb
|
115
|
+
- lib/resourceful/multipart_form_data.rb
|
110
116
|
- lib/resourceful/http_accessor.rb
|
111
117
|
- lib/resourceful/authentication_manager.rb
|
118
|
+
- History.txt
|
119
|
+
- resourceful.gemspec
|
112
120
|
- README.markdown
|
113
121
|
- MIT-LICENSE
|
114
122
|
- Rakefile
|
@@ -123,8 +131,12 @@ files:
|
|
123
131
|
- spec/acceptance/resource_spec.rb
|
124
132
|
- spec/acceptance/caching_spec.rb
|
125
133
|
- spec/acceptance/redirecting_spec.rb
|
134
|
+
- spec/resourceful/multipart_form_data_spec.rb
|
135
|
+
- spec/resourceful/header_spec.rb
|
136
|
+
- spec/resourceful/resource_spec.rb
|
137
|
+
- spec/resourceful/urlencoded_form_data_spec.rb
|
138
|
+
- spec/caching_spec.rb
|
126
139
|
- spec/spec.opts
|
127
|
-
- resourceful.gemspec
|
128
140
|
has_rdoc: true
|
129
141
|
homepage: http://github.com/paul/resourceful
|
130
142
|
licenses: []
|
@@ -1,78 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
|
-
module Resourceful
|
4
|
-
# Class that supports a declarative way to pick apart an options
|
5
|
-
# hash.
|
6
|
-
#
|
7
|
-
# OptionsInterpreter.new do
|
8
|
-
# option(:accept) { |accept| [accept].flatten.map{|m| m.to_str} }
|
9
|
-
# option(:http_header_fields, :default => {})
|
10
|
-
# end.interpret(:accept => 'this/that')
|
11
|
-
# # => {:accept => ['this/that'], :http_header_fields => { } }
|
12
|
-
#
|
13
|
-
# The returned hash contains :accept with the pass accept option
|
14
|
-
# value transformed into an array and :http_header_fields with its
|
15
|
-
# default value.
|
16
|
-
#
|
17
|
-
# OptionsInterpreter.new do
|
18
|
-
# option(:max_redirects)
|
19
|
-
# end.interpret(:foo => 1, :bar => 2)
|
20
|
-
# # Raises ArgumentError: Unrecognized options: foo, bar
|
21
|
-
#
|
22
|
-
# If options are passed that are not defined an exception is raised.
|
23
|
-
#
|
24
|
-
class OptionsInterpreter
|
25
|
-
def self.interpret(options_hash, &block)
|
26
|
-
interpreter = self.new(options_hash)
|
27
|
-
interpreter.instance_eval(&block)
|
28
|
-
|
29
|
-
interpreter.interpret
|
30
|
-
end
|
31
|
-
|
32
|
-
def initialize(&block)
|
33
|
-
@handlers = Hash.new
|
34
|
-
|
35
|
-
instance_eval(&block) if block_given?
|
36
|
-
end
|
37
|
-
|
38
|
-
def interpret(options_hash, &block)
|
39
|
-
unless (unrecognized_options = (options_hash.keys - supported_options)).empty?
|
40
|
-
raise ArgumentError, "Unrecognized options: #{unrecognized_options.join(", ")}"
|
41
|
-
end
|
42
|
-
|
43
|
-
options = Hash.new
|
44
|
-
handlers.each do |opt_name, a_handler|
|
45
|
-
opt_val = a_handler.call(options_hash)
|
46
|
-
options[opt_name] = opt_val if opt_val
|
47
|
-
end
|
48
|
-
|
49
|
-
yield(options) if block_given?
|
50
|
-
|
51
|
-
options
|
52
|
-
end
|
53
|
-
|
54
|
-
def option(name, opts = {}, &block)
|
55
|
-
|
56
|
-
passed_value_fetcher = if opts[:default]
|
57
|
-
default_value = opts[:default]
|
58
|
-
lambda{|options_hash| options_hash[name] || default_value}
|
59
|
-
else
|
60
|
-
lambda{|options_hash| options_hash[name]}
|
61
|
-
end
|
62
|
-
|
63
|
-
handlers[name] = if block_given?
|
64
|
-
lambda{|options_hash| (val = passed_value_fetcher.call(options_hash)) ? block.call(val) : nil}
|
65
|
-
else
|
66
|
-
passed_value_fetcher
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def supported_options
|
71
|
-
handlers.keys
|
72
|
-
end
|
73
|
-
|
74
|
-
private
|
75
|
-
|
76
|
-
attr_reader :handlers
|
77
|
-
end
|
78
|
-
end
|