rest-client 1.1.0 → 1.6.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

@@ -6,16 +6,16 @@
6
6
  # http://www.missiondata.com/blog/ruby/29/streaming-data-to-s3-with-ruby/
7
7
 
8
8
  module Net
9
- class HTTP
10
- alias __request__ request
9
+ class HTTP
10
+ alias __request__ request
11
11
 
12
- def request(req, body=nil, &block)
13
- if body != nil && body.respond_to?(:read)
14
- req.body_stream = body
15
- return __request__(req, nil, &block)
16
- else
17
- return __request__(req, body, &block)
18
- end
19
- end
20
- end
12
+ def request(req, body=nil, &block)
13
+ if body != nil && body.respond_to?(:read)
14
+ req.body_stream = body
15
+ return __request__(req, nil, &block)
16
+ else
17
+ return __request__(req, body, &block)
18
+ end
19
+ end
20
+ end
21
21
  end
@@ -1,171 +1,220 @@
1
- require "tempfile"
2
- require "stringio"
3
- require "mime/types"
1
+ require 'tempfile'
2
+ require 'stringio'
3
+ require 'mime/types'
4
4
 
5
5
  module RestClient
6
- module Payload
7
- extend self
8
-
9
- def generate(params)
10
- if params.is_a?(String)
11
- Base.new(params)
12
- elsif params
13
- if params.delete(:multipart) == true || has_file?(params)
14
- Multipart.new(params)
15
- else
16
- UrlEncoded.new(params)
17
- end
18
- else
19
- nil
20
- end
21
- end
22
-
23
- def has_file?(params)
24
- params.any? do |_, v|
25
- case v
26
- when Hash
27
- has_file?(v)
28
- else
29
- v.respond_to?(:path) && v.respond_to?(:read)
30
- end
31
- end
32
- end
33
-
34
- class Base
35
- def initialize(params)
36
- build_stream(params)
37
- end
38
-
39
- def build_stream(params)
40
- @stream = StringIO.new(params)
41
- @stream.seek(0)
42
- end
43
-
44
- def read(bytes=nil)
45
- @stream.read(bytes)
46
- end
47
- alias :to_s :read
48
-
49
- def escape(v)
50
- URI.escape(v.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
51
- end
52
-
53
- # Flatten parameters by converting hashes of hashes to flat hashes
54
- # {keys1 => {keys2 => value}} will be transformed into {keys1[key2] => value}
55
- def flatten_params(params, parent_key = nil)
56
- result = {}
57
- params.keys.map do |key|
58
- calculated_key = parent_key ? "#{parent_key}[#{escape key}]" : escape(key)
59
- value = params[key]
60
- if value.is_a? Hash
61
- result.merge!(flatten_params(value, calculated_key))
62
- else
63
- result[calculated_key] = value
64
- end
65
- end
66
- result
67
- end
68
-
69
- def headers
70
- { 'Content-Length' => size.to_s }
71
- end
72
-
73
- def size
74
- @stream.size
75
- end
76
- alias :length :size
77
-
78
- def close
79
- @stream.close
80
- end
81
-
82
- def inspect
83
- result = to_s.inspect
84
- @stream.seek(0)
85
- result
86
- end
87
- end
88
-
89
- class UrlEncoded < Base
90
- def build_stream(params = nil)
91
- @stream = StringIO.new(flatten_params(params).map do |k,v|
92
- "#{k}=#{escape(v)}"
93
- end.join("&"))
94
- @stream.seek(0)
95
- end
96
-
97
- def headers
98
- super.merge({ 'Content-Type' => 'application/x-www-form-urlencoded' })
99
- end
100
- end
101
-
102
- class Multipart < Base
103
- EOL = "\r\n"
104
-
105
- def build_stream(params)
106
- b = "--#{boundary}"
107
-
108
- @stream = Tempfile.new("RESTClient.Stream.#{rand(1000)}")
109
- @stream.write(b + EOL)
110
-
111
- if params.is_a? Hash
112
- x = flatten_params(params).to_a
113
- else
114
- x = params.to_a
115
- end
116
-
117
- last_index = x.length - 1
118
- x.each_with_index do |a, index|
119
- k, v = *a
120
- if v.respond_to?(:read) && v.respond_to?(:path)
121
- create_file_field(@stream, k,v)
122
- else
123
- create_regular_field(@stream, k,v)
124
- end
125
- @stream.write(EOL + b)
126
- @stream.write(EOL) unless last_index == index
127
- end
128
- @stream.write('--')
129
- @stream.write(EOL)
130
- @stream.seek(0)
131
- end
132
-
133
- def create_regular_field(s, k, v)
134
- s.write("Content-Disposition: multipart/form-data; name=\"#{k}\"")
135
- s.write(EOL)
136
- s.write(EOL)
137
- s.write(v)
138
- end
139
-
140
- def create_file_field(s, k, v)
141
- begin
142
- s.write("Content-Disposition: multipart/form-data; name=\"#{k}\"; filename=\"#{v.respond_to?(:original_filename) ? v.original_filename : File.basename(v.path)}\"#{EOL}")
143
- s.write("Content-Type: #{v.respond_to?(:content_type) ? v.content_type : mime_for(v.path)}#{EOL}")
144
- s.write(EOL)
145
- while data = v.read(8124)
146
- s.write(data)
147
- end
148
- ensure
149
- v.close
150
- end
151
- end
152
-
153
- def mime_for(path)
154
- mime = MIME::Types.type_for path
155
- mime.empty? ? 'text/plain' : mime[0].content_type
156
- end
157
-
158
- def boundary
159
- @boundary ||= rand(1_000_000).to_s
160
- end
161
-
162
- def headers
163
- super.merge({'Content-Type' => %Q{multipart/form-data; boundary="#{boundary}"}})
164
- end
165
-
166
- def close
167
- @stream.close
168
- end
169
- end
170
- end
6
+ module Payload
7
+ extend self
8
+
9
+ def generate(params)
10
+ if params.is_a?(String)
11
+ Base.new(params)
12
+ elsif params.respond_to?(:read)
13
+ Streamed.new(params)
14
+ elsif params
15
+ if params.delete(:multipart) == true || has_file?(params)
16
+ Multipart.new(params)
17
+ else
18
+ UrlEncoded.new(params)
19
+ end
20
+ else
21
+ nil
22
+ end
23
+ end
24
+
25
+ def has_file?(params)
26
+ params.any? do |_, v|
27
+ case v
28
+ when Hash
29
+ has_file?(v)
30
+ else
31
+ v.respond_to?(:path) && v.respond_to?(:read)
32
+ end
33
+ end
34
+ end
35
+
36
+ class Base
37
+ def initialize(params)
38
+ build_stream(params)
39
+ end
40
+
41
+ def build_stream(params)
42
+ @stream = StringIO.new(params)
43
+ @stream.seek(0)
44
+ end
45
+
46
+ def read(bytes=nil)
47
+ @stream.read(bytes)
48
+ end
49
+
50
+ alias :to_s :read
51
+
52
+ # Flatten parameters by converting hashes of hashes to flat hashes
53
+ # {keys1 => {keys2 => value}} will be transformed into [keys1[key2], value]
54
+ def flatten_params(params, parent_key = nil)
55
+ result = []
56
+ params.each do |key, value|
57
+ calculated_key = parent_key ? "#{parent_key}[#{handle_key(key)}]" : handle_key(key)
58
+ if value.is_a? Hash
59
+ result += flatten_params(value, calculated_key)
60
+ elsif value.is_a? Array
61
+ result += flatten_params_array(value, calculated_key)
62
+ else
63
+ result << [calculated_key, value]
64
+ end
65
+ end
66
+ result
67
+ end
68
+
69
+ def flatten_params_array value, calculated_key
70
+ result = []
71
+ value.each do |elem|
72
+ if elem.is_a? Hash
73
+ result += flatten_params(elem, calculated_key)
74
+ elsif elem.is_a? Array
75
+ result += flatten_params_array(elem, calculated_key)
76
+ else
77
+ result << ["#{calculated_key}[]", elem]
78
+ end
79
+ end
80
+ result
81
+ end
82
+
83
+ def headers
84
+ {'Content-Length' => size.to_s}
85
+ end
86
+
87
+ def size
88
+ @stream.size
89
+ end
90
+
91
+ alias :length :size
92
+
93
+ def close
94
+ @stream.close
95
+ end
96
+
97
+ def inspect
98
+ result = to_s.inspect
99
+ @stream.seek(0)
100
+ result
101
+ end
102
+
103
+ def short_inspect
104
+ (size > 500 ? "#{size} byte(s) length" : inspect)
105
+ end
106
+
107
+ end
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
+
125
+ class UrlEncoded < Base
126
+ def build_stream(params = nil)
127
+ @stream = StringIO.new(flatten_params(params).collect do |entry|
128
+ "#{entry[0]}=#{handle_key(entry[1])}"
129
+ end.join("&"))
130
+ @stream.seek(0)
131
+ end
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
+
138
+ def headers
139
+ super.merge({'Content-Type' => 'application/x-www-form-urlencoded'})
140
+ end
141
+ end
142
+
143
+ class Multipart < Base
144
+ EOL = "\r\n"
145
+
146
+ def build_stream(params)
147
+ b = "--#{boundary}"
148
+
149
+ @stream = Tempfile.new("RESTClient.Stream.#{rand(1000)}")
150
+ @stream.binmode
151
+ @stream.write(b + EOL)
152
+
153
+ if params.is_a? Hash
154
+ x = flatten_params(params)
155
+ else
156
+ x = params
157
+ end
158
+
159
+ last_index = x.length - 1
160
+ x.each_with_index do |a, index|
161
+ k, v = * a
162
+ if v.respond_to?(:read) && v.respond_to?(:path)
163
+ create_file_field(@stream, k, v)
164
+ else
165
+ create_regular_field(@stream, k, v)
166
+ end
167
+ @stream.write(EOL + b)
168
+ @stream.write(EOL) unless last_index == index
169
+ end
170
+ @stream.write('--')
171
+ @stream.write(EOL)
172
+ @stream.seek(0)
173
+ end
174
+
175
+ def create_regular_field(s, k, v)
176
+ s.write("Content-Disposition: form-data; name=\"#{k}\"")
177
+ s.write(EOL)
178
+ s.write(EOL)
179
+ s.write(v)
180
+ end
181
+
182
+ def create_file_field(s, k, v)
183
+ begin
184
+ s.write("Content-Disposition: form-data;")
185
+ s.write(" name=\"#{k}\";") unless (k.nil? || k=='')
186
+ s.write(" filename=\"#{v.respond_to?(:original_filename) ? v.original_filename : File.basename(v.path)}\"#{EOL}")
187
+ s.write("Content-Type: #{v.respond_to?(:content_type) ? v.content_type : mime_for(v.path)}#{EOL}")
188
+ s.write(EOL)
189
+ while data = v.read(8124)
190
+ s.write(data)
191
+ end
192
+ ensure
193
+ v.close if v.respond_to?(:close)
194
+ end
195
+ end
196
+
197
+ def mime_for(path)
198
+ mime = MIME::Types.type_for path
199
+ mime.empty? ? 'text/plain' : mime[0].content_type
200
+ end
201
+
202
+ def boundary
203
+ @boundary ||= rand(1_000_000).to_s
204
+ end
205
+
206
+ # for Multipart do not escape the keys
207
+ def handle_key key
208
+ key
209
+ end
210
+
211
+ def headers
212
+ super.merge({'Content-Type' => %Q{multipart/form-data; boundary=#{boundary}}})
213
+ end
214
+
215
+ def close
216
+ @stream.close!
217
+ end
218
+ end
219
+ end
171
220
  end
@@ -1,30 +1,34 @@
1
- require File.dirname(__FILE__) + '/mixin/response'
2
-
3
1
  module RestClient
4
- # The response from RestClient on a raw request looks like a string, but is
5
- # actually one of these. 99% of the time you're making a rest call all you
6
- # care about is the body, but on the occassion you want to fetch the
7
- # headers you can:
8
- #
9
- # RestClient.get('http://example.com').headers[:content_type]
10
- #
11
- # In addition, if you do not use the response as a string, you can access
12
- # a Tempfile object at res.file, which contains the path to the raw
13
- # downloaded request body.
14
- class RawResponse
15
- include RestClient::Mixin::Response
2
+ # The response from RestClient on a raw request looks like a string, but is
3
+ # actually one of these. 99% of the time you're making a rest call all you
4
+ # care about is the body, but on the occassion you want to fetch the
5
+ # headers you can:
6
+ #
7
+ # RestClient.get('http://example.com').headers[:content_type]
8
+ #
9
+ # In addition, if you do not use the response as a string, you can access
10
+ # a Tempfile object at res.file, which contains the path to the raw
11
+ # downloaded request body.
12
+ class RawResponse
13
+
14
+ include AbstractResponse
15
+
16
+ attr_reader :file
16
17
 
17
- attr_reader :file
18
+ def initialize tempfile, net_http_res, args
19
+ @net_http_res = net_http_res
20
+ @args = args
21
+ @file = tempfile
22
+ end
18
23
 
19
- def initialize(tempfile, net_http_res)
20
- @net_http_res = net_http_res
21
- @file = tempfile
22
- end
24
+ def to_s
25
+ @file.open
26
+ @file.read
27
+ end
23
28
 
24
- def to_s
25
- @file.open
26
- @file.read
27
- end
29
+ def size
30
+ File.size file
31
+ end
28
32
 
29
- end
33
+ end
30
34
  end