paul-resourceful 0.2.3 → 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.
- data/README.markdown +3 -5
- data/Rakefile +37 -10
- data/lib/resourceful/cache_manager.rb +113 -104
- data/lib/resourceful/http_accessor.rb +16 -1
- data/lib/resourceful/memcache_cache_manager.rb +85 -0
- data/lib/resourceful/request.rb +6 -0
- data/lib/resourceful.rb +0 -1
- data/resourceful.gemspec +33 -11
- data/spec/resourceful/cache_manager_spec.rb +79 -67
- data/spec/resourceful/http_accessor_spec.rb +46 -7
- data/spec/resourceful/memcache_cache_manager_spec.rb +111 -0
- data/spec/resourceful/options_interpreter_spec.rb +9 -1
- data/spec/simple_http_server_shared_spec.rb +4 -2
- metadata +103 -34
- data/Manifest.txt +0 -34
- data/lib/resourceful/version.rb +0 -1
data/README.markdown
CHANGED
@@ -37,8 +37,8 @@ Simplest example
|
|
37
37
|
Get a page requiring HTTP Authentication
|
38
38
|
----------------------------------------
|
39
39
|
|
40
|
-
|
41
|
-
http.
|
40
|
+
my_realm_authenticator = Resourceful::BasicAuthenticator.new('My Realm', 'admin', 'secret')
|
41
|
+
http = Resourceful::HttpAccessor.new(:authenticator => my_realm_authenticator)
|
42
42
|
resp = http.resource('http://example.com/').get
|
43
43
|
puts resp.body
|
44
44
|
|
@@ -53,8 +53,6 @@ callback. If the callback evaluates to true, it will follow the redirect.
|
|
53
53
|
resource.on_redirect { |req, resp| resp.header['Location'] =~ /example.com/ }
|
54
54
|
resource.get # Will only follow the redirect if the new location is example.com
|
55
55
|
|
56
|
-
|
57
|
-
|
58
56
|
Post a URL encoded form
|
59
57
|
-----------------------
|
60
58
|
|
@@ -82,5 +80,5 @@ Delete a resource
|
|
82
80
|
Copyright
|
83
81
|
---------
|
84
82
|
|
85
|
-
Copyright (c) 2008 Absolute Performance, Inc, Peter Williams
|
83
|
+
Copyright (c) 2008 Absolute Performance, Inc, Peter Williams. Released under the MIT License.
|
86
84
|
|
data/Rakefile
CHANGED
@@ -1,14 +1,41 @@
|
|
1
|
-
# -*- ruby -*-
|
2
|
-
|
3
1
|
require 'rubygems'
|
4
|
-
require '
|
5
|
-
require '
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('resourceful', '0.3.0') do |p|
|
6
|
+
p.description = "An HTTP library for Ruby that takes advantage of everything HTTP has to offer."
|
7
|
+
p.url = "http://github.com/paul/resourceful"
|
8
|
+
p.author = "Paul Sadauskas"
|
9
|
+
p.email = "psadauskas@gmail.com"
|
10
|
+
|
11
|
+
p.ignore_pattern = ["pkg/*", "tmp/*"]
|
12
|
+
p.dependencies = ['addressable', 'httpauth', 'rspec', 'facets', 'andand']
|
13
|
+
p.development_dependencies = ['thin', 'yard']
|
14
|
+
end
|
15
|
+
|
16
|
+
require 'spec/rake/spectask'
|
6
17
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
18
|
+
desc 'Run all specs'
|
19
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
20
|
+
t.spec_opts << '--options' << 'spec/spec.opts' if File.exists?('spec/spec.opts')
|
21
|
+
t.libs << 'lib'
|
22
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
12
23
|
end
|
13
24
|
|
14
|
-
|
25
|
+
desc 'Default: Run Specs'
|
26
|
+
task :default => :spec
|
27
|
+
|
28
|
+
desc 'Run all tests'
|
29
|
+
task :test => :spec
|
30
|
+
|
31
|
+
require 'yard'
|
32
|
+
|
33
|
+
desc "Generate Yardoc"
|
34
|
+
YARD::Rake::YardocTask.new do |t|
|
35
|
+
t.files = ['lib/**/*.rb', 'README.markdown']
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Update rubyforge documentation"
|
39
|
+
task :update_docs => :yardoc do
|
40
|
+
puts %x{rsync -aPz doc/* psadauskas@resourceful.rubyforge.org:/var/www/gforge-projects/resourceful/}
|
41
|
+
end
|
@@ -1,20 +1,24 @@
|
|
1
1
|
require 'resourceful/header'
|
2
|
+
require 'andand'
|
2
3
|
|
3
4
|
module Resourceful
|
4
5
|
|
5
|
-
class
|
6
|
+
class AbstractCacheManager
|
6
7
|
def initialize
|
7
8
|
raise NotImplementedError,
|
8
9
|
"Use one of CacheManager's child classes instead. Try NullCacheManager if you don't want any caching at all."
|
9
10
|
end
|
10
11
|
|
11
|
-
#
|
12
|
-
#
|
12
|
+
# Finds a previously cached response to the provided request. The
|
13
|
+
# response returned may be stale.
|
13
14
|
#
|
14
|
-
# @param
|
15
|
-
# The request
|
15
|
+
# @param [Resourceful::Request] request
|
16
|
+
# The request for which we are looking for a response.
|
17
|
+
#
|
18
|
+
# @return [Resourceful::Response]
|
19
|
+
# A (possibly stale) response for the request provided.
|
16
20
|
def lookup(request); end
|
17
|
-
|
21
|
+
|
18
22
|
# Store a response in the cache.
|
19
23
|
#
|
20
24
|
# This method is smart enough to not store responses that cannot be
|
@@ -35,29 +39,11 @@ module Resourceful
|
|
35
39
|
# @param uri<String>
|
36
40
|
# The uri of the resource to be invalidated
|
37
41
|
def invalidate(uri); end
|
38
|
-
|
39
|
-
# Selects the headers from the request named by the response's Vary header
|
40
|
-
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.6
|
41
|
-
#
|
42
|
-
# @param request<Resourceful::Request>
|
43
|
-
# The request used to obtain the response.
|
44
|
-
# @param response<Resourceful::Response>
|
45
|
-
# The response obtained from the request.
|
46
|
-
def select_request_headers(request, response)
|
47
|
-
header = Resourceful::Header.new
|
48
|
-
|
49
|
-
response.header['Vary'].first.split(',').each do |name|
|
50
|
-
name.strip!
|
51
|
-
header[name] = request.header[name]
|
52
|
-
end if response.header['Vary']
|
53
|
-
|
54
|
-
header
|
55
|
-
end
|
56
42
|
end
|
57
43
|
|
58
44
|
# This is the default cache, and does not do any caching. All lookups
|
59
45
|
# result in nil, and all attempts to store a response are a no-op.
|
60
|
-
class NullCacheManager <
|
46
|
+
class NullCacheManager < AbstractCacheManager
|
61
47
|
def initialize; end
|
62
48
|
|
63
49
|
def lookup(request)
|
@@ -70,105 +56,128 @@ module Resourceful
|
|
70
56
|
# This is a nieve implementation of caching. Unused entries are never
|
71
57
|
# removed, and this may eventually eat up all your memory and cause your
|
72
58
|
# machine to explode.
|
73
|
-
class InMemoryCacheManager <
|
59
|
+
class InMemoryCacheManager < AbstractCacheManager
|
74
60
|
|
75
61
|
def initialize
|
76
62
|
@collection = Hash.new{ |h,k| h[k] = CacheEntryCollection.new}
|
77
63
|
end
|
78
64
|
|
79
65
|
def lookup(request)
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
response
|
66
|
+
returning(@collection[request.uri.to_s][request]) do |response|
|
67
|
+
response.authoritative = false if response
|
68
|
+
end
|
85
69
|
end
|
86
70
|
|
87
71
|
def store(request, response)
|
88
72
|
return unless response.cachable?
|
89
73
|
|
90
|
-
|
91
|
-
select_request_headers(request, response),
|
92
|
-
response)
|
93
|
-
|
94
|
-
@collection[request.uri.to_s][request] = entry
|
74
|
+
@collection[request.uri.to_s][request] = response
|
95
75
|
end
|
96
76
|
|
97
77
|
def invalidate(uri)
|
98
78
|
@collection.delete(uri)
|
99
79
|
end
|
80
|
+
end # class InMemoryCacheManager
|
81
|
+
|
82
|
+
# The collection of cached entries. Nominally all the entry in a
|
83
|
+
# collection of this sort will be for the same resource but that is
|
84
|
+
# not required to be true.
|
85
|
+
class CacheEntryCollection
|
86
|
+
include Enumerable
|
87
|
+
|
88
|
+
def initialize
|
89
|
+
@entries = []
|
90
|
+
end
|
91
|
+
|
92
|
+
# Iterates over the entries. Needed for Enumerable
|
93
|
+
def each(&block)
|
94
|
+
@entries.each(&block)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Looks of a Entry that could fullfil the request. Returns nil if none
|
98
|
+
# was found.
|
99
|
+
#
|
100
|
+
# @param [Resourceful::Request] request
|
101
|
+
# The request to use for the lookup.
|
102
|
+
#
|
103
|
+
# @return [Resourceful::Response]
|
104
|
+
# The cached response for the specified request if one is available.
|
105
|
+
def [](request)
|
106
|
+
find { |an_entry| an_entry.valid_for?(request) }.andand.response
|
107
|
+
end
|
108
|
+
|
109
|
+
# Saves an entry into the collection. Replaces any existing ones that could
|
110
|
+
# be used with the updated response.
|
111
|
+
#
|
112
|
+
# @param [Resourceful::Request] request
|
113
|
+
# The request that was used to obtain the response
|
114
|
+
# @param [Resourceful::Response] response
|
115
|
+
# The cache_entry generated from response that was obtained.
|
116
|
+
def []=(request, response)
|
117
|
+
@entries.delete_if { |e| e.valid_for?(request) }
|
118
|
+
@entries << CacheEntry.new(request, response)
|
119
|
+
|
120
|
+
response
|
121
|
+
end
|
122
|
+
end # class CacheEntryCollection
|
123
|
+
|
124
|
+
# Represents a previous request and cached response with enough
|
125
|
+
# detail to determine construct a cached response to a matching
|
126
|
+
# request in the future. It also understands what a matching
|
127
|
+
# request means.
|
128
|
+
class CacheEntry
|
129
|
+
# request_vary_headers is a HttpHeader with keys from the Vary
|
130
|
+
# header of the response, plus the values from the matching fields
|
131
|
+
# in the request
|
132
|
+
attr_reader :request_vary_headers
|
133
|
+
|
134
|
+
# The time at which the client believes the request was made.
|
135
|
+
attr_reader :request_time
|
136
|
+
|
137
|
+
# The URI of the request
|
138
|
+
attr_reader :request_uri
|
139
|
+
|
140
|
+
# The response to that we are caching
|
141
|
+
attr_reader :response
|
142
|
+
|
143
|
+
# @param [Resourceful::Request] request
|
144
|
+
# The request whose response we are storing in the cache.
|
145
|
+
# @param response<Resourceful::Response>
|
146
|
+
# The Response obhect to be stored.
|
147
|
+
def initialize(request, response)
|
148
|
+
@request_uri = request.uri
|
149
|
+
@request_time = request.request_time
|
150
|
+
@request_vary_headers = select_request_headers(request, response)
|
151
|
+
@response = response
|
152
|
+
end
|
100
153
|
|
101
|
-
#
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
def each(&block)
|
111
|
-
@entries.each(&block)
|
112
|
-
end
|
113
|
-
|
114
|
-
# Looks of a Entry that could fullfil the request. Returns nil if none
|
115
|
-
# was found.
|
116
|
-
#
|
117
|
-
# @param request<Resourceful::Request>
|
118
|
-
# The request to use for the lookup.
|
119
|
-
def [](request)
|
120
|
-
self.each do |entry|
|
121
|
-
return entry if entry.valid_for?(request)
|
122
|
-
end
|
123
|
-
return nil
|
124
|
-
end
|
125
|
-
|
126
|
-
# Saves an entry into the collection. Replaces any existing ones that could
|
127
|
-
# be used with the updated response.
|
128
|
-
#
|
129
|
-
# @param request<Resourceful::Request>
|
130
|
-
# The request that was used to obtain the response
|
131
|
-
# @param cache_entry<CacheEntry>
|
132
|
-
# The cache_entry generated from response that was obtained.
|
133
|
-
def []=(request, cache_entry)
|
134
|
-
@entries.delete_if { |e| e.valid_for?(request) }
|
135
|
-
@entries.unshift cache_entry
|
136
|
-
end
|
154
|
+
# Returns true if this entry may be used to fullfil the given request,
|
155
|
+
# according to the vary headers.
|
156
|
+
#
|
157
|
+
# @param request<Resourceful::Request>
|
158
|
+
# The request to do the lookup on.
|
159
|
+
def valid_for?(request)
|
160
|
+
request.uri == @request_uri and
|
161
|
+
@request_vary_headers.all? {|key, value| request.header[key] == value}
|
162
|
+
end
|
137
163
|
|
138
|
-
|
139
|
-
|
140
|
-
#
|
141
|
-
#
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
# @param request_time<Time>
|
149
|
-
# Client-generated timestamp for when the request was made
|
150
|
-
# @param request_vary_headers<Resourceful::HttpHeader>
|
151
|
-
# A HttpHeader constructed from the keys listed in the vary headers
|
152
|
-
# of the response, and values obtained from those headers in the request
|
153
|
-
# @param response<Resourceful::Response>
|
154
|
-
# The Response obhect to be stored.
|
155
|
-
def initialize(request_time, request_vary_headers, response)
|
156
|
-
@request_time, @request_vary_headers, @response = request_time, request_vary_headers, response
|
157
|
-
end
|
164
|
+
# Selects the headers from the request named by the response's Vary header
|
165
|
+
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.6
|
166
|
+
#
|
167
|
+
# @param [Resourceful::Request] request
|
168
|
+
# The request used to obtain the response.
|
169
|
+
# @param [Resourceful::Response] response
|
170
|
+
# The response obtained from the request.
|
171
|
+
def select_request_headers(request, response)
|
172
|
+
header = Resourceful::Header.new
|
158
173
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
# @param request<Resourceful::Request>
|
163
|
-
# The request to do the lookup on.
|
164
|
-
def valid_for?(request)
|
165
|
-
@request_vary_headers.all? do |key, value|
|
166
|
-
request.header[key] == value
|
167
|
-
end
|
168
|
-
end
|
174
|
+
response.header['Vary'].each do |name|
|
175
|
+
header[name] = request.header[name]
|
176
|
+
end if response.header['Vary']
|
169
177
|
|
170
|
-
|
178
|
+
header
|
179
|
+
end
|
171
180
|
|
172
|
-
end # class
|
181
|
+
end # class CacheEntry
|
173
182
|
|
174
183
|
end
|
@@ -40,13 +40,14 @@ module Resourceful
|
|
40
40
|
attr_accessor :logger, :cache_manager
|
41
41
|
|
42
42
|
attr_reader :auth_manager
|
43
|
-
|
44
43
|
attr_reader :user_agent_tokens
|
45
44
|
|
46
45
|
INIT_OPTIONS = OptionsInterpreter.new do
|
47
46
|
option(:logger, :default => Resourceful::BitBucketLogger.new)
|
48
47
|
option(:user_agent, :default => []) {|ua| [ua].flatten}
|
49
48
|
option(:cache_manager, :default => NullCacheManager.new)
|
49
|
+
option(:authenticator)
|
50
|
+
option(:authenticators, :default => [])
|
50
51
|
end
|
51
52
|
|
52
53
|
# Initializes a new HttpAccessor. Valid options:
|
@@ -56,6 +57,13 @@ module Resourceful
|
|
56
57
|
#
|
57
58
|
# +:user_agent+:: One or more additional user agent tokens to
|
58
59
|
# added to the user agent string.
|
60
|
+
#
|
61
|
+
# +:cache_manager+:: The cache manager this accessor should use.
|
62
|
+
#
|
63
|
+
# +:authenticator+:: Add a single authenticator for this accessor.
|
64
|
+
#
|
65
|
+
# +:authenticators+:: Enumerable of the authenticators for this
|
66
|
+
# accessor.
|
59
67
|
def initialize(options = {})
|
60
68
|
@user_agent_tokens = [RESOURCEFUL_USER_AGENT_TOKEN]
|
61
69
|
|
@@ -64,6 +72,9 @@ module Resourceful
|
|
64
72
|
self.logger = opts[:logger]
|
65
73
|
@auth_manager = AuthenticationManager.new()
|
66
74
|
@cache_manager = opts[:cache_manager]
|
75
|
+
|
76
|
+
add_authenticator(opts[:authenticator]) if opts[:authenticator]
|
77
|
+
opts[:authenticators].each { |a| add_authenticator(a) }
|
67
78
|
end
|
68
79
|
end
|
69
80
|
|
@@ -81,5 +92,9 @@ module Resourceful
|
|
81
92
|
end
|
82
93
|
alias [] resource
|
83
94
|
|
95
|
+
# Adds an Authenticator to the set used by the accessor.
|
96
|
+
def add_authenticator(an_authenticator)
|
97
|
+
auth_manager.add_auth_handler(an_authenticator)
|
98
|
+
end
|
84
99
|
end
|
85
100
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/cache_manager"
|
2
|
+
|
3
|
+
require 'memcache'
|
4
|
+
require 'facets/kernel/returning'
|
5
|
+
|
6
|
+
module Resourceful
|
7
|
+
class MemcacheCacheManager < AbstractCacheManager
|
8
|
+
|
9
|
+
# Create a new Memcached backed cache manager
|
10
|
+
#
|
11
|
+
# @param [*String] memcache_servers
|
12
|
+
# list of all Memcached servers this cache manager should use.
|
13
|
+
def initialize(*memcache_servers)
|
14
|
+
@memcache = MemCache.new(memcache_servers, :multithread => true)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Finds a previously cached response to the provided request. The
|
18
|
+
# response returned may be stale.
|
19
|
+
#
|
20
|
+
# @param [Resourceful::Request] request
|
21
|
+
# The request for which we are looking for a response.
|
22
|
+
#
|
23
|
+
# @return [Resourceful::Response, nil]
|
24
|
+
# A (possibly stale) response for the request provided or nil if
|
25
|
+
# no matching response is found.
|
26
|
+
def lookup(request)
|
27
|
+
resp = cache_entries_for(request)[request]
|
28
|
+
return if resp.nil?
|
29
|
+
|
30
|
+
resp.authoritative = false
|
31
|
+
|
32
|
+
resp
|
33
|
+
end
|
34
|
+
|
35
|
+
# Store a response in the cache.
|
36
|
+
#
|
37
|
+
# This method is smart enough to not store responses that cannot be
|
38
|
+
# cached (Vary: * or Cache-Control: no-cache, private, ...)
|
39
|
+
#
|
40
|
+
# @param [Resourceful::Request] request
|
41
|
+
# The request used to obtain the response. This is needed so the
|
42
|
+
# values from the response's Vary header can be stored.
|
43
|
+
# @param [Resourceful::Response] response
|
44
|
+
# The response to be stored.
|
45
|
+
def store(request, response)
|
46
|
+
return unless response.cachable?
|
47
|
+
|
48
|
+
@memcache[request.to_mc_key] = returning(cache_entries_for(request)) do |entries|
|
49
|
+
entries[request] = response
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Invalidates a all cached entries for a uri.
|
54
|
+
#
|
55
|
+
# This is used, for example, to invalidate the cache for a resource
|
56
|
+
# that gets POSTed to.
|
57
|
+
#
|
58
|
+
# @param [String] uri
|
59
|
+
# The uri of the resource to be invalidated
|
60
|
+
def invalidate(uri)
|
61
|
+
@memcache.delete(Digest::MD5.hexdigest(uri))
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
##
|
68
|
+
# The memcache proxy.
|
69
|
+
attr_reader :memcache
|
70
|
+
|
71
|
+
def cache_entries_for(a_request)
|
72
|
+
@memcache.get(a_request.to_mc_key) || Resourceful::CacheEntryCollection.new
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
module MemCacheKey
|
77
|
+
def to_mc_key
|
78
|
+
Digest::MD5.hexdigest(uri)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class Request
|
83
|
+
include MemCacheKey
|
84
|
+
end
|
85
|
+
end
|
data/lib/resourceful/request.rb
CHANGED
@@ -12,6 +12,11 @@ module Resourceful
|
|
12
12
|
attr_accessor :method, :resource, :body, :header
|
13
13
|
attr_reader :request_time
|
14
14
|
|
15
|
+
# @param [Symbol] http_method
|
16
|
+
# :get, :put, :post, :delete or :head
|
17
|
+
# @param [Resourceful::Resource] resource
|
18
|
+
# @param [String] body
|
19
|
+
# @param [Resourceful::Header, Hash] header
|
15
20
|
def initialize(http_method, resource, body = nil, header = nil)
|
16
21
|
@method, @resource, @body = http_method, resource, body
|
17
22
|
@header = header.is_a?(Resourceful::Header) ? header : Resourceful::Header.new(header || {})
|
@@ -50,6 +55,7 @@ module Resourceful
|
|
50
55
|
@header['Cache-Control'] = 'max-age=0' if response.header.has_key?('Cache-Control') and response.header['Cache-Control'].include?('must-revalidate')
|
51
56
|
end
|
52
57
|
|
58
|
+
# @return [String] The URI against which this request will be, or was, made.
|
53
59
|
def uri
|
54
60
|
resource.uri
|
55
61
|
end
|
data/lib/resourceful.rb
CHANGED
data/resourceful.gemspec
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
1
3
|
Gem::Specification.new do |s|
|
2
4
|
s.name = %q{resourceful}
|
3
|
-
s.version = "0.
|
5
|
+
s.version = "0.3.0"
|
4
6
|
|
5
|
-
s.required_rubygems_version = Gem::Requirement.new(">=
|
6
|
-
s.authors = ["Paul Sadauskas"
|
7
|
-
s.date = %q{2008-
|
8
|
-
s.
|
9
|
-
s.
|
10
|
-
s.
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Paul Sadauskas"]
|
9
|
+
s.date = %q{2008-12-05}
|
10
|
+
s.description = %q{An HTTP library for Ruby that takes advantage of everything HTTP has to offer.}
|
11
|
+
s.email = %q{psadauskas@gmail.com}
|
12
|
+
s.extra_rdoc_files = ["lib/resourceful.rb", "lib/resourceful/authentication_manager.rb", "lib/resourceful/util.rb", "lib/resourceful/resource.rb", "lib/resourceful/memcache_cache_manager.rb", "lib/resourceful/net_http_adapter.rb", "lib/resourceful/http_accessor.rb", "lib/resourceful/stubbed_resource_proxy.rb", "lib/resourceful/header.rb", "lib/resourceful/cache_manager.rb", "lib/resourceful/options_interpreter.rb", "lib/resourceful/response.rb", "lib/resourceful/request.rb", "README.markdown"]
|
13
|
+
s.files = ["lib/resourceful.rb", "lib/resourceful/authentication_manager.rb", "lib/resourceful/util.rb", "lib/resourceful/resource.rb", "lib/resourceful/memcache_cache_manager.rb", "lib/resourceful/net_http_adapter.rb", "lib/resourceful/http_accessor.rb", "lib/resourceful/stubbed_resource_proxy.rb", "lib/resourceful/header.rb", "lib/resourceful/cache_manager.rb", "lib/resourceful/options_interpreter.rb", "lib/resourceful/response.rb", "lib/resourceful/request.rb", "spec/acceptance_shared_specs.rb", "spec/spec.opts", "spec/acceptance_spec.rb", "spec/simple_http_server_shared_spec_spec.rb", "spec/spec_helper.rb", "spec/resourceful/header_spec.rb", "spec/resourceful/authentication_manager_spec.rb", "spec/resourceful/memcache_cache_manager_spec.rb", "spec/resourceful/response_spec.rb", "spec/resourceful/options_interpreter_spec.rb", "spec/resourceful/http_accessor_spec.rb", "spec/resourceful/stubbed_resource_proxy_spec.rb", "spec/resourceful/request_spec.rb", "spec/resourceful/resource_spec.rb", "spec/resourceful/cache_manager_spec.rb", "spec/resourceful/net_http_adapter_spec.rb", "spec/simple_http_server_shared_spec.rb", "Manifest", "Rakefile", "README.markdown", "MIT-LICENSE", "resourceful.gemspec"]
|
11
14
|
s.has_rdoc = true
|
12
|
-
s.
|
15
|
+
s.homepage = %q{http://github.com/paul/resourceful}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Resourceful", "--main", "README.markdown"]
|
13
17
|
s.require_paths = ["lib"]
|
14
18
|
s.rubyforge_project = %q{resourceful}
|
15
19
|
s.rubygems_version = %q{1.3.1}
|
@@ -20,11 +24,29 @@ Gem::Specification.new do |s|
|
|
20
24
|
s.specification_version = 2
|
21
25
|
|
22
26
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
23
|
-
s.
|
27
|
+
s.add_runtime_dependency(%q<addressable>, [">= 0"])
|
28
|
+
s.add_runtime_dependency(%q<httpauth>, [">= 0"])
|
29
|
+
s.add_runtime_dependency(%q<rspec>, [">= 0"])
|
30
|
+
s.add_runtime_dependency(%q<facets>, [">= 0"])
|
31
|
+
s.add_runtime_dependency(%q<andand>, [">= 0"])
|
32
|
+
s.add_development_dependency(%q<thin>, [">= 0"])
|
33
|
+
s.add_development_dependency(%q<yard>, [">= 0"])
|
24
34
|
else
|
25
|
-
s.add_dependency(%q<
|
35
|
+
s.add_dependency(%q<addressable>, [">= 0"])
|
36
|
+
s.add_dependency(%q<httpauth>, [">= 0"])
|
37
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
38
|
+
s.add_dependency(%q<facets>, [">= 0"])
|
39
|
+
s.add_dependency(%q<andand>, [">= 0"])
|
40
|
+
s.add_dependency(%q<thin>, [">= 0"])
|
41
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
26
42
|
end
|
27
43
|
else
|
28
|
-
s.add_dependency(%q<
|
44
|
+
s.add_dependency(%q<addressable>, [">= 0"])
|
45
|
+
s.add_dependency(%q<httpauth>, [">= 0"])
|
46
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
47
|
+
s.add_dependency(%q<facets>, [">= 0"])
|
48
|
+
s.add_dependency(%q<andand>, [">= 0"])
|
49
|
+
s.add_dependency(%q<thin>, [">= 0"])
|
50
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
29
51
|
end
|
30
52
|
end
|
@@ -2,8 +2,8 @@ require 'pathname'
|
|
2
2
|
require Pathname(__FILE__).dirname + '../spec_helper'
|
3
3
|
|
4
4
|
require 'resourceful/cache_manager'
|
5
|
-
|
6
|
-
describe Resourceful::
|
5
|
+
|
6
|
+
describe Resourceful::AbstractCacheManager do
|
7
7
|
before do
|
8
8
|
@cm = Resourceful::InMemoryCacheManager.new #cheat, because I cant new a real one.
|
9
9
|
end
|
@@ -19,40 +19,10 @@ describe Resourceful::CacheManager do
|
|
19
19
|
it 'should have a store method' do
|
20
20
|
@cm.should respond_to(:store)
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
it 'should have a invalidate method' do
|
24
24
|
@cm.should respond_to(:invalidate)
|
25
25
|
end
|
26
|
-
|
27
|
-
describe '#select_request_headers' do
|
28
|
-
before do
|
29
|
-
@req_header = mock('header', :[] => nil)
|
30
|
-
@request = mock('request', :header => @req_header)
|
31
|
-
|
32
|
-
@resp_header = mock('header', :[] => nil)
|
33
|
-
@response = mock('response', :header => @resp_header)
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'should select the request headers from the Vary header' do
|
37
|
-
@resp_header.should_receive(:[]).with('Vary')
|
38
|
-
@cm.select_request_headers(@request, @response)
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'should pull the values from the request that match keys in the vary header' do
|
42
|
-
@resp_header.should_receive(:[]).with('Vary').twice.and_return(['foo, bar'])
|
43
|
-
@req_header.should_receive(:[]).with('foo').and_return('oof')
|
44
|
-
@req_header.should_receive(:[]).with('bar').and_return('rab')
|
45
|
-
|
46
|
-
header = @cm.select_request_headers(@request, @response)
|
47
|
-
header['foo'].should == 'oof'
|
48
|
-
header['bar'].should == 'rab'
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'should return a new Header object' do
|
52
|
-
@cm.select_request_headers(@request, @response).should be_kind_of(Resourceful::Header)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
26
|
end
|
57
27
|
|
58
28
|
describe Resourceful::NullCacheManager do
|
@@ -80,7 +50,7 @@ describe Resourceful::InMemoryCacheManager do
|
|
80
50
|
@response = mock('response', :header => {}, :cachable? => true)
|
81
51
|
|
82
52
|
@entry = mock('cache entry', :response => @response, :valid_for? => true)
|
83
|
-
Resourceful::
|
53
|
+
Resourceful::CacheEntry.stub!(:new).and_return(@entry)
|
84
54
|
|
85
55
|
@imcm = Resourceful::InMemoryCacheManager.new
|
86
56
|
end
|
@@ -88,7 +58,7 @@ describe Resourceful::InMemoryCacheManager do
|
|
88
58
|
describe 'finding' do
|
89
59
|
before do
|
90
60
|
@response.stub!(:authoritative=)
|
91
|
-
@imcm.instance_variable_set("@collection", {'uri' => {@request => @
|
61
|
+
@imcm.instance_variable_set("@collection", {'uri' => {@request => @response}})
|
92
62
|
end
|
93
63
|
|
94
64
|
it 'should lookup the response by request' do
|
@@ -103,9 +73,8 @@ describe Resourceful::InMemoryCacheManager do
|
|
103
73
|
|
104
74
|
describe 'saving' do
|
105
75
|
it 'should make a new cache entry' do
|
106
|
-
Resourceful::
|
107
|
-
|
108
|
-
{},
|
76
|
+
Resourceful::CacheEntry.should_receive(:new).with(
|
77
|
+
@request,
|
109
78
|
@response
|
110
79
|
)
|
111
80
|
|
@@ -115,7 +84,7 @@ describe Resourceful::InMemoryCacheManager do
|
|
115
84
|
it 'should store the response entity by request' do
|
116
85
|
@imcm.store(@request, @response)
|
117
86
|
col = @imcm.instance_variable_get("@collection")
|
118
|
-
col['uri'][@request].
|
87
|
+
col['uri'][@request].should == @response
|
119
88
|
end
|
120
89
|
|
121
90
|
it 'should check if the response is cachable' do
|
@@ -142,20 +111,21 @@ describe Resourceful::InMemoryCacheManager do
|
|
142
111
|
|
143
112
|
end
|
144
113
|
|
145
|
-
describe Resourceful::
|
114
|
+
describe Resourceful::CacheEntryCollection do
|
146
115
|
before do
|
147
|
-
@
|
148
|
-
@
|
116
|
+
@request = mock('request', :uri => 'this', :request_time => Time.now, :header => {})
|
117
|
+
@valid_resp = stub('valid_resp', :authoritative= => nil, :header => {})
|
149
118
|
|
150
|
-
@
|
119
|
+
@entry_valid = mock('entry', :valid_for? => true, :response => @valid_resp)
|
120
|
+
@entry_invalid = mock('entry', :valid_for? => false, :response => stub('invalid_resp'))
|
151
121
|
|
152
|
-
@collection = Resourceful::
|
122
|
+
@collection = Resourceful::CacheEntryCollection.new
|
153
123
|
end
|
154
124
|
|
155
125
|
it 'should find the right entry for a request' do
|
156
126
|
@collection.instance_variable_set('@entries', [@entry_valid, @entry_invalid])
|
157
127
|
@entry_valid.should_receive(:valid_for?).with(@request).and_return(true)
|
158
|
-
@collection[@request].should == @
|
128
|
+
@collection[@request].should == @valid_resp
|
159
129
|
end
|
160
130
|
|
161
131
|
it 'should be nil if no matching entry was found' do
|
@@ -165,47 +135,89 @@ describe Resourceful::InMemoryCacheManager::CacheEntryCollection do
|
|
165
135
|
end
|
166
136
|
|
167
137
|
it 'should store an entry' do
|
168
|
-
@collection[@request] = @
|
169
|
-
@collection.instance_variable_get("@entries").should
|
138
|
+
@collection[@request] = @valid_resp
|
139
|
+
@collection.instance_variable_get("@entries").should have(1).items
|
170
140
|
end
|
171
141
|
|
172
142
|
it 'should replace an existing entry if the existing entry matches the request' do
|
173
|
-
|
143
|
+
new_resp = stub('new_resp', :authoritative= => nil, :header => {})
|
174
144
|
|
175
|
-
@collection[@request] = @
|
176
|
-
@collection[@request] =
|
145
|
+
@collection[@request] = @valid_resp
|
146
|
+
@collection[@request] = new_resp
|
177
147
|
|
178
|
-
@collection.instance_variable_get("@entries").should include(
|
179
|
-
@collection.instance_variable_get("@entries").should_not include(@
|
148
|
+
@collection.instance_variable_get("@entries").map{|it| it.response}.should include(new_resp)
|
149
|
+
@collection.instance_variable_get("@entries").map{|it| it.response}.should_not include(@valid_resp)
|
180
150
|
end
|
181
151
|
|
182
152
|
end
|
183
153
|
|
184
|
-
describe Resourceful::
|
154
|
+
describe Resourceful::CacheEntry do
|
185
155
|
before do
|
186
|
-
@entry = Resourceful::
|
187
|
-
|
156
|
+
@entry = Resourceful::CacheEntry.new(
|
157
|
+
mock('original_request', :header => {'Accept' => 'text/plain'} ,
|
158
|
+
:request_time => Time.utc(2008,5,16,0,0,0), :uri => 'http://foo.invalid'),
|
159
|
+
mock('response', :header => {'Vary' => 'Accept'})
|
188
160
|
)
|
189
161
|
|
190
|
-
@request = mock('request')
|
162
|
+
@request = mock('request', :uri => 'http://foo.invalid')
|
191
163
|
end
|
192
164
|
|
193
|
-
|
194
|
-
it "should
|
195
|
-
@entry.
|
165
|
+
describe "#valid_for?(a_request)" do
|
166
|
+
it "should true for request to URI w/ matching header " do
|
167
|
+
@entry.valid_for?(mock("new_request",
|
168
|
+
:uri => 'http://foo.invalid',
|
169
|
+
:header => {'Accept' => 'text/plain'})).should be_true
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should false for requests against different URIs even if headers match" do
|
173
|
+
@entry.valid_for?(mock("new_request", :uri => 'http://bar.invalid',
|
174
|
+
:header => {'Accept' => 'text/plain'})).should be_false
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should false for requests where headers don't match" do
|
178
|
+
@entry.valid_for?(mock("new_request", :uri => 'http://foo.invalid',
|
179
|
+
:header => {'Accept' => 'application/octet-stream'})).should be_false
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should be false if request has a varying header and the original request was missing that header" do
|
183
|
+
entry = Resourceful::CacheEntry.new(
|
184
|
+
mock('original_request', :header => {},
|
185
|
+
:request_time => Time.utc(2008,5,16,0,0,0), :uri => 'http://foo.invalid'),
|
186
|
+
mock('response', :header => {'Vary' => 'Accept'}))
|
187
|
+
|
188
|
+
entry.valid_for?(mock("new_request", :uri => 'http://foo.invalid',
|
189
|
+
:header => {'Accept' => 'text/plain'})).should be_false
|
196
190
|
end
|
197
191
|
end
|
198
192
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
193
|
+
describe '#select_request_headers' do
|
194
|
+
before do
|
195
|
+
@req_header = mock('header', :[] => nil)
|
196
|
+
@request = mock('request', :header => @req_header)
|
203
197
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
198
|
+
@resp_header = mock('header', :[] => nil)
|
199
|
+
@response = mock('response', :header => @resp_header)
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'should select the request headers from the Vary header' do
|
203
|
+
@resp_header.should_receive(:[]).with('Vary')
|
204
|
+
@entry.select_request_headers(@request, @response)
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'should pull the values from the request that match keys in the vary header' do
|
208
|
+
@resp_header.should_receive(:[]).with('Vary').twice.and_return(['foo', 'bar'])
|
209
|
+
@req_header.should_receive(:[]).with('foo').and_return('oof')
|
210
|
+
@req_header.should_receive(:[]).with('bar').and_return('rab')
|
208
211
|
|
212
|
+
header = @entry.select_request_headers(@request, @response)
|
213
|
+
header['foo'].should == 'oof'
|
214
|
+
header['bar'].should == 'rab'
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should return a new Header object' do
|
218
|
+
@entry.select_request_headers(@request, @response).should be_kind_of(Resourceful::Header)
|
219
|
+
end
|
220
|
+
end
|
209
221
|
end
|
210
222
|
|
211
223
|
|
@@ -23,20 +23,26 @@ describe Resourceful::HttpAccessor, 'init' do
|
|
23
23
|
|
24
24
|
it 'should raise arg error if unrecognized options are passed' do
|
25
25
|
lambda {
|
26
|
-
|
26
|
+
Resourceful::HttpAccessor.new(:foo => 'foo', :bar => 'bar')
|
27
27
|
}.should raise_error(ArgumentError, /Unrecognized options: (foo, bar)|(bar, foo)/)
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'should allow an additional user agent token to be passed at init' do
|
31
|
-
Resourceful::HttpAccessor.new(:user_agent => "Super/3000")
|
32
|
-
|
33
|
-
|
31
|
+
ha = Resourceful::HttpAccessor.new(:user_agent => "Super/3000")
|
32
|
+
|
33
|
+
ha.user_agent_string.should match(%r{^Super/3000})
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'should allow multiple additional user agent tokens to be passed at init' do
|
37
|
-
Resourceful::HttpAccessor.new(:user_agent => ["Super/3000", "Duper/2.1"])
|
38
|
-
|
39
|
-
|
37
|
+
ha = Resourceful::HttpAccessor.new(:user_agent => ["Super/3000", "Duper/2.1"])
|
38
|
+
|
39
|
+
ha.user_agent_string.should match(%r{^Super/3000 Duper/2\.1 })
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should allow cache manager to be provided at init' do
|
43
|
+
ha = Resourceful::HttpAccessor.new(:cache_manager => :marker)
|
44
|
+
|
45
|
+
ha.cache_manager.should equal(:marker)
|
40
46
|
end
|
41
47
|
|
42
48
|
end
|
@@ -123,3 +129,36 @@ describe Resourceful::HttpAccessor do
|
|
123
129
|
end
|
124
130
|
|
125
131
|
end
|
132
|
+
|
133
|
+
describe Resourceful::HttpAccessor, "(authentication)" do
|
134
|
+
before do
|
135
|
+
@auth_manager = stub('auth_manager', :add_auth_handler => nil)
|
136
|
+
Resourceful::AuthenticationManager.stub!(:new).and_return(@auth_manager)
|
137
|
+
@ha = Resourceful::HttpAccessor.new()
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should allow authenticators to be registered' do
|
141
|
+
an_authenticator = stub('an_authenicator')
|
142
|
+
@auth_manager.should_receive(:add_auth_handler).with(an_authenticator)
|
143
|
+
|
144
|
+
@ha.add_authenticator(an_authenticator)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'should allow an authenicator to be specified at init' do
|
148
|
+
an_authenticator = stub('an_authenicator')
|
149
|
+
@auth_manager.should_receive(:add_auth_handler).with(an_authenticator)
|
150
|
+
|
151
|
+
Resourceful::HttpAccessor.new(:authenticator => an_authenticator)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should allow multiple authenicators to be specified at init' do
|
155
|
+
authenticator1 = stub('authenicator1')
|
156
|
+
authenticator2 = stub('authenicator2')
|
157
|
+
|
158
|
+
@auth_manager.should_receive(:add_auth_handler).with(authenticator1)
|
159
|
+
@auth_manager.should_receive(:add_auth_handler).with(authenticator2)
|
160
|
+
|
161
|
+
Resourceful::HttpAccessor.new(:authenticators => [authenticator1, authenticator2])
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname + '../spec_helper'
|
3
|
+
|
4
|
+
require 'resourceful/memcache_cache_manager'
|
5
|
+
require 'resourceful/request'
|
6
|
+
|
7
|
+
describe Resourceful::MemcacheCacheManager do
|
8
|
+
before do
|
9
|
+
@resource = stub('resource', :uri => 'http://foo.invalid/')
|
10
|
+
|
11
|
+
@request = Resourceful::Request.new(:get, @resource)
|
12
|
+
@response = Resourceful::Response.new('http://foo.invalid/', '200', {'Vary' => 'Accept'}, "a body")
|
13
|
+
|
14
|
+
@memcache = stub('memcache', :get => nil)
|
15
|
+
MemCache.stub!(:new).and_return(@memcache)
|
16
|
+
|
17
|
+
@cache_mngr = Resourceful::MemcacheCacheManager.new('foobar:42')
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#store(request,response)" do
|
21
|
+
it "should store the new pair in memcache" do
|
22
|
+
@memcache.should_receive(:[]=).with do |key, collection|
|
23
|
+
key.should == Digest::MD5.hexdigest('http://foo.invalid/')
|
24
|
+
collection[@request].should == @response
|
25
|
+
end
|
26
|
+
|
27
|
+
@cache_mngr.store(@request, @response)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should replace existing values if they exist" do
|
31
|
+
entries = Resourceful::CacheEntryCollection.new
|
32
|
+
entries[@request] = @response
|
33
|
+
@memcache.stub!(:[]=).and_return(entries)
|
34
|
+
|
35
|
+
new_request = Resourceful::Request.new(:get, @resource)
|
36
|
+
new_response = Resourceful::Response.new('http://foo.invalid/', '200', {}, "a different body")
|
37
|
+
|
38
|
+
@memcache.should_receive(:[]=).with do |key, collection|
|
39
|
+
collection[new_request].should == new_response
|
40
|
+
end
|
41
|
+
|
42
|
+
@cache_mngr.store(new_request, new_response)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should not store responses that are not cacheable" do
|
46
|
+
@memcache.should_not_receive(:[]=)
|
47
|
+
|
48
|
+
vary_star_response = Resourceful::Response.new('http://foo.invalid/', '200', {'Vary' => '*'}, "a different body")
|
49
|
+
|
50
|
+
@cache_mngr.store(@request, vary_star_response)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#lookup" do
|
55
|
+
before do
|
56
|
+
@entries = Resourceful::CacheEntryCollection.new
|
57
|
+
@entries[@request] = @response
|
58
|
+
@memcache.stub!(:get).and_return(@entries)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should lookup the entry collection by the URI" do
|
62
|
+
@memcache.should_receive(:get).with(Digest::MD5.hexdigest('http://foo.invalid/')).and_return(@entries)
|
63
|
+
|
64
|
+
@cache_mngr.lookup(@request)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should retrieve responses that match request" do
|
68
|
+
@cache_mngr.lookup(Resourceful::Request.new(:get, @resource)).should == @response
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should return nil if no responses that match request are found" do
|
72
|
+
@cache_mngr.lookup(Resourceful::Request.new(:get, @resource, "body", {'Accept' => 'text/plain'})).
|
73
|
+
should be_nil
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should return nil if no responses that resource are found" do
|
77
|
+
@memcache.stub!(:get).and_return(nil)
|
78
|
+
|
79
|
+
@cache_mngr.lookup(Resourceful::Request.new(:get, @resource)).should be_nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#invalidate(url)" do
|
84
|
+
it "should remove all cached responses for that resource from memcache" do
|
85
|
+
@memcache.should_receive(:delete).with(Digest::MD5.hexdigest('http://foo.invalid/'))
|
86
|
+
|
87
|
+
@cache_mngr.invalidate('http://foo.invalid/')
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe Resourceful::MemcacheCacheManager, 'init' do
|
93
|
+
it 'should be createable with single memcache server' do
|
94
|
+
MemCache.should_receive(:new).with(['foobar:42'], anything)
|
95
|
+
|
96
|
+
Resourceful::MemcacheCacheManager.new('foobar:42')
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should be createable with multiple memcache servers' do
|
100
|
+
MemCache.should_receive(:new).with(['foobar:42', 'baz:32'], anything)
|
101
|
+
|
102
|
+
Resourceful::MemcacheCacheManager.new('foobar:42', 'baz:32')
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should create a thread safe memcache client' do
|
106
|
+
MemCache.should_receive(:new).with(anything, {:multithread => true})
|
107
|
+
|
108
|
+
Resourceful::MemcacheCacheManager.new('foobar:42')
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
@@ -62,7 +62,15 @@ describe Resourceful::OptionsInterpreter, '#interpret(options)' do
|
|
62
62
|
@interpreter.interpret({}).keys.should_not include(:foo)
|
63
63
|
end
|
64
64
|
|
65
|
-
it 'should not invoked option value munging block if option is not specified'
|
65
|
+
it 'should not invoked option value munging block if option is not specified' do
|
66
|
+
@interpreter = Resourceful::OptionsInterpreter.new()
|
67
|
+
munging_block_executed = false
|
68
|
+
@interpreter.option(:foo) { |a| munging_block_executed = true }
|
69
|
+
|
70
|
+
lambda {
|
71
|
+
@interpreter.interpret({})
|
72
|
+
}.should_not change{munging_block_executed}
|
73
|
+
end
|
66
74
|
|
67
75
|
it 'should use default if option is not specified' do
|
68
76
|
@interpreter = Resourceful::OptionsInterpreter.new()
|
@@ -124,7 +124,7 @@ end unless defined? AuthorizationResponder
|
|
124
124
|
describe 'simple http server', :shared => true do
|
125
125
|
before(:all) do
|
126
126
|
require 'rack'
|
127
|
-
require '
|
127
|
+
require 'thin'
|
128
128
|
|
129
129
|
app = Rack::Builder.new do |env|
|
130
130
|
use Rack::ShowExceptions
|
@@ -145,7 +145,9 @@ describe 'simple http server', :shared => true do
|
|
145
145
|
|
146
146
|
#spawn the server in a separate thread
|
147
147
|
@httpd = Thread.new do
|
148
|
-
|
148
|
+
Thin::Logging.silent = true
|
149
|
+
# Thin::Logging.debug = true
|
150
|
+
Thin::Server.start(app)
|
149
151
|
end
|
150
152
|
#give the server a chance to initialize
|
151
153
|
sleep 0.05
|
metadata
CHANGED
@@ -1,78 +1,147 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paul-resourceful
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Sadauskas
|
8
|
-
- Peter Williams
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
11
|
|
13
|
-
date: 2008-
|
12
|
+
date: 2008-12-05 00:00:00 -08:00
|
14
13
|
default_executable:
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
|
-
name:
|
16
|
+
name: addressable
|
18
17
|
version_requirement:
|
19
18
|
version_requirements: !ruby/object:Gem::Requirement
|
20
19
|
requirements:
|
21
20
|
- - ">="
|
22
21
|
- !ruby/object:Gem::Version
|
23
|
-
version:
|
22
|
+
version: "0"
|
24
23
|
version:
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: httpauth
|
26
|
+
version_requirement:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: "0"
|
32
|
+
version:
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rspec
|
35
|
+
version_requirement:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: "0"
|
41
|
+
version:
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: facets
|
44
|
+
version_requirement:
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: "0"
|
50
|
+
version:
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
name: andand
|
53
|
+
version_requirement:
|
54
|
+
version_requirements: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
version:
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: thin
|
62
|
+
version_requirement:
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
version:
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: yard
|
71
|
+
version_requirement:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: "0"
|
77
|
+
version:
|
78
|
+
description: An HTTP library for Ruby that takes advantage of everything HTTP has to offer.
|
79
|
+
email: psadauskas@gmail.com
|
29
80
|
executables: []
|
30
81
|
|
31
82
|
extensions: []
|
32
83
|
|
33
84
|
extra_rdoc_files:
|
34
|
-
- Manifest.txt
|
35
|
-
files:
|
36
|
-
- MIT-LICENSE
|
37
|
-
- Manifest.txt
|
38
|
-
- README.markdown
|
39
|
-
- Rakefile
|
40
85
|
- lib/resourceful.rb
|
41
86
|
- lib/resourceful/authentication_manager.rb
|
42
|
-
- lib/resourceful/
|
43
|
-
- lib/resourceful/
|
44
|
-
- lib/resourceful/
|
87
|
+
- lib/resourceful/util.rb
|
88
|
+
- lib/resourceful/resource.rb
|
89
|
+
- lib/resourceful/memcache_cache_manager.rb
|
45
90
|
- lib/resourceful/net_http_adapter.rb
|
91
|
+
- lib/resourceful/http_accessor.rb
|
92
|
+
- lib/resourceful/stubbed_resource_proxy.rb
|
93
|
+
- lib/resourceful/header.rb
|
94
|
+
- lib/resourceful/cache_manager.rb
|
46
95
|
- lib/resourceful/options_interpreter.rb
|
96
|
+
- lib/resourceful/response.rb
|
47
97
|
- lib/resourceful/request.rb
|
98
|
+
- README.markdown
|
99
|
+
files:
|
100
|
+
- lib/resourceful.rb
|
101
|
+
- lib/resourceful/authentication_manager.rb
|
102
|
+
- lib/resourceful/util.rb
|
48
103
|
- lib/resourceful/resource.rb
|
49
|
-
- lib/resourceful/
|
104
|
+
- lib/resourceful/memcache_cache_manager.rb
|
105
|
+
- lib/resourceful/net_http_adapter.rb
|
106
|
+
- lib/resourceful/http_accessor.rb
|
50
107
|
- lib/resourceful/stubbed_resource_proxy.rb
|
51
|
-
- lib/resourceful/
|
52
|
-
- lib/resourceful/
|
53
|
-
- resourceful.
|
108
|
+
- lib/resourceful/header.rb
|
109
|
+
- lib/resourceful/cache_manager.rb
|
110
|
+
- lib/resourceful/options_interpreter.rb
|
111
|
+
- lib/resourceful/response.rb
|
112
|
+
- lib/resourceful/request.rb
|
54
113
|
- spec/acceptance_shared_specs.rb
|
114
|
+
- spec/spec.opts
|
55
115
|
- spec/acceptance_spec.rb
|
56
|
-
- spec/
|
57
|
-
- spec/
|
116
|
+
- spec/simple_http_server_shared_spec_spec.rb
|
117
|
+
- spec/spec_helper.rb
|
58
118
|
- spec/resourceful/header_spec.rb
|
59
|
-
- spec/resourceful/
|
60
|
-
- spec/resourceful/
|
119
|
+
- spec/resourceful/authentication_manager_spec.rb
|
120
|
+
- spec/resourceful/memcache_cache_manager_spec.rb
|
121
|
+
- spec/resourceful/response_spec.rb
|
61
122
|
- spec/resourceful/options_interpreter_spec.rb
|
123
|
+
- spec/resourceful/http_accessor_spec.rb
|
124
|
+
- spec/resourceful/stubbed_resource_proxy_spec.rb
|
62
125
|
- spec/resourceful/request_spec.rb
|
63
126
|
- spec/resourceful/resource_spec.rb
|
64
|
-
- spec/resourceful/
|
65
|
-
- spec/resourceful/
|
127
|
+
- spec/resourceful/cache_manager_spec.rb
|
128
|
+
- spec/resourceful/net_http_adapter_spec.rb
|
66
129
|
- spec/simple_http_server_shared_spec.rb
|
67
|
-
-
|
68
|
-
-
|
69
|
-
-
|
130
|
+
- Manifest
|
131
|
+
- Rakefile
|
132
|
+
- README.markdown
|
133
|
+
- MIT-LICENSE
|
134
|
+
- resourceful.gemspec
|
70
135
|
has_rdoc: true
|
71
|
-
homepage:
|
136
|
+
homepage: http://github.com/paul/resourceful
|
72
137
|
post_install_message:
|
73
138
|
rdoc_options:
|
139
|
+
- --line-numbers
|
140
|
+
- --inline-source
|
141
|
+
- --title
|
142
|
+
- Resourceful
|
74
143
|
- --main
|
75
|
-
- README.
|
144
|
+
- README.markdown
|
76
145
|
require_paths:
|
77
146
|
- lib
|
78
147
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -85,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
154
|
requirements:
|
86
155
|
- - ">="
|
87
156
|
- !ruby/object:Gem::Version
|
88
|
-
version: "
|
157
|
+
version: "1.2"
|
89
158
|
version:
|
90
159
|
requirements: []
|
91
160
|
|
data/Manifest.txt
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
MIT-LICENSE
|
2
|
-
Manifest.txt
|
3
|
-
README.markdown
|
4
|
-
Rakefile
|
5
|
-
lib/resourceful.rb
|
6
|
-
lib/resourceful/authentication_manager.rb
|
7
|
-
lib/resourceful/cache_manager.rb
|
8
|
-
lib/resourceful/header.rb
|
9
|
-
lib/resourceful/http_accessor.rb
|
10
|
-
lib/resourceful/net_http_adapter.rb
|
11
|
-
lib/resourceful/options_interpreter.rb
|
12
|
-
lib/resourceful/request.rb
|
13
|
-
lib/resourceful/resource.rb
|
14
|
-
lib/resourceful/response.rb
|
15
|
-
lib/resourceful/stubbed_resource_proxy.rb
|
16
|
-
lib/resourceful/util.rb
|
17
|
-
lib/resourceful/version.rb
|
18
|
-
resourceful.gemspec
|
19
|
-
spec/acceptance_shared_specs.rb
|
20
|
-
spec/acceptance_spec.rb
|
21
|
-
spec/resourceful/authentication_manager_spec.rb
|
22
|
-
spec/resourceful/cache_manager_spec.rb
|
23
|
-
spec/resourceful/header_spec.rb
|
24
|
-
spec/resourceful/http_accessor_spec.rb
|
25
|
-
spec/resourceful/net_http_adapter_spec.rb
|
26
|
-
spec/resourceful/options_interpreter_spec.rb
|
27
|
-
spec/resourceful/request_spec.rb
|
28
|
-
spec/resourceful/resource_spec.rb
|
29
|
-
spec/resourceful/response_spec.rb
|
30
|
-
spec/resourceful/stubbed_resource_proxy_spec.rb
|
31
|
-
spec/simple_http_server_shared_spec.rb
|
32
|
-
spec/simple_http_server_shared_spec_spec.rb
|
33
|
-
spec/spec.opts
|
34
|
-
spec/spec_helper.rb
|
data/lib/resourceful/version.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
RESOURCEFUL_VERSION = '0.2'
|