resourceful 0.5.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +18 -0
- data/Manifest +11 -1
- data/README.markdown +11 -2
- data/Rakefile +38 -18
- data/lib/resourceful.rb +6 -2
- data/lib/resourceful/abstract_form_data.rb +18 -0
- data/lib/resourceful/header.rb +228 -97
- data/lib/resourceful/http_accessor.rb +32 -26
- data/lib/resourceful/multipart_form_data.rb +46 -0
- data/lib/resourceful/net_http_adapter.rb +19 -5
- data/lib/resourceful/options_interpretation.rb +72 -0
- data/lib/resourceful/request.rb +6 -2
- data/lib/resourceful/resource.rb +25 -9
- data/lib/resourceful/response.rb +5 -5
- data/lib/resourceful/urlencoded_form_data.rb +17 -0
- data/resourceful.gemspec +7 -7
- data/spec/acceptance/caching_spec.rb +6 -8
- data/spec/acceptance/header_spec.rb +1 -1
- data/spec/acceptance/resource_spec.rb +3 -3
- data/spec/caching_spec.rb +89 -0
- data/spec/resourceful/header_spec.rb +8 -0
- data/spec/resourceful/multipart_form_data_spec.rb +77 -0
- data/spec/resourceful/resource_spec.rb +20 -0
- data/spec/resourceful/urlencoded_form_data_spec.rb +44 -0
- data/spec/simple_sinatra_server.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- metadata +18 -6
- data/lib/resourceful/options_interpreter.rb +0 -78
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
|
3
|
-
require 'resourceful/
|
3
|
+
require 'resourceful/options_interpretation'
|
4
4
|
require 'resourceful/authentication_manager'
|
5
5
|
require 'resourceful/cache_manager'
|
6
6
|
require 'resourceful/resource'
|
@@ -28,7 +28,8 @@ module Resourceful
|
|
28
28
|
# provided by the Resourceful library. Conceptually this object
|
29
29
|
# acts a collection of all the resources available via HTTP.
|
30
30
|
class HttpAccessor
|
31
|
-
|
31
|
+
include OptionsInterpretation
|
32
|
+
|
32
33
|
# A logger object to which messages about the activities of this
|
33
34
|
# object will be written. This should be an object that responds
|
34
35
|
# to +#info(message)+ and +#debug(message)+.
|
@@ -40,40 +41,45 @@ module Resourceful
|
|
40
41
|
attr_reader :auth_manager
|
41
42
|
attr_reader :user_agent_tokens
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
option(:cache_manager, :default => NullCacheManager.new)
|
47
|
-
option(:authenticator)
|
48
|
-
option(:authenticators, :default => [])
|
49
|
-
end
|
44
|
+
##
|
45
|
+
# The adapter this accessor will use to make the actual HTTP requests.
|
46
|
+
attr_reader :http_adapter
|
50
47
|
|
51
48
|
# Initializes a new HttpAccessor. Valid options:
|
52
49
|
#
|
53
|
-
#
|
54
|
-
# send log messages
|
50
|
+
# `:logger`
|
51
|
+
# : A Logger object that the new HTTP accessor should send log messages
|
52
|
+
#
|
53
|
+
# `:user_agent`
|
54
|
+
# : One or more additional user agent tokens to added to the user agent string.
|
55
55
|
#
|
56
|
-
#
|
57
|
-
#
|
56
|
+
# `:cache_manager`
|
57
|
+
# : The cache manager this accessor should use.
|
58
58
|
#
|
59
|
-
#
|
59
|
+
# `:authenticator`
|
60
|
+
# : Add a single authenticator for this accessor.
|
60
61
|
#
|
61
|
-
#
|
62
|
+
# `:authenticators`
|
63
|
+
# : Enumerable of the authenticators for this accessor.
|
62
64
|
#
|
63
|
-
#
|
64
|
-
# accessor
|
65
|
+
# `http_adapter`
|
66
|
+
# : The HttpAdapter to be used by this accessor
|
67
|
+
#
|
68
|
+
#
|
65
69
|
def initialize(options = {})
|
66
70
|
@user_agent_tokens = [RESOURCEFUL_USER_AGENT_TOKEN]
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
71
|
+
@auth_manager = AuthenticationManager.new()
|
72
|
+
|
73
|
+
extract_opts(options) do |opts|
|
74
|
+
@user_agent_tokens.push(*opts.extract(:user_agent, :default => []) {|ua| [ua].flatten})
|
75
|
+
|
76
|
+
self.logger = opts.extract(:logger, :default => BitBucketLogger.new)
|
77
|
+
@cache_manager = opts.extract(:cache_manager, :default => NullCacheManager.new)
|
78
|
+
@http_adapter = opts.extract(:http_adapter, :default => lambda{NetHttpAdapter.new})
|
73
79
|
|
74
|
-
|
75
|
-
opts
|
76
|
-
end
|
80
|
+
opts.extract(:authenticator, :required => false).tap{|a| add_authenticator(a) if a}
|
81
|
+
opts.extract(:authenticators, :default => []).each { |a| add_authenticator(a) }
|
82
|
+
end
|
77
83
|
end
|
78
84
|
|
79
85
|
# Returns the string that identifies this HTTP accessor. If you
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'resourceful/abstract_form_data'
|
2
|
+
|
3
|
+
module Resourceful
|
4
|
+
class MultipartFormData < AbstractFormData
|
5
|
+
FileParamValue = Struct.new(:content, :file_name, :content_type)
|
6
|
+
|
7
|
+
def add_file(name, file_name, content_type="application/octet-stream")
|
8
|
+
add(name, FileParamValue.new(File.new(file_name, 'r'), File.basename(file_name), content_type))
|
9
|
+
end
|
10
|
+
|
11
|
+
def content_type
|
12
|
+
"multipart/form-data; boundary=#{boundary}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def read
|
16
|
+
StringIO.new.tap do |out|
|
17
|
+
first = true
|
18
|
+
form_data.each do |key, val|
|
19
|
+
out << "\r\n" unless first
|
20
|
+
out << "--" << boundary
|
21
|
+
out << "\r\nContent-Disposition: form-data; name=\"#{key}\""
|
22
|
+
if val.kind_of?(FileParamValue)
|
23
|
+
out << "; filename=\"#{val.file_name}\""
|
24
|
+
out << "\r\nContent-Type: #{val.content_type}"
|
25
|
+
end
|
26
|
+
out << "\r\n\r\n"
|
27
|
+
if val.kind_of?(FileParamValue)
|
28
|
+
out << val.content.read
|
29
|
+
else
|
30
|
+
out << val.to_s
|
31
|
+
end
|
32
|
+
first = false
|
33
|
+
end
|
34
|
+
out << "\r\n--#{boundary}--"
|
35
|
+
end.string
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def boundary
|
41
|
+
@boundary ||= (0..30).map{BOUNDARY_CHARS[rand(BOUNDARY_CHARS.length)]}.join
|
42
|
+
end
|
43
|
+
|
44
|
+
BOUNDARY_CHARS = [('a'..'z').to_a,('A'..'Z').to_a,(0..9).to_a].flatten
|
45
|
+
end
|
46
|
+
end
|
@@ -23,17 +23,31 @@ module Resourceful
|
|
23
23
|
# Make an HTTP request using the standard library net/http.
|
24
24
|
#
|
25
25
|
# Will use a proxy defined in the http_proxy environment variable, if set.
|
26
|
-
|
26
|
+
#
|
27
|
+
# @param [#read] body
|
28
|
+
# An IO-ish thing containing the body of the request
|
29
|
+
#
|
30
|
+
def make_request(method, uri, body = nil, header = nil)
|
27
31
|
uri = uri.is_a?(Addressable::URI) ? uri : Addressable::URI.parse(uri)
|
28
32
|
|
33
|
+
if [:put, :post].include? method
|
34
|
+
body = body ? body.read : ""
|
35
|
+
header[:content_length] = body.size
|
36
|
+
end
|
37
|
+
|
29
38
|
req = net_http_request_class(method).new(uri.absolute_path)
|
30
39
|
header.each_field { |k,v| req[k] = v } if header
|
31
40
|
https = ("https" == uri.scheme)
|
32
|
-
|
41
|
+
conn_class = proxy_details ? Net::HTTP.Proxy(*proxy_details) : Net::HTTP
|
42
|
+
conn = conn_class.new(uri.host, uri.port || (https ? 443 : 80))
|
33
43
|
conn.use_ssl = https
|
34
44
|
begin
|
35
45
|
conn.start
|
36
|
-
res =
|
46
|
+
res = if body
|
47
|
+
conn.request(req, body)
|
48
|
+
else
|
49
|
+
conn.request(req)
|
50
|
+
end
|
37
51
|
ensure
|
38
52
|
conn.finish if conn.started?
|
39
53
|
end
|
@@ -49,12 +63,12 @@ module Resourceful
|
|
49
63
|
private
|
50
64
|
|
51
65
|
# Parse proxy details from http_proxy environment variable
|
52
|
-
def
|
66
|
+
def proxy_details
|
53
67
|
proxy = Addressable::URI.parse(ENV["http_proxy"])
|
54
68
|
[proxy.host, proxy.port, proxy.user, proxy.password] if proxy
|
55
69
|
end
|
56
70
|
|
57
|
-
def
|
71
|
+
def net_http_request_class(method)
|
58
72
|
case method
|
59
73
|
when :get then Net::HTTP::Get
|
60
74
|
when :head then Net::HTTP::Head
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Resourceful
|
2
|
+
# Declarative way of interpreting options hashes
|
3
|
+
#
|
4
|
+
# include OptionsInterpretion
|
5
|
+
# def my_method(opts = {})
|
6
|
+
# extract_opts(opts) do |opts|
|
7
|
+
# host = opts.extract(:host)
|
8
|
+
# port = opts.extract(:port, :default => 80) {|p| Integer(p)}
|
9
|
+
# end
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
module OptionsInterpretation
|
13
|
+
# Interpret an options hash
|
14
|
+
#
|
15
|
+
# @param [Hash] opts
|
16
|
+
# The options to interpret.
|
17
|
+
#
|
18
|
+
# @yield block that used to interpreter options hash
|
19
|
+
#
|
20
|
+
# @yieldparam [Resourceful::OptionsInterpretion::OptionsInterpreter] interpeter
|
21
|
+
# An interpreter that can be used to extract option information from the options hash.
|
22
|
+
def extract_opts(opts, &blk)
|
23
|
+
opts = opts.clone
|
24
|
+
yield OptionsInterpreter.new(opts)
|
25
|
+
|
26
|
+
unless opts.empty?
|
27
|
+
raise ArgumentError, "Unrecognized options: #{opts.keys.join(", ")}"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
class OptionsInterpreter
|
33
|
+
def initialize(options_hash)
|
34
|
+
@options_hash = options_hash
|
35
|
+
end
|
36
|
+
|
37
|
+
# Extract a particular option.
|
38
|
+
#
|
39
|
+
# @param [String] name
|
40
|
+
# Name of option to extract
|
41
|
+
# @param [Hash] interpreter_opts
|
42
|
+
# ':default'
|
43
|
+
# :: The default value, or an object that responds to #call
|
44
|
+
# with the default value.
|
45
|
+
# ':required'
|
46
|
+
# :: Boolean indicating if this option is required. Default:
|
47
|
+
# false if a default is provided; otherwise true.
|
48
|
+
def extract(name, interpreter_opts = {}, &blk)
|
49
|
+
option_required = !interpreter_opts.has_key?(:default)
|
50
|
+
option_required = interpreter_opts[:required] if interpreter_opts.has_key?(:required)
|
51
|
+
|
52
|
+
raise ArgumentError, "Required option #{name} not provided" if option_required && !@options_hash.has_key?(name)
|
53
|
+
# We have the option we need
|
54
|
+
|
55
|
+
orig_val = @options_hash.delete(name)
|
56
|
+
|
57
|
+
if block_given?
|
58
|
+
yield orig_val
|
59
|
+
|
60
|
+
elsif orig_val
|
61
|
+
orig_val
|
62
|
+
|
63
|
+
elsif interpreter_opts[:default] && interpreter_opts[:default].respond_to?(:call)
|
64
|
+
interpreter_opts[:default].call()
|
65
|
+
|
66
|
+
elsif interpreter_opts[:default]
|
67
|
+
interpreter_opts[:default]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/resourceful/request.rb
CHANGED
@@ -163,7 +163,7 @@ module Resourceful
|
|
163
163
|
def perform!
|
164
164
|
@request_time = Time.now
|
165
165
|
|
166
|
-
http_resp =
|
166
|
+
http_resp = adapter.make_request(@method, @resource.uri, @body, @header)
|
167
167
|
@response = Resourceful::Response.new(uri, *http_resp)
|
168
168
|
@response.request_time = @request_time
|
169
169
|
@response.authoritative = true
|
@@ -205,7 +205,7 @@ module Resourceful
|
|
205
205
|
|
206
206
|
# Does this request force us to revalidate the cache?
|
207
207
|
def forces_revalidation?
|
208
|
-
if max_age == 0 ||
|
208
|
+
if max_age == 0 || skip_cache?
|
209
209
|
logger.info(" Client forced revalidation")
|
210
210
|
true
|
211
211
|
else
|
@@ -225,6 +225,10 @@ module Resourceful
|
|
225
225
|
def logger
|
226
226
|
resource.logger
|
227
227
|
end
|
228
|
+
|
229
|
+
def adapter
|
230
|
+
accessor.http_adapter
|
231
|
+
end
|
228
232
|
end
|
229
233
|
|
230
234
|
end
|
data/lib/resourceful/resource.rb
CHANGED
@@ -5,7 +5,6 @@ module Resourceful
|
|
5
5
|
|
6
6
|
class Resource
|
7
7
|
attr_reader :accessor
|
8
|
-
attr_accessor :default_header
|
9
8
|
|
10
9
|
# Build a new resource for a uri
|
11
10
|
#
|
@@ -30,6 +29,10 @@ module Resourceful
|
|
30
29
|
end
|
31
30
|
alias uri effective_uri
|
32
31
|
|
32
|
+
def default_header(temp_defaults = {})
|
33
|
+
@default_header.merge(temp_defaults)
|
34
|
+
end
|
35
|
+
|
33
36
|
# Returns the host for this Resource's current uri
|
34
37
|
def host
|
35
38
|
Addressable::URI.parse(uri).host
|
@@ -95,7 +98,6 @@ module Resourceful
|
|
95
98
|
# @raise [UnsuccessfulHttpRequestError] unless the request is a
|
96
99
|
# success, ie the final request returned a 2xx response code
|
97
100
|
def post(data = nil, header = {})
|
98
|
-
check_content_type_exists(data, header)
|
99
101
|
request(:post, data, header)
|
100
102
|
end
|
101
103
|
|
@@ -116,7 +118,6 @@ module Resourceful
|
|
116
118
|
# @raise [UnsuccessfulHttpRequestError] unless the request is a
|
117
119
|
# success, ie the final request returned a 2xx response code
|
118
120
|
def put(data, header = {})
|
119
|
-
check_content_type_exists(data, header)
|
120
121
|
request(:put, data, header)
|
121
122
|
end
|
122
123
|
|
@@ -137,17 +138,32 @@ module Resourceful
|
|
137
138
|
private
|
138
139
|
|
139
140
|
# Ensures that the request has a content type header
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
141
|
+
def ensure_content_type(body, header)
|
142
|
+
return if header.has_key?('Content-Type')
|
143
|
+
|
144
|
+
if body.respond_to?(:content_type)
|
145
|
+
header['Content-Type'] = body.content_type
|
146
|
+
return
|
144
147
|
end
|
148
|
+
|
149
|
+
return if default_header.has_key?('Content-Type')
|
150
|
+
|
151
|
+
# could not figure it out
|
152
|
+
raise MissingContentType
|
145
153
|
end
|
146
154
|
|
147
155
|
# Actually make the request
|
148
156
|
def request(method, data, header)
|
149
|
-
|
150
|
-
|
157
|
+
header = default_header.merge(header)
|
158
|
+
ensure_content_type(data, header) if data
|
159
|
+
|
160
|
+
data = StringIO.new(data) if data.kind_of?(String)
|
161
|
+
|
162
|
+
logger.debug { header.map {|k,v| "#{k}: #{v}"}.join("\n\t\t") }
|
163
|
+
logger.debug { data = StringIO.new(data.read); data.string } if data
|
164
|
+
|
165
|
+
log_request_with_time "#{method.to_s.upcase} [#{uri}]" do
|
166
|
+
request = Request.new(method, self, data, header)
|
151
167
|
request.fetch_response
|
152
168
|
end
|
153
169
|
end
|
data/lib/resourceful/response.rb
CHANGED
@@ -26,8 +26,8 @@ module Resourceful
|
|
26
26
|
if header['Cache-Control'] and header['Cache-Control'].first.include?('max-age')
|
27
27
|
max_age = header['Cache-Control'].first.split(',').grep(/max-age/).first.split('=').last.to_i
|
28
28
|
return true if current_age > max_age
|
29
|
-
elsif header['
|
30
|
-
return true if Time.httpdate(header['
|
29
|
+
elsif header['Expires']
|
30
|
+
return true if Time.httpdate(header['Expires']) < Time.now
|
31
31
|
end
|
32
32
|
|
33
33
|
false
|
@@ -75,8 +75,8 @@ module Resourceful
|
|
75
75
|
|
76
76
|
# Algorithm taken from RCF2616#13.2.3
|
77
77
|
def current_age
|
78
|
-
age_value = header['Age']
|
79
|
-
date_value = Time.httpdate(header['Date']
|
78
|
+
age_value = header['Age'] || 0
|
79
|
+
date_value = Time.httpdate(header['Date'])
|
80
80
|
now = Time.now
|
81
81
|
|
82
82
|
apparent_age = [0, response_time - date_value].max
|
@@ -85,7 +85,7 @@ module Resourceful
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def body
|
88
|
-
encoding = header['Content-Encoding']
|
88
|
+
encoding = header['Content-Encoding']
|
89
89
|
case encoding
|
90
90
|
when nil
|
91
91
|
# body is identity encoded; just return it
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'resourceful/abstract_form_data'
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
module Resourceful
|
5
|
+
class UrlencodedFormData < AbstractFormData
|
6
|
+
|
7
|
+
def content_type
|
8
|
+
"application/x-www-form-urlencoded"
|
9
|
+
end
|
10
|
+
|
11
|
+
def read
|
12
|
+
@form_data.map do |k,v|
|
13
|
+
CGI.escape(k) + '=' + CGI.escape(v)
|
14
|
+
end.join('&')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/resourceful.gemspec
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{resourceful}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.6.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Paul Sadauskas"]
|
9
|
-
s.date = %q{2009-08-
|
9
|
+
s.date = %q{2009-08-14}
|
10
10
|
s.description = %q{An HTTP library for Ruby that takes advantage of everything HTTP has to offer.}
|
11
11
|
s.email = %q{psadauskas@gmail.com}
|
12
|
-
s.extra_rdoc_files = ["lib/resourceful.rb", "lib/resourceful/net_http_adapter.rb", "lib/resourceful/stubbed_resource_proxy.rb", "lib/resourceful/header.rb", "lib/resourceful/memcache_cache_manager.rb", "lib/resourceful/response.rb", "lib/resourceful/util.rb", "lib/resourceful/
|
13
|
-
s.files = ["lib/resourceful.rb", "lib/resourceful/net_http_adapter.rb", "lib/resourceful/stubbed_resource_proxy.rb", "lib/resourceful/header.rb", "lib/resourceful/memcache_cache_manager.rb", "lib/resourceful/response.rb", "lib/resourceful/util.rb", "lib/resourceful/
|
12
|
+
s.extra_rdoc_files = ["lib/resourceful.rb", "lib/resourceful/net_http_adapter.rb", "lib/resourceful/options_interpretation.rb", "lib/resourceful/stubbed_resource_proxy.rb", "lib/resourceful/urlencoded_form_data.rb", "lib/resourceful/header.rb", "lib/resourceful/memcache_cache_manager.rb", "lib/resourceful/response.rb", "lib/resourceful/util.rb", "lib/resourceful/abstract_form_data.rb", "lib/resourceful/cache_manager.rb", "lib/resourceful/request.rb", "lib/resourceful/resource.rb", "lib/resourceful/exceptions.rb", "lib/resourceful/multipart_form_data.rb", "lib/resourceful/http_accessor.rb", "lib/resourceful/authentication_manager.rb", "README.markdown"]
|
13
|
+
s.files = ["lib/resourceful.rb", "lib/resourceful/net_http_adapter.rb", "lib/resourceful/options_interpretation.rb", "lib/resourceful/stubbed_resource_proxy.rb", "lib/resourceful/urlencoded_form_data.rb", "lib/resourceful/header.rb", "lib/resourceful/memcache_cache_manager.rb", "lib/resourceful/response.rb", "lib/resourceful/util.rb", "lib/resourceful/abstract_form_data.rb", "lib/resourceful/cache_manager.rb", "lib/resourceful/request.rb", "lib/resourceful/resource.rb", "lib/resourceful/exceptions.rb", "lib/resourceful/multipart_form_data.rb", "lib/resourceful/http_accessor.rb", "lib/resourceful/authentication_manager.rb", "History.txt", "resourceful.gemspec", "README.markdown", "MIT-LICENSE", "Rakefile", "Manifest", "spec/simple_sinatra_server_spec.rb", "spec/old_acceptance_specs.rb", "spec/acceptance_shared_specs.rb", "spec/spec_helper.rb", "spec/simple_sinatra_server.rb", "spec/acceptance/authorization_spec.rb", "spec/acceptance/header_spec.rb", "spec/acceptance/resource_spec.rb", "spec/acceptance/caching_spec.rb", "spec/acceptance/redirecting_spec.rb", "spec/resourceful/multipart_form_data_spec.rb", "spec/resourceful/header_spec.rb", "spec/resourceful/resource_spec.rb", "spec/resourceful/urlencoded_form_data_spec.rb", "spec/caching_spec.rb", "spec/spec.opts"]
|
14
14
|
s.homepage = %q{http://github.com/paul/resourceful}
|
15
15
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Resourceful", "--main", "README.markdown"]
|
16
16
|
s.require_paths = ["lib"]
|
@@ -23,14 +23,14 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.specification_version = 3
|
24
24
|
|
25
25
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
26
|
-
s.add_runtime_dependency(%q<addressable>, [">= 0"])
|
26
|
+
s.add_runtime_dependency(%q<addressable>, [">= 2.1.0"])
|
27
27
|
s.add_runtime_dependency(%q<httpauth>, [">= 0"])
|
28
28
|
s.add_development_dependency(%q<thin>, [">= 0"])
|
29
29
|
s.add_development_dependency(%q<yard>, [">= 0"])
|
30
30
|
s.add_development_dependency(%q<sinatra>, [">= 0"])
|
31
31
|
s.add_development_dependency(%q<rspec>, [">= 0"])
|
32
32
|
else
|
33
|
-
s.add_dependency(%q<addressable>, [">= 0"])
|
33
|
+
s.add_dependency(%q<addressable>, [">= 2.1.0"])
|
34
34
|
s.add_dependency(%q<httpauth>, [">= 0"])
|
35
35
|
s.add_dependency(%q<thin>, [">= 0"])
|
36
36
|
s.add_dependency(%q<yard>, [">= 0"])
|
@@ -38,7 +38,7 @@ Gem::Specification.new do |s|
|
|
38
38
|
s.add_dependency(%q<rspec>, [">= 0"])
|
39
39
|
end
|
40
40
|
else
|
41
|
-
s.add_dependency(%q<addressable>, [">= 0"])
|
41
|
+
s.add_dependency(%q<addressable>, [">= 2.1.0"])
|
42
42
|
s.add_dependency(%q<httpauth>, [">= 0"])
|
43
43
|
s.add_dependency(%q<thin>, [">= 0"])
|
44
44
|
s.add_dependency(%q<yard>, [">= 0"])
|