paul-resourceful 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|