pezra-resourceful 0.5.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ Version 0.6.0
2
+ =============
3
+
4
+ * Improved support for multi-valued header fields. (Peter Williams)
5
+ * Added convenience mechanisms for making URL encoded and multipart form data requests. (Peter Williams)
6
+ * Ruby 1.9 support (Peter Williams)
7
+
8
+ Compatibility issues
9
+ --------------------
10
+
11
+ * The semantics of the Resourceful::Header API have changed slightly.
12
+ Previously, any header might return a string or an array. Now
13
+ fields are either "single-value" and always return a string, or
14
+ "multi-value" and always return an array. See API doc for more
15
+ details.
16
+
17
+
18
+
data/Manifest CHANGED
@@ -1,34 +1,39 @@
1
- lib/resourceful/authentication_manager.rb
2
- lib/resourceful/cache_manager.rb
3
- lib/resourceful/exceptions.rb
4
- lib/resourceful/header.rb
5
- lib/resourceful/http_accessor.rb
6
- lib/resourceful/memcache_cache_manager.rb
7
- lib/resourceful/multipart_form_data.rb
1
+ lib/resourceful.rb
8
2
  lib/resourceful/net_http_adapter.rb
9
3
  lib/resourceful/options_interpretation.rb
10
- lib/resourceful/request.rb
11
- lib/resourceful/resource.rb
12
- lib/resourceful/response.rb
13
4
  lib/resourceful/stubbed_resource_proxy.rb
5
+ lib/resourceful/urlencoded_form_data.rb
6
+ lib/resourceful/header.rb
7
+ lib/resourceful/memcache_cache_manager.rb
8
+ lib/resourceful/response.rb
14
9
  lib/resourceful/util.rb
15
- lib/resourceful.rb
16
- Manifest
10
+ lib/resourceful/abstract_form_data.rb
11
+ lib/resourceful/cache_manager.rb
12
+ lib/resourceful/request.rb
13
+ lib/resourceful/resource.rb
14
+ lib/resourceful/exceptions.rb
15
+ lib/resourceful/multipart_form_data.rb
16
+ lib/resourceful/http_accessor.rb
17
+ lib/resourceful/authentication_manager.rb
18
+ History.txt
19
+ resourceful.gemspec
20
+ README.markdown
17
21
  MIT-LICENSE
18
22
  Rakefile
19
- README.markdown
20
- resourceful.gemspec
23
+ Manifest
24
+ spec/simple_sinatra_server_spec.rb
25
+ spec/old_acceptance_specs.rb
26
+ spec/acceptance_shared_specs.rb
27
+ spec/spec_helper.rb
28
+ spec/simple_sinatra_server.rb
21
29
  spec/acceptance/authorization_spec.rb
22
- spec/acceptance/caching_spec.rb
23
30
  spec/acceptance/header_spec.rb
24
- spec/acceptance/redirecting_spec.rb
25
31
  spec/acceptance/resource_spec.rb
26
- spec/acceptance_shared_specs.rb
27
- spec/caching_spec.rb
28
- spec/old_acceptance_specs.rb
32
+ spec/acceptance/caching_spec.rb
33
+ spec/acceptance/redirecting_spec.rb
29
34
  spec/resourceful/multipart_form_data_spec.rb
35
+ spec/resourceful/header_spec.rb
30
36
  spec/resourceful/resource_spec.rb
31
- spec/simple_sinatra_server.rb
32
- spec/simple_sinatra_server_spec.rb
37
+ spec/resourceful/urlencoded_form_data_spec.rb
38
+ spec/caching_spec.rb
33
39
  spec/spec.opts
34
- spec/spec_helper.rb
@@ -58,8 +58,17 @@ Post a URL encoded form
58
58
 
59
59
  require 'resourceful'
60
60
  http = Resourceful::HttpAccessor.new
61
- resp = http.resource('http://mysite.example/service').
62
- post('hostname=test&level=super', :content_type => 'application/x-www-form-urlencoded')
61
+ resp = http.resource('http://mysite.example/service').
62
+ post(Resourceful::UrlencodedFormData.new(:hostname => 'test', :level => 'super'))
63
+
64
+ Post a Mulitpart form with a file
65
+ -----------------------
66
+
67
+ require 'resourceful'
68
+ http = Resourceful::HttpAccessor.new
69
+ form_data = Resourceful::MultipartFormData.new(:username => 'me')
70
+ form_data.add_file('avatar', '/tmp/my_avatar.png', 'image/png')
71
+ resp = http.resource('http://mysite.example/service').post(form_data)
63
72
 
64
73
  Put an XML document
65
74
  -------------------
@@ -10,9 +10,13 @@ require 'resourceful/util'
10
10
  require 'resourceful/header'
11
11
  require 'resourceful/http_accessor'
12
12
 
13
+ module Resourceful
14
+ autoload :MultipartFormData, 'resourceful/multipart_form_data'
15
+ autoload :UrlencodedFormData, 'resourceful/urlencoded_form_data'
16
+ end
17
+
13
18
  # Resourceful is a library that provides a high level HTTP interface.
14
19
  module Resourceful
15
- VERSION = "0.5.4"
20
+ VERSION = "0.6.0"
16
21
  RESOURCEFUL_USER_AGENT_TOKEN = "Resourceful/#{VERSION}(Ruby/#{RUBY_VERSION})"
17
-
18
22
  end
@@ -0,0 +1,18 @@
1
+ module Resourceful
2
+ class AbstractFormData
3
+ def initialize(contents = {})
4
+ @form_data = []
5
+
6
+ contents.each do |k,v|
7
+ add(k, v)
8
+ end
9
+ end
10
+
11
+ def add(name, value)
12
+ form_data << [name.to_s, value]
13
+ end
14
+
15
+ protected
16
+ attr_reader :form_data
17
+ end
18
+ end
@@ -1,125 +1,256 @@
1
- # A case-normalizing Hash, adjusting on [] and []=.
2
- # Shamelessly swiped from Rack
1
+ require 'resourceful/options_interpretation'
2
+ require 'set'
3
+
4
+ # Represents the header fields of an HTTP message. To access a field
5
+ # you can use `#[]` and `#[]=`. For example, to get the content type
6
+ # of a response you can do
7
+ #
8
+ # response.header['Content-Type'] # => "application/xml"
9
+ #
10
+ # Lookups and modifications done in this way are case insensitive, so
11
+ # 'Content-Type', 'content-type' and :content_type are all equivalent.
12
+ #
13
+ # Multi-valued fields
14
+ # -------------------
15
+ #
16
+ # Multi-value fields (e.g. Accept) are always returned as an Array
17
+ # regardless of the number of values, if the field is present.
18
+ # Single-value fields (e.g. Content-Type) are always returned as
19
+ # strings. The multi/single valueness of a header field is determined
20
+ # by the way it is defined in the HTTP spec. Unknown fields are
21
+ # treated as multi-valued.
22
+ #
23
+ # (This behavior is new in 0.6 and may be slightly incompatible with
24
+ # the way previous versions worked in some situations.)
25
+ #
26
+ # For example
27
+ #
28
+ # h = Resourceful::Header.new
29
+ # h['Accept'] = "application/xml"
30
+ # h['Accept'] # => ["application/xml"]
31
+ #
3
32
  module Resourceful
4
- class Header < Hash
33
+ class Header
34
+ include Enumerable
35
+
5
36
  def initialize(hash={})
37
+ @raw_fields = {}
6
38
  hash.each { |k, v| self[k] = v }
7
39
  end
8
40
 
9
41
  def to_hash
10
- {}.replace(self)
42
+ @raw_fields.dup
11
43
  end
12
44
 
13
45
  def [](k)
14
- super capitalize(k)
46
+ field_def(k).get_from(@raw_fields)
15
47
  end
16
48
 
17
49
  def []=(k, v)
18
- super capitalize(k), v
50
+ field_def(k).set_to(v, @raw_fields)
19
51
  end
20
52
 
21
53
  def has_key?(k)
22
- super capitalize(k)
54
+ field_def(k).exists_in?(@raw_fields)
55
+ end
56
+
57
+ def each(&blk)
58
+ @raw_fields.each(&blk)
59
+ end
60
+ alias each_field each
61
+
62
+ def merge!(another)
63
+ another.each do |k,v|
64
+ self[k] = v
65
+ end
66
+ self
23
67
  end
24
68
 
25
- def capitalize(k)
26
- k.to_s.downcase.gsub(/^.|[-_\s]./) { |x| x.upcase }.gsub('_', '-')
69
+ def merge(another)
70
+ self.class.new(self).merge!(another)
27
71
  end
28
72
 
29
- def each_field(&blk)
30
- to_hash.each { |k,v|
31
- blk.call capitalize(k), v
32
- }
73
+ def reverse_merge(another)
74
+ self.class.new(another).merge!(self)
33
75
  end
34
76
 
35
- HEADERS = %w[
36
- Accept
37
- Accept-Charset
38
- Accept-Encoding
39
- Accept-Language
40
- Accept-Ranges
41
- Age
42
- Allow
43
- Authorization
44
- Cache-Control
45
- Connection
46
- Content-Encoding
47
- Content-Language
48
- Content-Length
49
- Content-Location
50
- Content-MD5
51
- Content-Range
52
- Content-Type
53
- Date
54
- ETag
55
- Expect
56
- Expires
57
- From
58
- Host
59
- If-Match
60
- If-Modified-Since
61
- If-None-Match
62
- If-Range
63
- If-Unmodified-Since
64
- Keep-Alive
65
- Last-Modified
66
- Location
67
- Max-Forwards
68
- Pragma
69
- Proxy-Authenticate
70
- Proxy-Authorization
71
- Range
72
- Referer
73
- Retry-After
74
- Server
75
- TE
76
- Trailer
77
- Transfer-Encoding
78
- Upgrade
79
- User-Agent
80
- Vary
81
- Via
82
- Warning
83
- WWW-Authenticate
84
- ]
85
-
86
- HEADERS.each do |header|
87
- const = header.upcase.gsub('-', '_')
88
- meth = header.downcase.gsub('-', '_')
89
-
90
- class_eval <<-RUBY, __FILE__, __LINE__
91
- #{const} = "#{header}".freeze # ACCEPT = "accept".freeze
92
-
93
- def #{meth} # def accept
94
- self[#{const}] # self[ACCEPT]
95
- end # end
96
-
97
- def #{meth}=(str) # def accept=(str)
98
- self[#{const}] = str # self[ACCEPT] = str
99
- end # end
100
- RUBY
77
+ def dup
78
+ self.class.new(@raw_fields.dup)
79
+ end
80
+
81
+
82
+ # Class to handle the details of each type of field.
83
+ class HeaderFieldDef
84
+ include Comparable
85
+ include OptionsInterpretation
86
+
87
+ ##
88
+ attr_reader :name
89
+
90
+ def initialize(name, options = {})
91
+ @name = name
92
+ extract_opts(options) do |opts|
93
+ @repeatable = opts.extract(:repeatable, :default => false)
94
+ @hop_by_hop = opts.extract(:hop_by_hop, :default => false)
95
+ @modifiable = opts.extract(:modifiable, :default => true)
96
+ end
97
+ end
98
+
99
+ def repeatable?
100
+ @repeatable
101
+ end
102
+
103
+ def hop_by_hop?
104
+ @hop_by_hop
105
+ end
106
+
107
+ def modifiable?
108
+ @modifiable
109
+ end
110
+
111
+ def get_from(raw_fields_hash)
112
+ raw_fields_hash[name]
113
+ end
114
+
115
+ def set_to(value, raw_fields_hash)
116
+ raw_fields_hash[name] = if repeatable?
117
+ Array(value)
118
+ elsif value.kind_of?(Array)
119
+ raise ArgumentError, "#{name} field may only have one value" if value.size > 1
120
+ value.first
121
+ else
122
+ value
123
+ end
124
+ end
125
+
126
+ def exists_in?(raw_fields_hash)
127
+ raw_fields_hash.has_key?(name)
128
+ end
129
+
130
+ def <=>(another)
131
+ name <=> another.name
132
+ end
101
133
 
134
+ def ==(another)
135
+ name_pattern === another.name
136
+ end
137
+ alias eql? ==
138
+
139
+ def ===(another)
140
+ if another.kind_of?(HeaderFieldDef)
141
+ self == another
142
+ else
143
+ name_pattern === another
144
+ end
145
+ end
146
+
147
+ def name_pattern
148
+ Regexp.new('^' + name.gsub('-', '[_-]') + '$', Regexp::IGNORECASE)
149
+ end
150
+
151
+ def methodized_name
152
+ name.downcase.gsub('-', '_')
153
+ end
154
+
155
+ alias to_s name
156
+
157
+ def gen_setter(klass)
158
+ klass.class_eval <<-RUBY
159
+ def #{methodized_name}=(val) # def accept=(val)
160
+ self['#{name}'] = val # self['Accept'] = val
161
+ end # end
162
+ RUBY
163
+ end
164
+
165
+ def gen_getter(klass)
166
+ klass.class_eval <<-RUBY
167
+ def #{methodized_name} # def accept
168
+ self['#{name}'] # self['Accept']
169
+ end # end
170
+ RUBY
171
+ end
172
+
173
+ def gen_canonical_name_const(klass)
174
+ const_name = name.upcase.gsub('-', '_')
175
+
176
+ klass.const_set(const_name, name)
177
+ end
178
+ end
179
+
180
+ @@header_field_defs = Set.new
181
+
182
+ def self.header_field(name, options = {})
183
+ hfd = HeaderFieldDef.new(name, options)
184
+
185
+ @@header_field_defs << hfd
186
+
187
+ hfd.gen_getter(self)
188
+ hfd.gen_setter(self)
189
+ hfd.gen_canonical_name_const(self)
190
+ end
191
+
192
+ def self.hop_by_hop_headers
193
+ @@header_field_defs.select{|hfd| hfd.hop_by_hop?}
194
+ end
195
+
196
+ def self.non_modifiable_headers
197
+ @@header_field_defs.reject{|hfd| hfd.repeatable?}
198
+ end
199
+
200
+ def field_def(name)
201
+ @@header_field_defs.find{|hfd| hfd === name} ||
202
+ HeaderFieldDef.new(name.to_s.downcase.gsub(/^.|[-_\s]./) { |x| x.upcase }.gsub('_', '-'), :repeatable => true)
102
203
  end
103
204
 
104
- HOP_BY_HOP_HEADERS = [
105
- CONNECTION,
106
- KEEP_ALIVE,
107
- PROXY_AUTHENTICATE,
108
- PROXY_AUTHORIZATION,
109
- TE,
110
- TRAILER,
111
- TRANSFER_ENCODING,
112
- UPGRADE
113
- ].freeze
114
-
115
- NON_MODIFIABLE_HEADERS = [
116
- CONTENT_LOCATION,
117
- CONTENT_MD5,
118
- ETAG,
119
- LAST_MODIFIED,
120
- EXPIRES
121
- ].freeze
122
205
 
206
+ header_field('Accept', :repeatable => true)
207
+ header_field('Accept-Charset', :repeatable => true)
208
+ header_field('Accept-Encoding', :repeatable => true)
209
+ header_field('Accept-Language', :repeatable => true)
210
+ header_field('Accept-Ranges', :repeatable => true)
211
+ header_field('Age')
212
+ header_field('Allow', :repeatable => true)
213
+ header_field('Authorization', :repeatable => true)
214
+ header_field('Cache-Control', :repeatable => true)
215
+ header_field('Connection', :hop_by_hop => true)
216
+ header_field('Content-Encoding', :repeatable => true)
217
+ header_field('Content-Language', :repeatable => true)
218
+ header_field('Content-Length')
219
+ header_field('Content-Location', :modifiable => false)
220
+ header_field('Content-MD5', :modifiable => false)
221
+ header_field('Content-Range')
222
+ header_field('Content-Type')
223
+ header_field('Date')
224
+ header_field('ETag', :modifiable => false)
225
+ header_field('Expect', :repeatable => true)
226
+ header_field('Expires', :modifiable => false)
227
+ header_field('From')
228
+ header_field('Host')
229
+ header_field('If-Match', :repeatable => true)
230
+ header_field('If-Modified-Since')
231
+ header_field('If-None-Match', :repeatable => true)
232
+ header_field('If-Range')
233
+ header_field('If-Unmodified-Since')
234
+ header_field('Keep-Alive', :hop_by_hop => true)
235
+ header_field('Last-Modified', :modifiable => false)
236
+ header_field('Location')
237
+ header_field('Max-Forwards')
238
+ header_field('Pragma', :repeatable => true)
239
+ header_field('Proxy-Authenticate', :hop_by_hop => true)
240
+ header_field('Proxy-Authorization', :hop_by_hop => true)
241
+ header_field('Range')
242
+ header_field('Referer')
243
+ header_field('Retry-After')
244
+ header_field('Server')
245
+ header_field('TE', :repeatable => true, :hop_by_hop => true)
246
+ header_field('Trailer', :repeatable => true, :hop_by_hop => true)
247
+ header_field('Transfer-Encoding', :repeatable => true, :hop_by_hop => true)
248
+ header_field('Upgrade', :repeatable => true, :hop_by_hop => true)
249
+ header_field('User-Agent')
250
+ header_field('Vary', :repeatable => true)
251
+ header_field('Via', :repeatable => true)
252
+ header_field('Warning', :repeatable => true)
253
+ header_field('WWW-Authenticate', :repeatable => true)
123
254
  end
124
255
  end
125
256
 
@@ -1,16 +1,9 @@
1
+ require 'resourceful/abstract_form_data'
1
2
 
2
3
  module Resourceful
3
- class MultipartFormData
4
+ class MultipartFormData < AbstractFormData
4
5
  FileParamValue = Struct.new(:content, :file_name, :content_type)
5
6
 
6
- def initialize()
7
- @form_data = []
8
- end
9
-
10
- def add(name, value)
11
- form_data << [name, value]
12
- end
13
-
14
7
  def add_file(name, file_name, content_type="application/octet-stream")
15
8
  add(name, FileParamValue.new(File.new(file_name, 'r'), File.basename(file_name), content_type))
16
9
  end
@@ -21,8 +14,10 @@ module Resourceful
21
14
 
22
15
  def read
23
16
  StringIO.new.tap do |out|
17
+ first = true
24
18
  form_data.each do |key, val|
25
- out << "\r\n--" << boundary
19
+ out << "\r\n" unless first
20
+ out << "--" << boundary
26
21
  out << "\r\nContent-Disposition: form-data; name=\"#{key}\""
27
22
  if val.kind_of?(FileParamValue)
28
23
  out << "; filename=\"#{val.file_name}\""
@@ -34,13 +29,13 @@ module Resourceful
34
29
  else
35
30
  out << val.to_s
36
31
  end
32
+ first = false
37
33
  end
38
34
  out << "\r\n--#{boundary}--"
39
35
  end.string
40
36
  end
41
37
 
42
38
  protected
43
- attr_reader :form_data
44
39
 
45
40
  def boundary
46
41
  @boundary ||= (0..30).map{BOUNDARY_CHARS[rand(BOUNDARY_CHARS.length)]}.join
@@ -30,15 +30,21 @@ module Resourceful
30
30
  def make_request(method, uri, body = nil, header = nil)
31
31
  uri = uri.is_a?(Addressable::URI) ? uri : Addressable::URI.parse(uri)
32
32
 
33
+ if [:put, :post].include? method
34
+ body = body ? body.read : ""
35
+ header[:content_length] = body.size
36
+ end
37
+
33
38
  req = net_http_request_class(method).new(uri.absolute_path)
34
39
  header.each_field { |k,v| req[k] = v } if header
35
40
  https = ("https" == uri.scheme)
36
- conn = Net::HTTP.Proxy(*proxy_details).new(uri.host, uri.port || (https ? 443 : 80))
41
+ conn_class = proxy_details ? Net::HTTP.Proxy(*proxy_details) : Net::HTTP
42
+ conn = conn_class.new(uri.host, uri.port || (https ? 443 : 80))
37
43
  conn.use_ssl = https
38
44
  begin
39
45
  conn.start
40
46
  res = if body
41
- conn.request(req, body.read)
47
+ conn.request(req, body)
42
48
  else
43
49
  conn.request(req)
44
50
  end
@@ -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 || header.cache_control && cc.include?('no-cache')
208
+ if max_age == 0 || skip_cache?
209
209
  logger.info(" Client forced revalidation")
210
210
  true
211
211
  else
@@ -30,7 +30,7 @@ module Resourceful
30
30
  alias uri effective_uri
31
31
 
32
32
  def default_header(temp_defaults = {})
33
- temp_defaults.merge(@default_header)
33
+ @default_header.merge(temp_defaults)
34
34
  end
35
35
 
36
36
  # Returns the host for this Resource's current uri
@@ -139,14 +139,14 @@ module Resourceful
139
139
 
140
140
  # Ensures that the request has a content type header
141
141
  def ensure_content_type(body, header)
142
- return if header.has_key?(:content_type)
142
+ return if header.has_key?('Content-Type')
143
143
 
144
144
  if body.respond_to?(:content_type)
145
- header[:content_type] = body.content_type
145
+ header['Content-Type'] = body.content_type
146
146
  return
147
147
  end
148
148
 
149
- return if default_header.has_key?(:content_type)
149
+ return if default_header.has_key?('Content-Type')
150
150
 
151
151
  # could not figure it out
152
152
  raise MissingContentType
@@ -154,12 +154,16 @@ module Resourceful
154
154
 
155
155
  # Actually make the request
156
156
  def request(method, data, header)
157
+ header = default_header.merge(header)
157
158
  ensure_content_type(data, header) if data
158
159
 
159
160
  data = StringIO.new(data) if data.kind_of?(String)
160
161
 
161
- log_request_with_time "#{method.to_s.upcase} [#{uri}]" do
162
- request = Request.new(method, self, data, default_header.merge(header))
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)
163
167
  request.fetch_response
164
168
  end
165
169
  end
@@ -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['Expire']
30
- return true if Time.httpdate(header['Expire'].first) < Time.now
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'] ? header['Age'].first.to_i : 0
79
- date_value = Time.httpdate(header['Date'].first)
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'] && header['Content-Encoding'].first
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
@@ -2,26 +2,25 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{resourceful}
5
- s.version = "0.5.4"
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-07}
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/authentication_manager.rb", "lib/resourceful/cache_manager.rb", "lib/resourceful/exceptions.rb", "lib/resourceful/header.rb", "lib/resourceful/http_accessor.rb", "lib/resourceful/memcache_cache_manager.rb", "lib/resourceful/multipart_form_data.rb", "lib/resourceful/net_http_adapter.rb", "lib/resourceful/options_interpretation.rb", "lib/resourceful/request.rb", "lib/resourceful/resource.rb", "lib/resourceful/response.rb", "lib/resourceful/stubbed_resource_proxy.rb", "lib/resourceful/util.rb", "lib/resourceful.rb", "README.markdown"]
13
- s.files = ["lib/resourceful/authentication_manager.rb", "lib/resourceful/cache_manager.rb", "lib/resourceful/exceptions.rb", "lib/resourceful/header.rb", "lib/resourceful/http_accessor.rb", "lib/resourceful/memcache_cache_manager.rb", "lib/resourceful/multipart_form_data.rb", "lib/resourceful/net_http_adapter.rb", "lib/resourceful/options_interpretation.rb", "lib/resourceful/request.rb", "lib/resourceful/resource.rb", "lib/resourceful/response.rb", "lib/resourceful/stubbed_resource_proxy.rb", "lib/resourceful/util.rb", "lib/resourceful.rb", "Manifest", "MIT-LICENSE", "Rakefile", "README.markdown", "resourceful.gemspec", "spec/acceptance/authorization_spec.rb", "spec/acceptance/caching_spec.rb", "spec/acceptance/header_spec.rb", "spec/acceptance/redirecting_spec.rb", "spec/acceptance/resource_spec.rb", "spec/acceptance_shared_specs.rb", "spec/caching_spec.rb", "spec/old_acceptance_specs.rb", "spec/resourceful/multipart_form_data_spec.rb", "spec/resourceful/resource_spec.rb", "spec/simple_sinatra_server.rb", "spec/simple_sinatra_server_spec.rb", "spec/spec.opts", "spec/spec_helper.rb"]
14
- s.has_rdoc = true
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"]
15
14
  s.homepage = %q{http://github.com/paul/resourceful}
16
15
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Resourceful", "--main", "README.markdown"]
17
- s.require_paths = ["lib", "ext"]
16
+ s.require_paths = ["lib"]
18
17
  s.rubyforge_project = %q{resourceful}
19
- s.rubygems_version = %q{1.3.1}
18
+ s.rubygems_version = %q{1.3.5}
20
19
  s.summary = %q{An HTTP library for Ruby that takes advantage of everything HTTP has to offer.}
21
20
 
22
21
  if s.respond_to? :specification_version then
23
22
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
- s.specification_version = 2
23
+ s.specification_version = 3
25
24
 
26
25
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
26
  s.add_runtime_dependency(%q<addressable>, [">= 2.1.0"])
@@ -104,7 +104,7 @@ describe Resourceful do
104
104
 
105
105
  it 'should revalidate the cached response if the response is expired' do
106
106
  in_the_past = (Time.now - 60).httpdate
107
- resource = @http.resource(uri_for_code(200, "Expire" => in_the_past))
107
+ resource = @http.resource(uri_for_code(200, "Expires" => in_the_past))
108
108
 
109
109
  resp = resource.get
110
110
  resp.should be_expired
@@ -7,12 +7,12 @@ describe Resourceful do
7
7
  describe "working with a resource" do
8
8
  before do
9
9
  @http = Resourceful::HttpAccessor.new
10
- @resource = @http.resource('http://localhost:3000/')
10
+ @resource = @http.resource('http://localhost:42682/')
11
11
  end
12
12
 
13
13
  it 'should make the original uri available' do
14
- @resource.effective_uri.should == 'http://localhost:3000/'
15
- @resource.uri.should == 'http://localhost:3000/'
14
+ @resource.effective_uri.should == 'http://localhost:42682/'
15
+ @resource.uri.should == 'http://localhost:42682/'
16
16
  end
17
17
 
18
18
  it 'should set the user agent string on the default header' do
@@ -0,0 +1,8 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper.rb"
2
+
3
+
4
+ describe Resourceful::Header do
5
+ it "should have constants for header names" do
6
+ Resourceful::Header::CONTENT_TYPE.should == 'Content-Type'
7
+ end
8
+ end
@@ -29,7 +29,6 @@ describe Resourceful::MultipartFormData do
29
29
 
30
30
  boundary = /boundary=(\w+)/.match(@form_data.content_type)[1]
31
31
  @form_data.read.should eql(<<MPFD[0..-2])
32
- \r
33
32
  --#{boundary}\r
34
33
  Content-Disposition: form-data; name="foo"\r
35
34
  \r
@@ -62,7 +61,6 @@ MPFD
62
61
 
63
62
  boundary = /boundary=(\w+)/.match(@form_data.content_type)[1]
64
63
  @form_data.read.should eql(<<MPFD[0..-2])
65
- \r
66
64
  --#{boundary}\r
67
65
  Content-Disposition: form-data; name="foo"; filename="#{File.basename(file_to_upload.path)}"\r
68
66
  Content-Type: application/octet-stream\r
@@ -0,0 +1,44 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+ require 'tempfile'
3
+ require "resourceful/urlencoded_form_data.rb"
4
+
5
+ describe Resourceful::UrlencodedFormData do
6
+
7
+ before do
8
+ @form_data = Resourceful::UrlencodedFormData.new
9
+ end
10
+
11
+ it "should know its content-type" do
12
+ @form_data.content_type.should match(/^application\/x-www-form-urlencoded$/i)
13
+ end
14
+
15
+ describe "instantiation" do
16
+ it "should be creatable with hash" do
17
+ Resourceful::UrlencodedFormData.new(:foo => 'testing').read.should eql("foo=testing")
18
+ end
19
+ end
20
+
21
+ describe "with simple parameters" do
22
+ it "should all simple parameters to be added" do
23
+ @form_data.add(:foo, "testing")
24
+ end
25
+
26
+ it "should render a multipart form-data document when #read is called" do
27
+ @form_data.add('foo', 'bar')
28
+ @form_data.add('baz', 'this')
29
+
30
+ @form_data.read.should eql("foo=bar&baz=this")
31
+ end
32
+
33
+ it "should escape character in values that are unsafe" do
34
+ @form_data.add('foo', 'this & that')
35
+
36
+ @form_data.read.should eql("foo=this+%26+that")
37
+ end
38
+
39
+ it "should escape character in names that are unsafe" do
40
+ @form_data.add('foo=bar', 'this')
41
+ @form_data.read.should eql("foo%3Dbar=this")
42
+ end
43
+ end
44
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pezra-resourceful
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Sadauskas
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-07 00:00:00 -07:00
12
+ date: 2009-08-14 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -79,58 +79,65 @@ executables: []
79
79
  extensions: []
80
80
 
81
81
  extra_rdoc_files:
82
- - lib/resourceful/authentication_manager.rb
83
- - lib/resourceful/cache_manager.rb
84
- - lib/resourceful/exceptions.rb
85
- - lib/resourceful/header.rb
86
- - lib/resourceful/http_accessor.rb
87
- - lib/resourceful/memcache_cache_manager.rb
88
- - lib/resourceful/multipart_form_data.rb
82
+ - lib/resourceful.rb
89
83
  - lib/resourceful/net_http_adapter.rb
90
84
  - lib/resourceful/options_interpretation.rb
91
- - lib/resourceful/request.rb
92
- - lib/resourceful/resource.rb
93
- - lib/resourceful/response.rb
94
85
  - lib/resourceful/stubbed_resource_proxy.rb
86
+ - lib/resourceful/urlencoded_form_data.rb
87
+ - lib/resourceful/header.rb
88
+ - lib/resourceful/memcache_cache_manager.rb
89
+ - lib/resourceful/response.rb
95
90
  - lib/resourceful/util.rb
96
- - lib/resourceful.rb
97
- - README.markdown
98
- files:
99
- - lib/resourceful/authentication_manager.rb
91
+ - lib/resourceful/abstract_form_data.rb
100
92
  - lib/resourceful/cache_manager.rb
93
+ - lib/resourceful/request.rb
94
+ - lib/resourceful/resource.rb
101
95
  - lib/resourceful/exceptions.rb
102
- - lib/resourceful/header.rb
103
- - lib/resourceful/http_accessor.rb
104
- - lib/resourceful/memcache_cache_manager.rb
105
96
  - lib/resourceful/multipart_form_data.rb
97
+ - lib/resourceful/http_accessor.rb
98
+ - lib/resourceful/authentication_manager.rb
99
+ - README.markdown
100
+ files:
101
+ - lib/resourceful.rb
106
102
  - lib/resourceful/net_http_adapter.rb
107
103
  - lib/resourceful/options_interpretation.rb
108
- - lib/resourceful/request.rb
109
- - lib/resourceful/resource.rb
110
- - lib/resourceful/response.rb
111
104
  - lib/resourceful/stubbed_resource_proxy.rb
105
+ - lib/resourceful/urlencoded_form_data.rb
106
+ - lib/resourceful/header.rb
107
+ - lib/resourceful/memcache_cache_manager.rb
108
+ - lib/resourceful/response.rb
112
109
  - lib/resourceful/util.rb
113
- - lib/resourceful.rb
114
- - Manifest
110
+ - lib/resourceful/abstract_form_data.rb
111
+ - lib/resourceful/cache_manager.rb
112
+ - lib/resourceful/request.rb
113
+ - lib/resourceful/resource.rb
114
+ - lib/resourceful/exceptions.rb
115
+ - lib/resourceful/multipart_form_data.rb
116
+ - lib/resourceful/http_accessor.rb
117
+ - lib/resourceful/authentication_manager.rb
118
+ - History.txt
119
+ - resourceful.gemspec
120
+ - README.markdown
115
121
  - MIT-LICENSE
116
122
  - Rakefile
117
- - README.markdown
118
- - resourceful.gemspec
123
+ - Manifest
124
+ - spec/simple_sinatra_server_spec.rb
125
+ - spec/old_acceptance_specs.rb
126
+ - spec/acceptance_shared_specs.rb
127
+ - spec/spec_helper.rb
128
+ - spec/simple_sinatra_server.rb
119
129
  - spec/acceptance/authorization_spec.rb
120
- - spec/acceptance/caching_spec.rb
121
130
  - spec/acceptance/header_spec.rb
122
- - spec/acceptance/redirecting_spec.rb
123
131
  - spec/acceptance/resource_spec.rb
124
- - spec/acceptance_shared_specs.rb
125
- - spec/caching_spec.rb
126
- - spec/old_acceptance_specs.rb
132
+ - spec/acceptance/caching_spec.rb
133
+ - spec/acceptance/redirecting_spec.rb
127
134
  - spec/resourceful/multipart_form_data_spec.rb
135
+ - spec/resourceful/header_spec.rb
128
136
  - spec/resourceful/resource_spec.rb
129
- - spec/simple_sinatra_server.rb
130
- - spec/simple_sinatra_server_spec.rb
137
+ - spec/resourceful/urlencoded_form_data_spec.rb
138
+ - spec/caching_spec.rb
131
139
  - spec/spec.opts
132
- - spec/spec_helper.rb
133
- has_rdoc: true
140
+ has_rdoc: false
134
141
  homepage: http://github.com/paul/resourceful
135
142
  licenses:
136
143
  post_install_message:
@@ -143,7 +150,6 @@ rdoc_options:
143
150
  - README.markdown
144
151
  require_paths:
145
152
  - lib
146
- - ext
147
153
  required_ruby_version: !ruby/object:Gem::Requirement
148
154
  requirements:
149
155
  - - ">="
@@ -161,7 +167,7 @@ requirements: []
161
167
  rubyforge_project: resourceful
162
168
  rubygems_version: 1.3.5
163
169
  signing_key:
164
- specification_version: 2
170
+ specification_version: 3
165
171
  summary: An HTTP library for Ruby that takes advantage of everything HTTP has to offer.
166
172
  test_files: []
167
173