rest-client-next 1.1.0 → 1.3.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.
@@ -1,48 +1,64 @@
1
1
  module RestClient
2
- module Mixin
3
- module Response
4
- attr_reader :net_http_res
2
+ module Mixin
3
+ module Response
4
+ attr_reader :net_http_res
5
5
 
6
- # HTTP status code, always 200 since RestClient throws exceptions for
7
- # other codes.
8
- def code
9
- @code ||= @net_http_res.code.to_i
10
- end
6
+ # HTTP status code
7
+ def code
8
+ @code ||= @net_http_res.code.to_i
9
+ end
11
10
 
12
- # A hash of the headers, beautified with symbols and underscores.
13
- # e.g. "Content-type" will become :content_type.
14
- def headers
15
- @headers ||= self.class.beautify_headers(@net_http_res.to_hash)
16
- end
11
+ # A hash of the headers, beautified with symbols and underscores.
12
+ # e.g. "Content-type" will become :content_type.
13
+ def headers
14
+ @headers ||= self.class.beautify_headers(@net_http_res.to_hash)
15
+ end
17
16
 
18
- # The raw headers.
19
- def raw_headers
20
- @raw_headers ||= @net_http_res.to_hash
21
- end
17
+ # The raw headers.
18
+ def raw_headers
19
+ @raw_headers ||= @net_http_res.to_hash
20
+ end
22
21
 
23
- # Hash of cookies extracted from response headers
24
- def cookies
25
- @cookies ||= (self.headers[:set_cookie] || "").split('; ').inject({}) do |out, raw_c|
26
- key, val = raw_c.split('=')
27
- unless %w(expires domain path secure).member?(key)
28
- out[key] = val
29
- end
30
- out
31
- end
32
- end
22
+ # Hash of cookies extracted from response headers
23
+ def cookies
24
+ @cookies ||= (self.headers[:set_cookie] || []).inject({}) do |out, cookie_content|
25
+ # correctly parse comma-separated cookies containing HTTP dates (which also contain a comma)
26
+ cookie_content.split(/,\s*/).inject([""]) { |array, blob|
27
+ blob =~ /expires=.+?$/ ? array.push(blob) : array.last.concat(blob)
28
+ array
29
+ }.each do |cookie|
30
+ next if cookie.empty?
31
+ key, *val = cookie.split(";").first.split("=")
32
+ out[key] = val.join("=")
33
+ end
34
+ out
35
+ end
36
+ end
33
37
 
34
- def self.included(receiver)
35
- receiver.extend(RestClient::Mixin::Response::ClassMethods)
36
- end
38
+ # Return the default behavior corresponding to the response code:
39
+ # the response itself for code in 200..206 and an exception in other cases
40
+ def return!
41
+ if (200..206).include? code
42
+ self
43
+ elsif Exceptions::EXCEPTIONS_MAP[code]
44
+ raise Exceptions::EXCEPTIONS_MAP[code], self
45
+ else
46
+ raise RequestFailed, self
47
+ end
48
+ end
37
49
 
38
- module ClassMethods
39
- def beautify_headers(headers)
40
- headers.inject({}) do |out, (key, value)|
41
- out[key.gsub(/-/, '_').downcase.to_sym] = value.first
42
- out
43
- end
44
- end
45
- end
46
- end
47
- end
50
+ def self.included(receiver)
51
+ receiver.extend(RestClient::Mixin::Response::ClassMethods)
52
+ end
53
+
54
+ module ClassMethods
55
+ def beautify_headers(headers)
56
+ headers.inject({}) do |out, (key, value)|
57
+ out[key.gsub(/-/, '_').downcase.to_sym] = %w{set-cookie}.include?(key.downcase) ? value : value.first
58
+ out
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
48
64
  end
@@ -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,178 @@
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
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
+
48
+ alias :to_s :read
49
+
50
+ def escape(v)
51
+ URI.escape(v.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
52
+ end
53
+
54
+ # Flatten parameters by converting hashes of hashes to flat hashes
55
+ # {keys1 => {keys2 => value}} will be transformed into {keys1[key2] => value}
56
+ def flatten_params(params, parent_key = nil)
57
+ result = {}
58
+ params.keys.map do |key|
59
+ calculated_key = parent_key ? "#{parent_key}[#{escape key}]" : escape(key)
60
+ value = params[key]
61
+ if value.is_a? Hash
62
+ result.merge!(flatten_params(value, calculated_key))
63
+ else
64
+ result[calculated_key] = value
65
+ end
66
+ end
67
+ result
68
+ end
69
+
70
+ def headers
71
+ { 'Content-Length' => size.to_s }
72
+ end
73
+
74
+ def size
75
+ @stream.size
76
+ end
77
+
78
+ alias :length :size
79
+
80
+ def close
81
+ @stream.close
82
+ end
83
+
84
+ def inspect
85
+ result = to_s.inspect
86
+ @stream.seek(0)
87
+ result
88
+ end
89
+
90
+ def short_inspect
91
+ (size > 100 ? "#{size} byte length" : inspect)
92
+ end
93
+
94
+ end
95
+
96
+ class UrlEncoded < Base
97
+ def build_stream(params = nil)
98
+ @stream = StringIO.new(flatten_params(params).map do |k, v|
99
+ "#{k}=#{escape(v)}"
100
+ end.join("&"))
101
+ @stream.seek(0)
102
+ end
103
+
104
+ def headers
105
+ super.merge({ 'Content-Type' => 'application/x-www-form-urlencoded' })
106
+ end
107
+ end
108
+
109
+ class Multipart < Base
110
+ EOL = "\r\n"
111
+
112
+ def build_stream(params)
113
+ b = "--#{boundary}"
114
+
115
+ @stream = Tempfile.new("RESTClient.Stream.#{rand(1000)}")
116
+ @stream.write(b + EOL)
117
+
118
+ if params.is_a? Hash
119
+ x = flatten_params(params).to_a
120
+ else
121
+ x = params.to_a
122
+ end
123
+
124
+ last_index = x.length - 1
125
+ x.each_with_index do |a, index|
126
+ k, v = *a
127
+ if v.respond_to?(:read) && v.respond_to?(:path)
128
+ create_file_field(@stream, k, v)
129
+ else
130
+ create_regular_field(@stream, k, v)
131
+ end
132
+ @stream.write(EOL + b)
133
+ @stream.write(EOL) unless last_index == index
134
+ end
135
+ @stream.write('--')
136
+ @stream.write(EOL)
137
+ @stream.seek(0)
138
+ end
139
+
140
+ def create_regular_field(s, k, v)
141
+ s.write("Content-Disposition: form-data; name=\"#{k}\"")
142
+ s.write(EOL)
143
+ s.write(EOL)
144
+ s.write(v)
145
+ end
146
+
147
+ def create_file_field(s, k, v)
148
+ begin
149
+ s.write("Content-Disposition: form-data; name=\"#{k}\"; filename=\"#{v.respond_to?(:original_filename) ? v.original_filename : File.basename(v.path)}\"#{EOL}")
150
+ s.write("Content-Type: #{v.respond_to?(:content_type) ? v.content_type : mime_for(v.path)}#{EOL}")
151
+ s.write(EOL)
152
+ while data = v.read(8124)
153
+ s.write(data)
154
+ end
155
+ ensure
156
+ v.close
157
+ end
158
+ end
159
+
160
+ def mime_for(path)
161
+ mime = MIME::Types.type_for path
162
+ mime.empty? ? 'text/plain' : mime[0].content_type
163
+ end
164
+
165
+ def boundary
166
+ @boundary ||= rand(1_000_000).to_s
167
+ end
168
+
169
+ def headers
170
+ super.merge({'Content-Type' => %Q{multipart/form-data; boundary="#{boundary}"}})
171
+ end
172
+
173
+ def close
174
+ @stream.close
175
+ end
176
+ end
177
+ end
171
178
  end