rest-client 1.5.1 → 1.6.0.a

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.

Potentially problematic release.


This version of rest-client might be problematic. Click here for more details.

@@ -13,7 +13,9 @@ of specifying actions: get, put, post, delete.
13
13
 
14
14
  RestClient.get 'http://example.com/resource'
15
15
 
16
- RestClient.get 'https://user:password@example.com/private/resource'
16
+ RestClient.get 'http://example.com/resource', {:params => {:id => 50, 'foo' => 'bar'}}
17
+
18
+ RestClient.get 'https://user:password@example.com/private/resource', {:accept => :json}
17
19
 
18
20
  RestClient.post 'http://example.com/resource', :param1 => 'one', :nested => { :param2 => 'two' }
19
21
 
@@ -77,8 +79,8 @@ See RestClient::Resource docs for details.
77
79
 
78
80
  == Exceptions (see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
79
81
 
80
- * for results code between 200 and 206 a RestClient::Response will be returned
81
- * for results code 301 and 302 the redirection will be followed if the request is a get or a head
82
+ * for results code between 200 and 207 a RestClient::Response will be returned
83
+ * for results code 301, 302 or 307 the redirection will be followed if the request is a get or a head
82
84
  * for result code 303 the redirection will be followed and the request transformed into a get
83
85
  * for other cases a RestClient::Exception holding the Response will be raised, a specific exception class will be thrown for know error codes
84
86
 
@@ -98,11 +100,11 @@ A block can be passed to the RestClient method, this block will then be called w
98
100
  Response.return! can be called to invoke the default response's behavior.
99
101
 
100
102
  # Don't raise exceptions but return the response
101
- RestClient.get('http://example.com/resource'){|response| response }
103
+ RestClient.get('http://example.com/resource'){|response, request| response }
102
104
  ➔ 404 Resource Not Found | text/html 282 bytes
103
105
 
104
106
  # Manage a specific error code
105
- RestClient.get('http://my-rest-service.com/resource'){ |response, &block|
107
+ RestClient.get('http://my-rest-service.com/resource'){ |response, request, &block|
106
108
  case response.code
107
109
  when 200
108
110
  p "It worked !"
@@ -110,19 +112,19 @@ Response.return! can be called to invoke the default response's behavior.
110
112
  when 423
111
113
  raise SomeCustomExceptionIfYouWant
112
114
  else
113
- response.return! &block
115
+ response.return!(request, &block)
114
116
  end
115
117
  }
116
118
 
117
119
  # Follow redirections for all request types and not only for get and head
118
- # RFC : "If the 301 (or 302) status code is received in response to a request other than GET or HEAD,
120
+ # RFC : "If the 301, 302 or 307 status code is received in response to a request other than GET or HEAD,
119
121
  # the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user,
120
122
  # since this might change the conditions under which the request was issued."
121
- RestClient.get('http://my-rest-service.com/resource'){ |response, &block|
122
- if [301, 302].include? response.code
123
- response.follow_redirection &block
123
+ RestClient.get('http://my-rest-service.com/resource'){ |response, request, &block|
124
+ if [301, 302, 307].include? response.code
125
+ response.follow_redirection(request, &block)
124
126
  else
125
- response.return! &block
127
+ response.return!(request, &block)
126
128
  end
127
129
  }
128
130
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.5.1
1
+ 1.6.0.a
data/history.md CHANGED
@@ -1,3 +1,15 @@
1
+ # 1.6.0
2
+
3
+ - forgot to include rest-client.rb in the gem
4
+ - user, password and user-defined headers should survive a redirect
5
+ - added all missing status codes
6
+ - added parameter passing for get request using the :param key in header
7
+ - the warning about the logger when using a string was a bad idea
8
+ - multipart parameters names should not be escaped
9
+ - remove the cookie escaping introduced by migrating to CGI cookie parsing in 1.5.1
10
+ - add a streamed payload type (patch provided by Caleb Land)
11
+ - Exception#http_body works even when no response
12
+
1
13
  # 1.5.1
2
14
 
3
15
  - only converts headers keys which are Symbols
@@ -0,0 +1,2 @@
1
+ # More logical way to require 'rest-client'
2
+ require File.dirname(__FILE__) + '/restclient'
@@ -92,9 +92,6 @@ module RestClient
92
92
  # Value should be a logger but can can be stdout, stderr, or a filename.
93
93
  # You can also configure logging by the environment variable RESTCLIENT_LOG.
94
94
  def self.log= log
95
- if log.is_a? String
96
- warn "[warning] You should set the log with a logger"
97
- end
98
95
  @@log = create_log log
99
96
  end
100
97
 
@@ -27,7 +27,7 @@ module RestClient
27
27
  @cookies ||= (self.headers[:set_cookie] || {}).inject({}) do |out, cookie_content|
28
28
  CGI::Cookie::parse(cookie_content).each do |key, cookie|
29
29
  unless ['expires', 'path'].include? key
30
- out[key] = cookie.value[0] || ''
30
+ out[CGI::escape(key)] = cookie.value[0] ? (CGI::escape(cookie.value[0]) || '') : ''
31
31
  end
32
32
  end
33
33
  out
@@ -35,20 +35,20 @@ module RestClient
35
35
  end
36
36
 
37
37
  # Return the default behavior corresponding to the response code:
38
- # the response itself for code in 200..206, redirection for 301 and 302 in get and head cases, redirection for 303 and an exception in other cases
39
- def return! &block
40
- if (200..206).include? code
38
+ # the response itself for code in 200..206, redirection for 301, 302 and 307 in get and head cases, redirection for 303 and an exception in other cases
39
+ def return! request = nil, &block
40
+ if (200..207).include? code
41
41
  self
42
- elsif [301, 302].include? code
42
+ elsif [301, 302, 307].include? code
43
43
  unless [:get, :head].include? args[:method]
44
44
  raise Exceptions::EXCEPTIONS_MAP[code], self
45
45
  else
46
- follow_redirection(&block)
46
+ follow_redirection(request, &block)
47
47
  end
48
48
  elsif code == 303
49
49
  args[:method] = :get
50
50
  args.delete :payload
51
- follow_redirection(&block)
51
+ follow_redirection(request, &block)
52
52
  elsif Exceptions::EXCEPTIONS_MAP[code]
53
53
  raise Exceptions::EXCEPTIONS_MAP[code], self
54
54
  else
@@ -65,18 +65,23 @@ module RestClient
65
65
  end
66
66
 
67
67
  # Follow a redirection
68
- def follow_redirection &block
68
+ def follow_redirection request = nil, &block
69
69
  url = headers[:location]
70
70
  if url !~ /^http/
71
71
  url = URI.parse(args[:url]).merge(url).to_s
72
72
  end
73
73
  args[:url] = url
74
+ if request
75
+ args[:password] = request.password
76
+ args[:user] = request.user
77
+ args[:headers] = request.headers
78
+ end
74
79
  Request.execute args, &block
75
80
  end
76
81
 
77
82
  def AbstractResponse.beautify_headers(headers)
78
83
  headers.inject({}) do |out, (key, value)|
79
- out[key.gsub(/-/, '_').downcase.to_sym] = %w{set-cookie}.include?(key.downcase) ? value : value.first
84
+ out[key.gsub(/-/, '_').downcase.to_sym] = %w{ set-cookie }.include?(key.downcase) ? value : value.first
80
85
  out
81
86
  end
82
87
  end
@@ -2,21 +2,29 @@ module RestClient
2
2
 
3
3
  STATUSES = {100 => 'Continue',
4
4
  101 => 'Switching Protocols',
5
+ 102 => 'Processing', #WebDAV
6
+
5
7
  200 => 'OK',
6
8
  201 => 'Created',
7
9
  202 => 'Accepted',
8
- 203 => 'Non-Authoritative Information',
10
+ 203 => 'Non-Authoritative Information', # http/1.1
9
11
  204 => 'No Content',
10
12
  205 => 'Reset Content',
11
13
  206 => 'Partial Content',
14
+ 207 => 'Multi-Status', #WebDAV
15
+
12
16
  300 => 'Multiple Choices',
13
17
  301 => 'Moved Permanently',
14
18
  302 => 'Found',
15
- 303 => 'See Other',
19
+ 303 => 'See Other', # http/1.1
16
20
  304 => 'Not Modified',
17
- 305 => 'Use Proxy',
21
+ 305 => 'Use Proxy', # http/1.1
22
+ 306 => 'Switch Proxy', # no longer used
23
+ 307 => 'Temporary Redirect', # http/1.1
24
+
18
25
  400 => 'Bad Request',
19
26
  401 => 'Unauthorized',
27
+ 402 => 'Payment Required',
20
28
  403 => 'Forbidden',
21
29
  404 => 'Resource Not Found',
22
30
  405 => 'Method Not Allowed',
@@ -32,12 +40,26 @@ module RestClient
32
40
  415 => 'Unsupported Media Type',
33
41
  416 => 'Requested Range Not Satisfiable',
34
42
  417 => 'Expectation Failed',
43
+ 418 => 'I\'m A Teapot',
44
+ 421 => 'Too Many Connections From This IP',
45
+ 422 => 'Unprocessable Entity', #WebDAV
46
+ 423 => 'Locked', #WebDAV
47
+ 424 => 'Failed Dependency', #WebDAV
48
+ 425 => 'Unordered Collection', #WebDAV
49
+ 426 => 'Upgrade Required',
50
+ 449 => 'Retry With', #Microsoft
51
+ 450 => 'Blocked By Windows Parental Controls', #Microsoft
52
+
35
53
  500 => 'Internal Server Error',
36
54
  501 => 'Not Implemented',
37
55
  502 => 'Bad Gateway',
38
56
  503 => 'Service Unavailable',
39
57
  504 => 'Gateway Timeout',
40
- 505 => 'HTTP Version Not Supported'}
58
+ 505 => 'HTTP Version Not Supported',
59
+ 506 => 'Variant Also Negotiates',
60
+ 507 => 'Insufficient Storage', #WebDAV
61
+ 509 => 'Bandwidth Limit Exceeded', #Apache
62
+ 510 => 'Not Extended'}
41
63
 
42
64
  # Compatibility : make the Response act like a Net::HTTPResponse when needed
43
65
  module ResponseForException
@@ -73,7 +95,7 @@ module RestClient
73
95
  end
74
96
 
75
97
  def http_body
76
- @response.body
98
+ @response.body if @response
77
99
  end
78
100
 
79
101
  def inspect
@@ -111,7 +133,7 @@ module RestClient
111
133
  klass = Class.new(superclass) do
112
134
  send(:define_method, :message) {message}
113
135
  end
114
- klass_constant = const_set message.gsub(/ /, '').gsub(/-/, ''), klass
136
+ klass_constant = const_set message.delete(' \-\''), klass
115
137
  Exceptions::EXCEPTIONS_MAP[code] = klass_constant
116
138
  end
117
139
 
@@ -9,6 +9,8 @@ module RestClient
9
9
  def generate(params)
10
10
  if params.is_a?(String)
11
11
  Base.new(params)
12
+ elsif params.respond_to?(:read)
13
+ Streamed.new(params)
12
14
  elsif params
13
15
  if params.delete(:multipart) == true || has_file?(params)
14
16
  Multipart.new(params)
@@ -47,16 +49,12 @@ module RestClient
47
49
 
48
50
  alias :to_s :read
49
51
 
50
- def escape(v)
51
- URI.escape(v.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
52
- end
53
-
54
52
  # Flatten parameters by converting hashes of hashes to flat hashes
55
53
  # {keys1 => {keys2 => value}} will be transformed into [keys1[key2], value]
56
54
  def flatten_params(params, parent_key = nil)
57
55
  result = []
58
56
  params.each do |key, value|
59
- calculated_key = parent_key ? "#{parent_key}[#{escape key}]" : escape(key)
57
+ calculated_key = parent_key ? "#{parent_key}[#{handle_key(key)}]" : handle_key(key)
60
58
  if value.is_a? Hash
61
59
  result += flatten_params(value, calculated_key)
62
60
  elsif value.is_a? Array
@@ -83,7 +81,7 @@ module RestClient
83
81
  end
84
82
 
85
83
  def headers
86
- { 'Content-Length' => size.to_s }
84
+ {'Content-Length' => size.to_s}
87
85
  end
88
86
 
89
87
  def size
@@ -108,16 +106,37 @@ module RestClient
108
106
 
109
107
  end
110
108
 
109
+ class Streamed < Base
110
+ def build_stream(params = nil)
111
+ @stream = params
112
+ end
113
+
114
+ def size
115
+ if @stream.respond_to?(:size)
116
+ @stream.size
117
+ elsif @stream.is_a?(IO)
118
+ @stream.stat.size
119
+ end
120
+ end
121
+
122
+ alias :length :size
123
+ end
124
+
111
125
  class UrlEncoded < Base
112
126
  def build_stream(params = nil)
113
127
  @stream = StringIO.new(flatten_params(params).collect do |entry|
114
- "#{entry[0]}=#{escape(entry[1])}"
128
+ "#{entry[0]}=#{handle_key(entry[1])}"
115
129
  end.join("&"))
116
130
  @stream.seek(0)
117
131
  end
118
132
 
133
+ # for UrlEncoded escape the keys
134
+ def handle_key key
135
+ URI.escape(key.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
136
+ end
137
+
119
138
  def headers
120
- super.merge({ 'Content-Type' => 'application/x-www-form-urlencoded' })
139
+ super.merge({'Content-Type' => 'application/x-www-form-urlencoded'})
121
140
  end
122
141
  end
123
142
 
@@ -139,7 +158,7 @@ module RestClient
139
158
 
140
159
  last_index = x.length - 1
141
160
  x.each_with_index do |a, index|
142
- k, v = *a
161
+ k, v = * a
143
162
  if v.respond_to?(:read) && v.respond_to?(:path)
144
163
  create_file_field(@stream, k, v)
145
164
  else
@@ -184,6 +203,11 @@ module RestClient
184
203
  @boundary ||= rand(1_000_000).to_s
185
204
  end
186
205
 
206
+ # for Multipart do not escape the keys
207
+ def handle_key key
208
+ key
209
+ end
210
+
187
211
  def headers
188
212
  super.merge({'Content-Type' => %Q{multipart/form-data; boundary=#{boundary}}})
189
213
  end
@@ -27,14 +27,18 @@ module RestClient
27
27
  :open_timeout, :raw_response, :verify_ssl, :ssl_client_cert,
28
28
  :ssl_client_key, :ssl_ca_file, :processed_headers, :args
29
29
 
30
- def self.execute(args, &block)
31
- new(args).execute(&block)
30
+ def self.execute(args, & block)
31
+ new(args).execute(& block)
32
32
  end
33
33
 
34
34
  def initialize args
35
35
  @method = args[:method] or raise ArgumentError, "must pass :method"
36
- @url = args[:url] or raise ArgumentError, "must pass :url"
37
36
  @headers = args[:headers] || {}
37
+ if args[:url]
38
+ @url = process_get_params(args[:url], headers)
39
+ else
40
+ raise ArgumentError, "must pass :url"
41
+ end
38
42
  @cookies = @headers.delete(:cookies) || args[:cookies] || {}
39
43
  @payload = Payload.generate(args[:payload])
40
44
  @user = args[:user]
@@ -51,14 +55,37 @@ module RestClient
51
55
  @args = args
52
56
  end
53
57
 
54
- def execute &block
58
+ def execute & block
55
59
  uri = parse_url_with_auth(url)
56
- transmit uri, net_http_request_class(method).new(uri.request_uri, processed_headers), payload, &block
60
+ transmit uri, net_http_request_class(method).new(uri.request_uri, processed_headers), payload, & block
61
+ end
62
+
63
+ # Extract the query parameters for get request and append them to the url
64
+ def process_get_params url, headers
65
+ if method == :get
66
+ get_params = {}
67
+ headers.delete_if do |key, value|
68
+ if 'params' == key.to_s.downcase && value.is_a?(Hash)
69
+ get_params.merge! value
70
+ true
71
+ else
72
+ false
73
+ end
74
+ end
75
+ unless get_params.empty?
76
+ query_string = get_params.collect { |k, v| "#{k.to_s}=#{CGI::escape(v.to_s)}" }.join('&')
77
+ url + "?#{query_string}"
78
+ else
79
+ url
80
+ end
81
+ else
82
+ url
83
+ end
57
84
  end
58
85
 
59
86
  def make_headers user_headers
60
87
  unless @cookies.empty?
61
- user_headers[:cookie] = @cookies.map {|(key, val)| "#{key.to_s}=#{val}" }.sort.join(';')
88
+ user_headers[:cookie] = @cookies.map { |(key, val)| "#{key.to_s}=#{CGI::unescape(val)}" }.sort.join(';')
62
89
  end
63
90
  headers = stringify_headers(default_headers).merge(stringify_headers(user_headers))
64
91
  headers.merge!(@payload.headers) if @payload
@@ -107,7 +134,7 @@ module RestClient
107
134
  end
108
135
  end
109
136
 
110
- def transmit uri, req, payload, &block
137
+ def transmit uri, req, payload, & block
111
138
  setup_credentials req
112
139
 
113
140
  net = net_http_class.new(uri.host, uri.port)
@@ -139,7 +166,7 @@ module RestClient
139
166
  net.start do |http|
140
167
  res = http.request(req, payload) { |http_response| fetch_body(http_response) }
141
168
  log_response res
142
- process_result res, &block
169
+ process_result res, & block
143
170
  end
144
171
  rescue EOFError
145
172
  raise RestClient::ServerBrokeConnection
@@ -179,7 +206,7 @@ module RestClient
179
206
  http_response
180
207
  end
181
208
 
182
- def process_result res, &block
209
+ def process_result res, & block
183
210
  if @raw_response
184
211
  # We don't decode raw requests
185
212
  response = RawResponse.new(@tf, res, args)
@@ -188,9 +215,9 @@ module RestClient
188
215
  end
189
216
 
190
217
  if block_given?
191
- block.call response, &block
218
+ block.call(response, self, & block)
192
219
  else
193
- response.return!(&block)
220
+ response.return!(self, & block)
194
221
  end
195
222
 
196
223
  end
@@ -212,7 +239,7 @@ module RestClient
212
239
  out = []
213
240
  out << "RestClient.#{method} #{url.inspect}"
214
241
  out << payload.short_inspect if payload
215
- out << processed_headers.to_a.sort.map{|(k,v)| [k.inspect, v.inspect].join("=>")}.join(", ")
242
+ out << processed_headers.to_a.sort.map { |(k, v)| [k.inspect, v.inspect].join("=>") }.join(", ")
216
243
  RestClient.log << out.join(', ') + "\n"
217
244
  end
218
245
  end
@@ -228,7 +255,7 @@ module RestClient
228
255
  def stringify_headers headers
229
256
  headers.inject({}) do |result, (key, value)|
230
257
  if key.is_a? Symbol
231
- key = key.to_s.split(/_/).map{|w| w.capitalize}.join('-')
258
+ key = key.to_s.split(/_/).map { |w| w.capitalize }.join('-')
232
259
  end
233
260
  if 'CONTENT-TYPE' == key.upcase
234
261
  target_value = value.to_s
@@ -240,7 +267,7 @@ module RestClient
240
267
  else
241
268
  target_values = value.to_s.split ','
242
269
  end
243
- result[key] = target_values.map{ |ext| MIME::Types.type_for_extension(ext.to_s.strip)}.join(', ')
270
+ result[key] = target_values.map { |ext| MIME::Types.type_for_extension(ext.to_s.strip) }.join(', ')
244
271
  else
245
272
  result[key] = value.to_s
246
273
  end
@@ -249,7 +276,7 @@ module RestClient
249
276
  end
250
277
 
251
278
  def default_headers
252
- { :accept => '*/*; q=0.5, application/xml', :accept_encoding => 'gzip, deflate' }
279
+ {:accept => '*/*; q=0.5, application/xml', :accept_encoding => 'gzip, deflate'}
253
280
  end
254
281
 
255
282
  end
@@ -53,7 +53,12 @@ describe RestClient::AbstractResponse do
53
53
 
54
54
  it "extract strange cookies" do
55
55
  @net_http_res.should_receive(:to_hash).and_return('set-cookie' => ['session_id=ZJ/HQVH6YE+rVkTpn0zvTQ==; path=/'])
56
- @response.cookies.should == { 'session_id' => 'ZJ/HQVH6YE rVkTpn0zvTQ==' }
56
+ @response.cookies.should == { 'session_id' => 'ZJ%2FHQVH6YE+rVkTpn0zvTQ%3D%3D' }
57
+ end
58
+
59
+ it "doesn't escape cookies" do
60
+ @net_http_res.should_receive(:to_hash).and_return('set-cookie' => ['session_id=BAh7BzoNYXBwX25hbWUiEGFwcGxpY2F0aW9uOgpsb2dpbiIKYWRtaW4%3D%0A--08114ba654f17c04d20dcc5228ec672508f738ca; path=/'])
61
+ @response.cookies.should == { 'session_id' => 'BAh7BzoNYXBwX25hbWUiEGFwcGxpY2F0aW9uOgpsb2dpbiIKYWRtaW4%3D%0A--08114ba654f17c04d20dcc5228ec672508f738ca' }
57
62
  end
58
63
 
59
64
  it "can access the net http result directly" do
@@ -14,6 +14,11 @@ describe RestClient::Payload do
14
14
  RestClient::Payload::UrlEncoded.new({:foo => 'bar', :baz => 'qux'}).to_s)
15
15
  end
16
16
 
17
+ it "should escape parameters" do
18
+ RestClient::Payload::UrlEncoded.new({'foo ' => 'bar'}).to_s.
19
+ should == "foo%20=bar"
20
+ end
21
+
17
22
  it "should properly handle hashes as parameter" do
18
23
  RestClient::Payload::UrlEncoded.new({:foo => {:bar => 'baz' }}).to_s.
19
24
  should == "foo[bar]=baz"
@@ -74,6 +79,17 @@ bar\r
74
79
  EOS
75
80
  end
76
81
 
82
+ it "should not escape parameters names" do
83
+ m = RestClient::Payload::Multipart.new([["bar ", "baz"]])
84
+ m.to_s.should == <<-EOS
85
+ --#{m.boundary}\r
86
+ Content-Disposition: form-data; name="bar "\r
87
+ \r
88
+ baz\r
89
+ --#{m.boundary}--\r
90
+ EOS
91
+ end
92
+
77
93
  it "should form properly separated multipart data" do
78
94
  f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
79
95
  m = RestClient::Payload::Multipart.new({:foo => f})
@@ -141,6 +157,33 @@ Content-Type: text/plain\r
141
157
 
142
158
  end
143
159
 
160
+ context "streamed payloads" do
161
+ it "should properly determine the size of file payloads" do
162
+ f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
163
+ payload = RestClient::Payload.generate(f)
164
+ payload.size.should == 22_545
165
+ payload.length.should == 22_545
166
+ end
167
+
168
+ it "should properly determine the size of other kinds of streaming payloads" do
169
+ s = StringIO.new 'foo'
170
+ payload = RestClient::Payload.generate(s)
171
+ payload.size.should == 3
172
+ payload.length.should == 3
173
+
174
+ begin
175
+ f = Tempfile.new "rest-client"
176
+ f.write 'foo bar'
177
+
178
+ payload = RestClient::Payload.generate(f)
179
+ payload.size.should == 7
180
+ payload.length.should == 7
181
+ ensure
182
+ f.close
183
+ end
184
+ end
185
+ end
186
+
144
187
  context "Payload generation" do
145
188
  it "should recognize standard urlencoded params" do
146
189
  RestClient::Payload.generate({"foo" => 'bar'}).should be_kind_of(RestClient::Payload::UrlEncoded)
@@ -164,5 +207,13 @@ Content-Type: text/plain\r
164
207
  RestClient::Payload.generate({"foo" => {"file" => f}}).should be_kind_of(RestClient::Payload::Multipart)
165
208
  end
166
209
 
210
+ it "should recognize file payloads that can be streamed" do
211
+ f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
212
+ RestClient::Payload.generate(f).should be_kind_of(RestClient::Payload::Streamed)
213
+ end
214
+
215
+ it "should recognize other payloads that can be streamed" do
216
+ RestClient::Payload.generate(StringIO.new('foo')).should be_kind_of(RestClient::Payload::Streamed)
217
+ end
167
218
  end
168
219
  end
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+
3
+ require 'webmock/rspec'
4
+ include WebMock
5
+
6
+ describe RestClient::Request do
7
+
8
+ it "manage params for get requests" do
9
+ stub_request(:get, 'http://some/resource?a=b&c=d').with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'Foo'=>'bar'}).to_return(:body => 'foo', :status => 200)
10
+ RestClient::Request.execute(:url => 'http://some/resource', :method => :get, :headers => {:foo => :bar, :params => {:a => :b, 'c' => 'd'}}).body.should == 'foo'
11
+
12
+ stub_request(:get, 'http://some/resource').with(:headers => {'Accept'=>'*/*; q=0.5, application/xml', 'Accept-Encoding'=>'gzip, deflate', 'Foo'=>'bar', 'params' => 'a'}).to_return(:body => 'foo', :status => 200)
13
+ RestClient::Request.execute(:url => 'http://some/resource', :method => :get, :headers => {:foo => :bar, :params => :a}).body.should == 'foo'
14
+ end
15
+
16
+ end
17
+
@@ -59,7 +59,7 @@ describe RestClient::Request do
59
59
  end
60
60
 
61
61
  it "doesn't classify successful requests as failed" do
62
- 203.upto(206) do |code|
62
+ 203.upto(207) do |code|
63
63
  res = mock("result")
64
64
  res.stub!(:code).and_return(code.to_s)
65
65
  res.stub!(:body).and_return("")
@@ -276,7 +276,7 @@ describe RestClient::Request do
276
276
  describe "block usage" do
277
277
  it "returns what asked to" do
278
278
  res = mock('response', :code => '401', :[] => ['content-encoding' => ''], :body => '' )
279
- @request.process_result(res){|response| "foo"}.should == "foo"
279
+ @request.process_result(res){|response, request| "foo"}.should == "foo"
280
280
  end
281
281
  end
282
282
 
@@ -5,32 +5,32 @@ include WebMock
5
5
 
6
6
  describe RestClient::Resource do
7
7
  before do
8
- @resource = RestClient::Resource.new('http://some/resource', :user => 'jane', :password => 'mypass', :headers => { 'X-Something' => '1'})
8
+ @resource = RestClient::Resource.new('http://some/resource', :user => 'jane', :password => 'mypass', :headers => {'X-Something' => '1'})
9
9
  end
10
10
 
11
11
  context "Resource delegation" do
12
12
  it "GET" do
13
- RestClient::Request.should_receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => { 'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
13
+ RestClient::Request.should_receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
14
14
  @resource.get
15
15
  end
16
16
 
17
17
  it "POST" do
18
- RestClient::Request.should_receive(:execute).with(:method => :post, :url => 'http://some/resource', :payload => 'abc', :headers => { :content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
18
+ RestClient::Request.should_receive(:execute).with(:method => :post, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
19
19
  @resource.post 'abc', :content_type => 'image/jpg'
20
20
  end
21
21
 
22
22
  it "PUT" do
23
- RestClient::Request.should_receive(:execute).with(:method => :put, :url => 'http://some/resource', :payload => 'abc', :headers => { :content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
23
+ RestClient::Request.should_receive(:execute).with(:method => :put, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
24
24
  @resource.put 'abc', :content_type => 'image/jpg'
25
25
  end
26
26
 
27
27
  it "DELETE" do
28
- RestClient::Request.should_receive(:execute).with(:method => :delete, :url => 'http://some/resource', :headers => { 'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
28
+ RestClient::Request.should_receive(:execute).with(:method => :delete, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass')
29
29
  @resource.delete
30
30
  end
31
31
 
32
32
  it "overrides resource headers" do
33
- RestClient::Request.should_receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => { 'X-Something' => '2'}, :user => 'jane', :password => 'mypass')
33
+ RestClient::Request.should_receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {'X-Something' => '2'}, :user => 'jane', :password => 'mypass')
34
34
  @resource.get 'X-Something' => '2'
35
35
  end
36
36
  end
@@ -79,20 +79,20 @@ describe RestClient::Resource do
79
79
  describe 'block' do
80
80
  it 'can use block when creating the resource' do
81
81
  stub_request(:get, 'www.example.com').to_return(:body => '', :status => 404)
82
- resource = RestClient::Resource.new('www.example.com'){|response| 'foo'}
82
+ resource = RestClient::Resource.new('www.example.com') { |response, request| 'foo' }
83
83
  resource.get.should == 'foo'
84
84
  end
85
85
 
86
86
  it 'can use block when executing the resource' do
87
87
  stub_request(:get, 'www.example.com').to_return(:body => '', :status => 404)
88
88
  resource = RestClient::Resource.new('www.example.com')
89
- resource.get{|response| 'foo'}.should == 'foo'
89
+ resource.get { |response, request| 'foo' }.should == 'foo'
90
90
  end
91
91
 
92
92
  it 'execution block override resource block' do
93
93
  stub_request(:get, 'www.example.com').to_return(:body => '', :status => 404)
94
- resource = RestClient::Resource.new('www.example.com'){|response| 'foo'}
95
- resource.get{|response| 'bar'}.should == 'bar'
94
+ resource = RestClient::Resource.new('www.example.com') { |response, request| 'foo' }
95
+ resource.get { |response, request| 'bar' }.should == 'bar'
96
96
  end
97
97
 
98
98
  end
@@ -6,6 +6,7 @@ include WebMock
6
6
  describe RestClient::Response do
7
7
  before do
8
8
  @net_http_res = mock('net http response', :to_hash => {"Status" => ["200 OK"]}, :code => 200)
9
+ @request = mock('http request', :user => nil, :password => nil)
9
10
  @response = RestClient::Response.create('abc', @net_http_res, {})
10
11
  end
11
12
 
@@ -59,13 +60,13 @@ describe RestClient::Response do
59
60
  (200..206).each do |code|
60
61
  net_http_res = mock('net http response', :code => '200')
61
62
  response = RestClient::Response.create('abc', net_http_res, {})
62
- response.return!
63
+ response.return! @request
63
64
  end
64
65
  end
65
66
 
66
67
  it "should throw an exception for other codes" do
67
68
  RestClient::Exceptions::EXCEPTIONS_MAP.each_key do |code|
68
- unless (200..206).include? code
69
+ unless (200..207).include? code
69
70
  net_http_res = mock('net http response', :code => code.to_i)
70
71
  response = RestClient::Response.create('abc', net_http_res, {})
71
72
  lambda { response.return!}.should raise_error
@@ -83,16 +84,34 @@ describe RestClient::Response do
83
84
  RestClient::Request.execute(:url => 'http://some/resource', :method => :get).body.should == 'Foo'
84
85
  end
85
86
 
86
- it "doesn't follow a redirection when the request is a post" do
87
+ it "follows a redirection and keep the parameters" do
88
+ stub_request(:get, 'http://foo:bar@some/resource').with(:headers => {'Accept' => 'application/json'}).to_return(:body => '', :status => 301, :headers => {'Location' => 'http://new/resource'})
89
+ stub_request(:get, 'http://foo:bar@new/resource').with(:headers => {'Accept' => 'application/json'}).to_return(:body => 'Foo')
90
+ RestClient::Request.execute(:url => 'http://some/resource', :method => :get, :user => 'foo', :password => 'bar', :headers => {:accept => :json}).body.should == 'Foo'
91
+ end
92
+
93
+ it "doesn't follow a 301 when the request is a post" do
87
94
  net_http_res = mock('net http response', :code => 301)
88
95
  response = RestClient::Response.create('abc', net_http_res, {:method => :post})
89
- lambda { response.return!}.should raise_error(RestClient::MovedPermanently)
96
+ lambda { response.return!(@request)}.should raise_error(RestClient::MovedPermanently)
97
+ end
98
+
99
+ it "doesn't follow a 302 when the request is a post" do
100
+ net_http_res = mock('net http response', :code => 302)
101
+ response = RestClient::Response.create('abc', net_http_res, {:method => :post})
102
+ lambda { response.return!(@request)}.should raise_error(RestClient::Found)
103
+ end
104
+
105
+ it "doesn't follow a 307 when the request is a post" do
106
+ net_http_res = mock('net http response', :code => 307)
107
+ response = RestClient::Response.create('abc', net_http_res, {:method => :post})
108
+ lambda { response.return!(@request)}.should raise_error(RestClient::TemporaryRedirect)
90
109
  end
91
110
 
92
111
  it "doesn't follow a redirection when the request is a put" do
93
112
  net_http_res = mock('net http response', :code => 301)
94
113
  response = RestClient::Response.create('abc', net_http_res, {:method => :put})
95
- lambda { response.return!}.should raise_error(RestClient::MovedPermanently)
114
+ lambda { response.return!(@request)}.should raise_error(RestClient::MovedPermanently)
96
115
  end
97
116
 
98
117
  it "follows a redirection when the request is a post and result is a 303" do
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rest-client
3
3
  version: !ruby/object:Gem::Version
4
- hash: 1
5
- prerelease: false
4
+ hash: 10
5
+ prerelease: true
6
6
  segments:
7
7
  - 1
8
- - 5
9
- - 1
10
- version: 1.5.1
8
+ - 6
9
+ - 0
10
+ - a
11
+ version: 1.6.0.a
11
12
  platform: ruby
12
13
  authors:
13
14
  - Adam Wiggins
@@ -16,7 +17,7 @@ autorequire:
16
17
  bindir: bin
17
18
  cert_chain: []
18
19
 
19
- date: 2010-03-13 00:00:00 +01:00
20
+ date: 2010-06-28 00:00:00 +02:00
20
21
  default_executable: restclient
21
22
  dependencies:
22
23
  - !ruby/object:Gem::Dependency
@@ -49,6 +50,7 @@ files:
49
50
  - VERSION
50
51
  - bin/restclient
51
52
  - lib/rest_client.rb
53
+ - lib/rest-client.rb
52
54
  - lib/restclient.rb
53
55
  - lib/restclient/exceptions.rb
54
56
  - lib/restclient/abstract_response.rb
@@ -66,6 +68,7 @@ files:
66
68
  - spec/payload_spec.rb
67
69
  - spec/raw_response_spec.rb
68
70
  - spec/request_spec.rb
71
+ - spec/request2_spec.rb
69
72
  - spec/resource_spec.rb
70
73
  - spec/response_spec.rb
71
74
  - spec/restclient_spec.rb
@@ -115,6 +118,7 @@ test_files:
115
118
  - spec/payload_spec.rb
116
119
  - spec/raw_response_spec.rb
117
120
  - spec/request_spec.rb
121
+ - spec/request2_spec.rb
118
122
  - spec/resource_spec.rb
119
123
  - spec/response_spec.rb
120
124
  - spec/restclient_spec.rb