httpserious 0.13.5.lstoll1

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.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rubocop.yml +92 -0
  4. data/.rubocop_todo.yml +124 -0
  5. data/.simplecov +1 -0
  6. data/.travis.yml +7 -0
  7. data/CONTRIBUTING.md +23 -0
  8. data/Gemfile +19 -0
  9. data/Guardfile +16 -0
  10. data/History +370 -0
  11. data/MIT-LICENSE +20 -0
  12. data/README.md +78 -0
  13. data/Rakefile +10 -0
  14. data/bin/httparty +116 -0
  15. data/cucumber.yml +1 -0
  16. data/examples/README.md +67 -0
  17. data/examples/aaws.rb +32 -0
  18. data/examples/basic.rb +28 -0
  19. data/examples/crack.rb +19 -0
  20. data/examples/custom_parsers.rb +64 -0
  21. data/examples/delicious.rb +37 -0
  22. data/examples/google.rb +16 -0
  23. data/examples/headers_and_user_agents.rb +6 -0
  24. data/examples/logging.rb +36 -0
  25. data/examples/nokogiri_html_parser.rb +19 -0
  26. data/examples/rescue_json.rb +17 -0
  27. data/examples/rubyurl.rb +14 -0
  28. data/examples/stackexchange.rb +24 -0
  29. data/examples/tripit_sign_in.rb +33 -0
  30. data/examples/twitter.rb +31 -0
  31. data/examples/whoismyrep.rb +10 -0
  32. data/features/basic_authentication.feature +20 -0
  33. data/features/command_line.feature +90 -0
  34. data/features/deals_with_http_error_codes.feature +26 -0
  35. data/features/digest_authentication.feature +20 -0
  36. data/features/handles_compressed_responses.feature +27 -0
  37. data/features/handles_multiple_formats.feature +57 -0
  38. data/features/steps/env.rb +27 -0
  39. data/features/steps/httparty_response_steps.rb +52 -0
  40. data/features/steps/httparty_steps.rb +43 -0
  41. data/features/steps/mongrel_helper.rb +94 -0
  42. data/features/steps/remote_service_steps.rb +86 -0
  43. data/features/supports_read_timeout_option.feature +13 -0
  44. data/features/supports_redirection.feature +22 -0
  45. data/features/supports_timeout_option.feature +13 -0
  46. data/httparty.gemspec +28 -0
  47. data/httpserious.gemspec +25 -0
  48. data/lib/httparty.rb +612 -0
  49. data/lib/httparty/connection_adapter.rb +190 -0
  50. data/lib/httparty/cookie_hash.rb +21 -0
  51. data/lib/httparty/exceptions.rb +29 -0
  52. data/lib/httparty/hash_conversions.rb +49 -0
  53. data/lib/httparty/logger/apache_formatter.rb +22 -0
  54. data/lib/httparty/logger/curl_formatter.rb +48 -0
  55. data/lib/httparty/logger/logger.rb +26 -0
  56. data/lib/httparty/module_inheritable_attributes.rb +56 -0
  57. data/lib/httparty/net_digest_auth.rb +117 -0
  58. data/lib/httparty/parser.rb +141 -0
  59. data/lib/httparty/request.rb +361 -0
  60. data/lib/httparty/response.rb +77 -0
  61. data/lib/httparty/response/headers.rb +31 -0
  62. data/lib/httparty/version.rb +3 -0
  63. data/lib/httpserious.rb +1 -0
  64. data/script/release +42 -0
  65. data/spec/fixtures/delicious.xml +23 -0
  66. data/spec/fixtures/empty.xml +0 -0
  67. data/spec/fixtures/google.html +3 -0
  68. data/spec/fixtures/ssl/generate.sh +29 -0
  69. data/spec/fixtures/ssl/generated/1fe462c2.0 +16 -0
  70. data/spec/fixtures/ssl/generated/bogushost.crt +13 -0
  71. data/spec/fixtures/ssl/generated/ca.crt +16 -0
  72. data/spec/fixtures/ssl/generated/ca.key +15 -0
  73. data/spec/fixtures/ssl/generated/selfsigned.crt +14 -0
  74. data/spec/fixtures/ssl/generated/server.crt +13 -0
  75. data/spec/fixtures/ssl/generated/server.key +15 -0
  76. data/spec/fixtures/ssl/openssl-exts.cnf +9 -0
  77. data/spec/fixtures/twitter.csv +2 -0
  78. data/spec/fixtures/twitter.json +1 -0
  79. data/spec/fixtures/twitter.xml +403 -0
  80. data/spec/fixtures/undefined_method_add_node_for_nil.xml +2 -0
  81. data/spec/httparty/connection_adapter_spec.rb +468 -0
  82. data/spec/httparty/cookie_hash_spec.rb +83 -0
  83. data/spec/httparty/exception_spec.rb +38 -0
  84. data/spec/httparty/hash_conversions_spec.rb +41 -0
  85. data/spec/httparty/logger/apache_formatter_spec.rb +41 -0
  86. data/spec/httparty/logger/curl_formatter_spec.rb +18 -0
  87. data/spec/httparty/logger/logger_spec.rb +38 -0
  88. data/spec/httparty/net_digest_auth_spec.rb +191 -0
  89. data/spec/httparty/parser_spec.rb +167 -0
  90. data/spec/httparty/request_spec.rb +872 -0
  91. data/spec/httparty/response_spec.rb +241 -0
  92. data/spec/httparty/ssl_spec.rb +74 -0
  93. data/spec/httparty_spec.rb +823 -0
  94. data/spec/spec_helper.rb +59 -0
  95. data/spec/support/ssl_test_helper.rb +47 -0
  96. data/spec/support/ssl_test_server.rb +80 -0
  97. data/spec/support/stub_response.rb +43 -0
  98. data/website/css/common.css +47 -0
  99. data/website/index.html +73 -0
  100. metadata +219 -0
@@ -0,0 +1,117 @@
1
+ require 'digest/md5'
2
+ require 'net/http'
3
+
4
+ module Net
5
+ module HTTPHeader
6
+ def digest_auth(username, password, response)
7
+ authenticator = DigestAuthenticator.new(
8
+ username,
9
+ password,
10
+ @method,
11
+ @path,
12
+ response
13
+ )
14
+
15
+ @header['Authorization'] = authenticator.authorization_header
16
+ @header['cookie'] = append_cookies(authenticator) if response['Set-Cookie']
17
+ end
18
+
19
+ def append_cookies(authenticator)
20
+ cookies = @header['cookie'] ? @header['cookie'] : []
21
+ cookies.concat(authenticator.cookie_header)
22
+ end
23
+
24
+ class DigestAuthenticator
25
+ def initialize(username, password, method, path, response_header)
26
+ @username = username
27
+ @password = password
28
+ @method = method
29
+ @path = path
30
+ @response = parse(response_header)
31
+ @cookies = parse_cookies(response_header)
32
+ end
33
+
34
+ def authorization_header
35
+ @cnonce = md5(random)
36
+ header = [
37
+ %(Digest username="#{@username}"),
38
+ %(realm="#{@response['realm']}"),
39
+ %(nonce="#{@response['nonce']}"),
40
+ %(uri="#{@path}"),
41
+ %(response="#{request_digest}")
42
+ ]
43
+
44
+ if qop_present?
45
+ fields = [
46
+ %(cnonce="#{@cnonce}"),
47
+ %(qop="#{@response['qop']}"),
48
+ "nc=00000001"
49
+ ]
50
+ fields.each { |field| header << field }
51
+ end
52
+
53
+ header << %(opaque="#{@response['opaque']}") if opaque_present?
54
+ header
55
+ end
56
+
57
+ def cookie_header
58
+ @cookies
59
+ end
60
+
61
+ private
62
+
63
+ def parse(response_header)
64
+ header = response_header['www-authenticate']
65
+ .gsub(/qop=(auth(?:-int)?)/, 'qop="\\1"')
66
+
67
+ header =~ /Digest (.*)/
68
+ params = {}
69
+ $1.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
70
+ params
71
+ end
72
+
73
+ def parse_cookies(response_header)
74
+ return [] unless response_header['Set-Cookie']
75
+
76
+ cookies = response_header['Set-Cookie'].split('; ')
77
+
78
+ cookies.reduce([]) do |ret, cookie|
79
+ ret << cookie
80
+ ret
81
+ end
82
+
83
+ cookies
84
+ end
85
+
86
+ def opaque_present?
87
+ @response.key?('opaque') && !@response['opaque'].empty?
88
+ end
89
+
90
+ def qop_present?
91
+ @response.key?('qop') && !@response['qop'].empty?
92
+ end
93
+
94
+ def random
95
+ format "%x", (Time.now.to_i + rand(65535))
96
+ end
97
+
98
+ def request_digest
99
+ a = [md5(a1), @response['nonce'], md5(a2)]
100
+ a.insert(2, "00000001", @cnonce, @response['qop']) if qop_present?
101
+ md5(a.join(":"))
102
+ end
103
+
104
+ def md5(str)
105
+ Digest::MD5.hexdigest(str)
106
+ end
107
+
108
+ def a1
109
+ [@username, @response['realm'], @password].join(":")
110
+ end
111
+
112
+ def a2
113
+ [@method, @path].join(":")
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,141 @@
1
+ module HTTParty
2
+ # The default parser used by HTTParty, supports xml, json, html, csv and
3
+ # plain text.
4
+ #
5
+ # == Custom Parsers
6
+ #
7
+ # If you'd like to do your own custom parsing, subclassing HTTParty::Parser
8
+ # will make that process much easier. There are a few different ways you can
9
+ # utilize HTTParty::Parser as a superclass.
10
+ #
11
+ # @example Intercept the parsing for all formats
12
+ # class SimpleParser < HTTParty::Parser
13
+ # def parse
14
+ # perform_parsing
15
+ # end
16
+ # end
17
+ #
18
+ # @example Add the atom format and parsing method to the default parser
19
+ # class AtomParsingIncluded < HTTParty::Parser
20
+ # SupportedFormats.merge!(
21
+ # {"application/atom+xml" => :atom}
22
+ # )
23
+ #
24
+ # def atom
25
+ # perform_atom_parsing
26
+ # end
27
+ # end
28
+ #
29
+ # @example Only support the atom format
30
+ # class ParseOnlyAtom < HTTParty::Parser
31
+ # SupportedFormats = {"application/atom+xml" => :atom}
32
+ #
33
+ # def atom
34
+ # perform_atom_parsing
35
+ # end
36
+ # end
37
+ #
38
+ # @abstract Read the Custom Parsers section for more information.
39
+ class Parser
40
+ SupportedFormats = {
41
+ 'text/xml' => :xml,
42
+ 'application/xml' => :xml,
43
+ 'application/json' => :json,
44
+ 'text/json' => :json,
45
+ 'application/javascript' => :plain,
46
+ 'text/javascript' => :plain,
47
+ 'text/html' => :html,
48
+ 'text/plain' => :plain,
49
+ 'text/csv' => :csv,
50
+ 'application/csv' => :csv,
51
+ 'text/comma-separated-values' => :csv
52
+ }
53
+
54
+ # The response body of the request
55
+ # @return [String]
56
+ attr_reader :body
57
+
58
+ # The intended parsing format for the request
59
+ # @return [Symbol] e.g. :json
60
+ attr_reader :format
61
+
62
+ # Instantiate the parser and call {#parse}.
63
+ # @param [String] body the response body
64
+ # @param [Symbol] format the response format
65
+ # @return parsed response
66
+ def self.call(body, format)
67
+ new(body, format).parse
68
+ end
69
+
70
+ # @return [Hash] the SupportedFormats hash
71
+ def self.formats
72
+ const_get(:SupportedFormats)
73
+ end
74
+
75
+ # @param [String] mimetype response MIME type
76
+ # @return [Symbol]
77
+ # @return [nil] mime type not supported
78
+ def self.format_from_mimetype(mimetype)
79
+ formats[formats.keys.detect {|k| mimetype.include?(k)}]
80
+ end
81
+
82
+ # @return [Array<Symbol>] list of supported formats
83
+ def self.supported_formats
84
+ formats.values.uniq
85
+ end
86
+
87
+ # @param [Symbol] format e.g. :json, :xml
88
+ # @return [Boolean]
89
+ def self.supports_format?(format)
90
+ supported_formats.include?(format)
91
+ end
92
+
93
+ def initialize(body, format)
94
+ @body = body
95
+ @format = format
96
+ end
97
+
98
+ # @return [Object] the parsed body
99
+ # @return [nil] when the response body is nil, an empty string, spaces only or "null"
100
+ def parse
101
+ return nil if body.nil? || body.strip.empty? || body == "null"
102
+ if supports_format?
103
+ parse_supported_format
104
+ else
105
+ body
106
+ end
107
+ end
108
+
109
+ protected
110
+
111
+ def xml
112
+ MultiXml.parse(body)
113
+ end
114
+
115
+ def json
116
+ JSON.parse(body, :quirks_mode => true, :allow_nan => true)
117
+ end
118
+
119
+ def csv
120
+ CSV.parse(body)
121
+ end
122
+
123
+ def html
124
+ body
125
+ end
126
+
127
+ def plain
128
+ body
129
+ end
130
+
131
+ def supports_format?
132
+ self.class.supports_format?(format)
133
+ end
134
+
135
+ def parse_supported_format
136
+ send(format)
137
+ rescue NoMethodError => e
138
+ raise NotImplementedError, "#{self.class.name} has not implemented a parsing method for the #{format.inspect} format.", e.backtrace
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,361 @@
1
+ module HTTParty
2
+ class Request #:nodoc:
3
+ SupportedHTTPMethods = [
4
+ Net::HTTP::Get,
5
+ Net::HTTP::Post,
6
+ Net::HTTP::Patch,
7
+ Net::HTTP::Put,
8
+ Net::HTTP::Delete,
9
+ Net::HTTP::Head,
10
+ Net::HTTP::Options,
11
+ Net::HTTP::Move,
12
+ Net::HTTP::Copy
13
+ ]
14
+
15
+ SupportedURISchemes = ['http', 'https', 'webcal', nil]
16
+
17
+ NON_RAILS_QUERY_STRING_NORMALIZER = proc do |query|
18
+ Array(query).sort_by { |a| a[0].to_s }.map do |key, value|
19
+ if value.nil?
20
+ key.to_s
21
+ elsif value.respond_to?(:to_ary)
22
+ value.to_ary.map {|v| "#{key}=#{ERB::Util.url_encode(v.to_s)}"}
23
+ else
24
+ HashConversions.to_params(key => value)
25
+ end
26
+ end.flatten.join('&')
27
+ end
28
+
29
+ attr_accessor :http_method, :options, :last_response, :redirect, :last_uri
30
+ attr_reader :path
31
+
32
+ def initialize(http_method, path, o = {})
33
+ self.http_method = http_method
34
+ self.options = {
35
+ limit: o.delete(:no_follow) ? 1 : 5,
36
+ assume_utf16_is_big_endian: true,
37
+ default_params: {},
38
+ follow_redirects: true,
39
+ parser: Parser,
40
+ uri_adapter: URI,
41
+ connection_adapter: ConnectionAdapter
42
+ }.merge(o)
43
+ self.path = path
44
+ set_basic_auth_from_uri
45
+ end
46
+
47
+ def path=(uri)
48
+ uri_adapter = options[:uri_adapter]
49
+
50
+ @path = if uri.is_a?(uri_adapter)
51
+ uri
52
+ elsif String.try_convert(uri)
53
+ uri_adapter.parse uri
54
+ else
55
+ raise ArgumentError,
56
+ "bad argument (expected #{uri_adapter} object or URI string)"
57
+ end
58
+ end
59
+
60
+ def request_uri(uri)
61
+ if uri.respond_to? :request_uri
62
+ uri.request_uri
63
+ else
64
+ uri.path
65
+ end
66
+ end
67
+
68
+ def uri
69
+ if redirect && path.relative? && path.path[0] != "/"
70
+ last_uri_host = @last_uri.path.gsub(/[^\/]+$/, "")
71
+
72
+ path.path = "/#{path.path}" if last_uri_host[-1] != "/"
73
+ path.path = last_uri_host + path.path
74
+ end
75
+
76
+ new_uri = path.relative? ? options[:uri_adapter].parse("#{base_uri}#{path}") : path.clone
77
+
78
+ # avoid double query string on redirects [#12]
79
+ unless redirect
80
+ new_uri.query = query_string(new_uri)
81
+ end
82
+
83
+ unless SupportedURISchemes.include? new_uri.scheme
84
+ raise UnsupportedURIScheme, "'#{new_uri}' Must be HTTP, HTTPS or Generic"
85
+ end
86
+
87
+ @last_uri = new_uri
88
+ end
89
+
90
+ def base_uri
91
+ redirect ? "#{@last_uri.scheme}://#{@last_uri.host}" : options[:base_uri]
92
+ end
93
+
94
+ def format
95
+ options[:format] || (format_from_mimetype(last_response['content-type']) if last_response)
96
+ end
97
+
98
+ def parser
99
+ options[:parser]
100
+ end
101
+
102
+ def connection_adapter
103
+ options[:connection_adapter]
104
+ end
105
+
106
+ def perform(&block)
107
+ validate
108
+ setup_raw_request
109
+ chunked_body = nil
110
+
111
+ self.last_response = http.request(@raw_request) do |http_response|
112
+ if block
113
+ chunks = []
114
+
115
+ http_response.read_body do |fragment|
116
+ chunks << fragment unless options[:stream_body]
117
+ block.call(fragment)
118
+ end
119
+
120
+ chunked_body = chunks.join
121
+ end
122
+ end
123
+
124
+ handle_deflation unless http_method == Net::HTTP::Head
125
+ handle_response(chunked_body, &block)
126
+ end
127
+
128
+ def raw_body
129
+ @raw_request.body
130
+ end
131
+
132
+ private
133
+
134
+ def http
135
+ connection_adapter.call(uri, options)
136
+ end
137
+
138
+ def body
139
+ options[:body].respond_to?(:to_hash) ? normalize_query(options[:body]) : options[:body]
140
+ end
141
+
142
+ def credentials
143
+ (options[:basic_auth] || options[:digest_auth]).to_hash
144
+ end
145
+
146
+ def username
147
+ credentials[:username]
148
+ end
149
+
150
+ def password
151
+ credentials[:password]
152
+ end
153
+
154
+ def normalize_query(query)
155
+ if query_string_normalizer
156
+ query_string_normalizer.call(query)
157
+ else
158
+ HashConversions.to_params(query)
159
+ end
160
+ end
161
+
162
+ def query_string_normalizer
163
+ options[:query_string_normalizer]
164
+ end
165
+
166
+ def setup_raw_request
167
+ @raw_request = http_method.new(request_uri(uri))
168
+ @raw_request.body = body if body
169
+ @raw_request.body_stream = options[:body_stream] if options[:body_stream]
170
+ @raw_request.initialize_http_header(options[:headers].to_hash) if options[:headers].respond_to?(:to_hash)
171
+ @raw_request.basic_auth(username, password) if options[:basic_auth]
172
+ setup_digest_auth if options[:digest_auth]
173
+ end
174
+
175
+ def setup_digest_auth
176
+ auth_request = http_method.new(uri.request_uri)
177
+ auth_request.initialize_http_header(options[:headers].to_hash) if options[:headers].respond_to?(:to_hash)
178
+ res = http.request(auth_request)
179
+
180
+ if !res['www-authenticate'].nil? && res['www-authenticate'].length > 0
181
+ @raw_request.digest_auth(username, password, res)
182
+ end
183
+ end
184
+
185
+ def query_string(uri)
186
+ query_string_parts = []
187
+ query_string_parts << uri.query unless uri.query.nil?
188
+
189
+ if options[:query].respond_to?(:to_hash)
190
+ query_string_parts << normalize_query(options[:default_params].merge(options[:query].to_hash))
191
+ else
192
+ query_string_parts << normalize_query(options[:default_params]) unless options[:default_params].empty?
193
+ query_string_parts << options[:query] unless options[:query].nil?
194
+ end
195
+
196
+ query_string_parts.reject!(&:empty?) unless query_string_parts == [""]
197
+ query_string_parts.size > 0 ? query_string_parts.join('&') : nil
198
+ end
199
+
200
+ def get_charset
201
+ content_type = last_response["content-type"]
202
+ if content_type.nil?
203
+ return nil
204
+ end
205
+
206
+ if content_type =~ /;\s*charset\s*=\s*([^=,;"\s]+)/i
207
+ return $1
208
+ end
209
+
210
+ if content_type =~ /;\s*charset\s*=\s*"((\\.|[^\\"])+)"/i
211
+ return $1.gsub(/\\(.)/, '\1')
212
+ end
213
+
214
+ nil
215
+ end
216
+
217
+ def encode_with_ruby_encoding(body, charset)
218
+ encoding = Encoding.find(charset)
219
+ body.force_encoding(encoding)
220
+ rescue
221
+ body
222
+ end
223
+
224
+ def assume_utf16_is_big_endian
225
+ options[:assume_utf16_is_big_endian]
226
+ end
227
+
228
+ def encode_utf_16(body)
229
+ if body.bytesize >= 2
230
+ if body.getbyte(0) == 0xFF && body.getbyte(1) == 0xFE
231
+ return body.force_encoding("UTF-16LE")
232
+ elsif body.getbyte(0) == 0xFE && body.getbyte(1) == 0xFF
233
+ return body.force_encoding("UTF-16BE")
234
+ end
235
+ end
236
+
237
+ if assume_utf16_is_big_endian
238
+ body.force_encoding("UTF-16BE")
239
+ else
240
+ body.force_encoding("UTF-16LE")
241
+ end
242
+ end
243
+
244
+ def _encode_body(body)
245
+ charset = get_charset
246
+
247
+ if charset.nil?
248
+ return body
249
+ end
250
+
251
+ if "utf-16".casecmp(charset) == 0
252
+ encode_utf_16(body)
253
+ else
254
+ encode_with_ruby_encoding(body, charset)
255
+ end
256
+ end
257
+
258
+ def encode_body(body)
259
+ if "".respond_to?(:encoding)
260
+ _encode_body(body)
261
+ else
262
+ body
263
+ end
264
+ end
265
+
266
+ def handle_response(body, &block)
267
+ if response_redirects?
268
+ options[:limit] -= 1
269
+ if options[:logger]
270
+ logger = HTTParty::Logger.build(options[:logger], options[:log_level], options[:log_format])
271
+ logger.format(self, last_response)
272
+ end
273
+ self.path = last_response['location']
274
+ self.redirect = true
275
+ if last_response.class == Net::HTTPSeeOther
276
+ unless options[:maintain_method_across_redirects] && options[:resend_on_redirect]
277
+ self.http_method = Net::HTTP::Get
278
+ end
279
+ else
280
+ unless options[:maintain_method_across_redirects]
281
+ self.http_method = Net::HTTP::Get
282
+ end
283
+ end
284
+ capture_cookies(last_response)
285
+ perform(&block)
286
+ else
287
+ body ||= last_response.body
288
+ body = encode_body(body)
289
+ Response.new(self, last_response, lambda { parse_response(body) }, body: body)
290
+ end
291
+ end
292
+
293
+ # Inspired by Ruby 1.9
294
+ def handle_deflation
295
+ case last_response["content-encoding"]
296
+ when "gzip", "x-gzip"
297
+ body_io = StringIO.new(last_response.body)
298
+ last_response.body.replace Zlib::GzipReader.new(body_io).read
299
+ last_response.delete('content-encoding')
300
+ when "deflate"
301
+ last_response.body.replace Zlib::Inflate.inflate(last_response.body)
302
+ last_response.delete('content-encoding')
303
+ end
304
+ end
305
+
306
+ def response_redirects?
307
+ case last_response
308
+ when Net::HTTPMultipleChoice, # 300
309
+ Net::HTTPMovedPermanently, # 301
310
+ Net::HTTPFound, # 302
311
+ Net::HTTPSeeOther, # 303
312
+ Net::HTTPUseProxy, # 305
313
+ Net::HTTPTemporaryRedirect
314
+ options[:follow_redirects] && last_response.key?('location')
315
+ end
316
+ end
317
+
318
+ def parse_response(body)
319
+ parser.call(body, format)
320
+ end
321
+
322
+ def capture_cookies(response)
323
+ return unless response['Set-Cookie']
324
+ cookies_hash = HTTParty::CookieHash.new
325
+ cookies_hash.add_cookies(options[:headers].to_hash['Cookie']) if options[:headers] && options[:headers].to_hash['Cookie']
326
+ response.get_fields('Set-Cookie').each { |cookie| cookies_hash.add_cookies(cookie) }
327
+ options[:headers] ||= {}
328
+ options[:headers]['Cookie'] = cookies_hash.to_cookie_string
329
+ end
330
+
331
+ # Uses the HTTP Content-Type header to determine the format of the
332
+ # response It compares the MIME type returned to the types stored in the
333
+ # SupportedFormats hash
334
+ def format_from_mimetype(mimetype)
335
+ if mimetype && parser.respond_to?(:format_from_mimetype)
336
+ parser.format_from_mimetype(mimetype)
337
+ end
338
+ end
339
+
340
+ def validate
341
+ raise HTTParty::RedirectionTooDeep.new(last_response), 'HTTP redirects too deep' if options[:limit].to_i <= 0
342
+ raise ArgumentError, 'only get, post, patch, put, delete, head, and options methods are supported' unless SupportedHTTPMethods.include?(http_method)
343
+ raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].respond_to?(:to_hash)
344
+ raise ArgumentError, 'only one authentication method, :basic_auth or :digest_auth may be used at a time' if options[:basic_auth] && options[:digest_auth]
345
+ raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] && !options[:basic_auth].respond_to?(:to_hash)
346
+ raise ArgumentError, ':digest_auth must be a hash' if options[:digest_auth] && !options[:digest_auth].respond_to?(:to_hash)
347
+ raise ArgumentError, ':query must be hash if using HTTP Post' if post? && !options[:query].nil? && !options[:query].respond_to?(:to_hash)
348
+ end
349
+
350
+ def post?
351
+ Net::HTTP::Post == http_method
352
+ end
353
+
354
+ def set_basic_auth_from_uri
355
+ if path.userinfo
356
+ username, password = path.userinfo.split(':')
357
+ options[:basic_auth] = {username: username, password: password}
358
+ end
359
+ end
360
+ end
361
+ end