httparty-responsibly 0.17.0.r1

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +18 -0
  3. data/.gitignore +13 -0
  4. data/.rubocop.yml +92 -0
  5. data/.rubocop_todo.yml +124 -0
  6. data/.simplecov +1 -0
  7. data/.travis.yml +11 -0
  8. data/CONTRIBUTING.md +23 -0
  9. data/Changelog.md +502 -0
  10. data/Gemfile +23 -0
  11. data/Guardfile +16 -0
  12. data/MIT-LICENSE +20 -0
  13. data/README.md +78 -0
  14. data/Rakefile +10 -0
  15. data/bin/httparty +123 -0
  16. data/cucumber.yml +1 -0
  17. data/docs/README.md +106 -0
  18. data/examples/README.md +86 -0
  19. data/examples/aaws.rb +32 -0
  20. data/examples/basic.rb +28 -0
  21. data/examples/body_stream.rb +14 -0
  22. data/examples/crack.rb +19 -0
  23. data/examples/custom_parsers.rb +68 -0
  24. data/examples/delicious.rb +37 -0
  25. data/examples/google.rb +16 -0
  26. data/examples/headers_and_user_agents.rb +10 -0
  27. data/examples/logging.rb +36 -0
  28. data/examples/microsoft_graph.rb +52 -0
  29. data/examples/multipart.rb +22 -0
  30. data/examples/nokogiri_html_parser.rb +19 -0
  31. data/examples/peer_cert.rb +9 -0
  32. data/examples/rescue_json.rb +17 -0
  33. data/examples/rubyurl.rb +14 -0
  34. data/examples/stackexchange.rb +24 -0
  35. data/examples/stream_download.rb +26 -0
  36. data/examples/tripit_sign_in.rb +44 -0
  37. data/examples/twitter.rb +31 -0
  38. data/examples/whoismyrep.rb +10 -0
  39. data/httparty-responsibly.gemspec +27 -0
  40. data/lib/httparty.rb +684 -0
  41. data/lib/httparty/connection_adapter.rb +244 -0
  42. data/lib/httparty/cookie_hash.rb +21 -0
  43. data/lib/httparty/exceptions.rb +33 -0
  44. data/lib/httparty/hash_conversions.rb +69 -0
  45. data/lib/httparty/logger/apache_formatter.rb +45 -0
  46. data/lib/httparty/logger/curl_formatter.rb +91 -0
  47. data/lib/httparty/logger/logger.rb +28 -0
  48. data/lib/httparty/logger/logstash_formatter.rb +59 -0
  49. data/lib/httparty/module_inheritable_attributes.rb +56 -0
  50. data/lib/httparty/net_digest_auth.rb +136 -0
  51. data/lib/httparty/parser.rb +150 -0
  52. data/lib/httparty/request.rb +386 -0
  53. data/lib/httparty/request/body.rb +84 -0
  54. data/lib/httparty/request/multipart_boundary.rb +11 -0
  55. data/lib/httparty/response.rb +140 -0
  56. data/lib/httparty/response/headers.rb +33 -0
  57. data/lib/httparty/response_fragment.rb +19 -0
  58. data/lib/httparty/text_encoder.rb +70 -0
  59. data/lib/httparty/utils.rb +11 -0
  60. data/lib/httparty/version.rb +3 -0
  61. data/script/release +42 -0
  62. data/website/css/common.css +47 -0
  63. data/website/index.html +73 -0
  64. metadata +138 -0
@@ -0,0 +1,44 @@
1
+ dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require File.join(dir, 'httparty')
3
+
4
+ class TripIt
5
+ include HTTParty
6
+ base_uri 'https://www.tripit.com'
7
+ debug_output
8
+
9
+ def initialize(email, password)
10
+ @email = email
11
+ get_response = self.class.get('/account/login')
12
+ get_response_cookie = parse_cookie(get_response.headers['Set-Cookie'])
13
+
14
+ post_response = self.class.post(
15
+ '/account/login',
16
+ body: {
17
+ login_email_address: email,
18
+ login_password: password
19
+ },
20
+ headers: {'Cookie' => get_response_cookie.to_cookie_string }
21
+ )
22
+
23
+ @cookie = parse_cookie(post_response.headers['Set-Cookie'])
24
+ end
25
+
26
+ def account_settings
27
+ self.class.get('/account/edit', headers: { 'Cookie' => @cookie.to_cookie_string })
28
+ end
29
+
30
+ def logged_in?
31
+ account_settings.include? "You're logged in as #{@email}"
32
+ end
33
+
34
+ private
35
+
36
+ def parse_cookie(resp)
37
+ cookie_hash = CookieHash.new
38
+ resp.get_fields('Set-Cookie').each { |c| cookie_hash.add_cookies(c) }
39
+ cookie_hash
40
+ end
41
+ end
42
+
43
+ tripit = TripIt.new('email', 'password')
44
+ puts "Logged in: #{tripit.logged_in?}"
@@ -0,0 +1,31 @@
1
+ dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require File.join(dir, 'httparty')
3
+ require 'pp'
4
+ config = YAML.load(File.read(File.join(ENV['HOME'], '.twitter')))
5
+
6
+ class Twitter
7
+ include HTTParty
8
+ base_uri 'twitter.com'
9
+
10
+ def initialize(u, p)
11
+ @auth = {username: u, password: p}
12
+ end
13
+
14
+ # which can be :friends, :user or :public
15
+ # options[:query] can be things like since, since_id, count, etc.
16
+ def timeline(which = :friends, options = {})
17
+ options.merge!({ basic_auth: @auth })
18
+ self.class.get("/statuses/#{which}_timeline.json", options)
19
+ end
20
+
21
+ def post(text)
22
+ options = { query: { status: text }, basic_auth: @auth }
23
+ self.class.post('/statuses/update.json', options)
24
+ end
25
+ end
26
+
27
+ twitter = Twitter.new(config['email'], config['password'])
28
+ pp twitter.timeline
29
+ # pp twitter.timeline(:friends, query: {since_id: 868482746})
30
+ # pp twitter.timeline(:friends, query: 'since_id=868482746')
31
+ # pp twitter.post('this is a test of 0.2.0')
@@ -0,0 +1,10 @@
1
+ dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require File.join(dir, 'httparty')
3
+ require 'pp'
4
+
5
+ class Rep
6
+ include HTTParty
7
+ end
8
+
9
+ pp Rep.get('http://whoismyrepresentative.com/getall_mems.php?zip=46544')
10
+ pp Rep.get('http://whoismyrepresentative.com/getall_mems.php', query: { zip: 46544 })
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $LOAD_PATH.push File.expand_path("../lib", __FILE__)
3
+ require "httparty/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "httparty-responsibly"
7
+ s.version = HTTParty::VERSION + '.r1'
8
+ s.platform = Gem::Platform::RUBY
9
+ s.licenses = ['MIT']
10
+ s.authors = ["John Nunemaker", "Sandro Turriate", "James Denness"]
11
+ s.email = ["nunemaker@gmail.com", "james@denness.org"]
12
+ s.homepage = "https://github.com/scarybot/httparty-responsibly"
13
+ s.summary = "An up-to-date fork of jnunemaker's httparty, without the post-install nonsense."
14
+ s.description = "An up-to-date fork of jnunemaker's httparty, without the post-install nonsense."
15
+
16
+ s.required_ruby_version = '>= 2.0.0'
17
+
18
+ s.add_dependency 'multi_xml', ">= 0.5.2"
19
+ s.add_dependency('mime-types', "~> 3.0")
20
+
21
+ all_files = `git ls-files`.split("\n")
22
+ test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+
24
+ s.files = all_files - test_files
25
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
26
+ s.require_paths = ["lib"]
27
+ end
@@ -0,0 +1,684 @@
1
+ require 'pathname'
2
+ require 'net/http'
3
+ require 'net/https'
4
+ require 'uri'
5
+ require 'zlib'
6
+ require 'multi_xml'
7
+ require 'mime/types'
8
+ require 'json'
9
+ require 'csv'
10
+
11
+ require 'httparty/module_inheritable_attributes'
12
+ require 'httparty/cookie_hash'
13
+ require 'httparty/net_digest_auth'
14
+ require 'httparty/version'
15
+ require 'httparty/connection_adapter'
16
+ require 'httparty/logger/logger'
17
+ require 'httparty/request/body'
18
+ require 'httparty/response_fragment'
19
+ require 'httparty/text_encoder'
20
+
21
+ # @see HTTParty::ClassMethods
22
+ module HTTParty
23
+ def self.included(base)
24
+ base.extend ClassMethods
25
+ base.send :include, ModuleInheritableAttributes
26
+ base.send(:mattr_inheritable, :default_options)
27
+ base.send(:mattr_inheritable, :default_cookies)
28
+ base.instance_variable_set("@default_options", {})
29
+ base.instance_variable_set("@default_cookies", CookieHash.new)
30
+ end
31
+
32
+ # == Common Request Options
33
+ # Request methods (get, post, patch, put, delete, head, options) all take a common set of options. These are:
34
+ #
35
+ # [:+body+:] Body of the request. If passed an object that responds to #to_hash, will try to normalize it first, by default passing it to ActiveSupport::to_params. Any other kind of object will get used as-is.
36
+ # [:+http_proxyaddr+:] Address of proxy server to use.
37
+ # [:+http_proxyport+:] Port of proxy server to use.
38
+ # [:+http_proxyuser+:] User for proxy server authentication.
39
+ # [:+http_proxypass+:] Password for proxy server authentication.
40
+ # [:+limit+:] Maximum number of redirects to follow. Takes precedences over :+no_follow+.
41
+ # [:+query+:] Query string, or an object that responds to #to_hash representing it. Normalized according to the same rules as :+body+. If you specify this on a POST, you must use an object which responds to #to_hash. See also HTTParty::ClassMethods.default_params.
42
+ # [:+timeout+:] Timeout for opening connection and reading data.
43
+ # [:+local_host:] Local address to bind to before connecting.
44
+ # [:+local_port:] Local port to bind to before connecting.
45
+ # [:+body_stream:] Allow streaming to a REST server to specify a body_stream.
46
+ # [:+stream_body:] Allow for streaming large files without loading them into memory.
47
+ # [:+multipart:] Force content-type to be multipart
48
+ #
49
+ # There are also another set of options with names corresponding to various class methods. The methods in question are those that let you set a class-wide default, and the options override the defaults on a request-by-request basis. Those options are:
50
+ # * :+base_uri+: see HTTParty::ClassMethods.base_uri.
51
+ # * :+basic_auth+: see HTTParty::ClassMethods.basic_auth. Only one of :+basic_auth+ and :+digest_auth+ can be used at a time; if you try using both, you'll get an ArgumentError.
52
+ # * :+debug_output+: see HTTParty::ClassMethods.debug_output.
53
+ # * :+digest_auth+: see HTTParty::ClassMethods.digest_auth. Only one of :+basic_auth+ and :+digest_auth+ can be used at a time; if you try using both, you'll get an ArgumentError.
54
+ # * :+format+: see HTTParty::ClassMethods.format.
55
+ # * :+headers+: see HTTParty::ClassMethods.headers. Must be a an object which responds to #to_hash.
56
+ # * :+maintain_method_across_redirects+: see HTTParty::ClassMethods.maintain_method_across_redirects.
57
+ # * :+no_follow+: see HTTParty::ClassMethods.no_follow.
58
+ # * :+parser+: see HTTParty::ClassMethods.parser.
59
+ # * :+uri_adapter+: see HTTParty::ClassMethods.uri_adapter
60
+ # * :+connection_adapter+: see HTTParty::ClassMethods.connection_adapter.
61
+ # * :+pem+: see HTTParty::ClassMethods.pem.
62
+ # * :+query_string_normalizer+: see HTTParty::ClassMethods.query_string_normalizer
63
+ # * :+ssl_ca_file+: see HTTParty::ClassMethods.ssl_ca_file.
64
+ # * :+ssl_ca_path+: see HTTParty::ClassMethods.ssl_ca_path.
65
+
66
+ module ClassMethods
67
+ # Turns on logging
68
+ #
69
+ # class Foo
70
+ # include HTTParty
71
+ # logger Logger.new('http_logger'), :info, :apache
72
+ # end
73
+ def logger(logger, level = :info, format = :apache)
74
+ default_options[:logger] = logger
75
+ default_options[:log_level] = level
76
+ default_options[:log_format] = format
77
+ end
78
+
79
+ # Raises HTTParty::ResponseError if response's code matches this statuses
80
+ #
81
+ # class Foo
82
+ # include HTTParty
83
+ # raise_on [404, 500]
84
+ # end
85
+ def raise_on(codes = [])
86
+ default_options[:raise_on] = *codes
87
+ end
88
+
89
+ # Allows setting http proxy information to be used
90
+ #
91
+ # class Foo
92
+ # include HTTParty
93
+ # http_proxy 'http://foo.com', 80, 'user', 'pass'
94
+ # end
95
+ def http_proxy(addr = nil, port = nil, user = nil, pass = nil)
96
+ default_options[:http_proxyaddr] = addr
97
+ default_options[:http_proxyport] = port
98
+ default_options[:http_proxyuser] = user
99
+ default_options[:http_proxypass] = pass
100
+ end
101
+
102
+ # Allows setting a base uri to be used for each request.
103
+ # Will normalize uri to include http, etc.
104
+ #
105
+ # class Foo
106
+ # include HTTParty
107
+ # base_uri 'twitter.com'
108
+ # end
109
+ def base_uri(uri = nil)
110
+ return default_options[:base_uri] unless uri
111
+ default_options[:base_uri] = HTTParty.normalize_base_uri(uri)
112
+ end
113
+
114
+ # Allows setting basic authentication username and password.
115
+ #
116
+ # class Foo
117
+ # include HTTParty
118
+ # basic_auth 'username', 'password'
119
+ # end
120
+ def basic_auth(u, p)
121
+ default_options[:basic_auth] = {username: u, password: p}
122
+ end
123
+
124
+ # Allows setting digest authentication username and password.
125
+ #
126
+ # class Foo
127
+ # include HTTParty
128
+ # digest_auth 'username', 'password'
129
+ # end
130
+ def digest_auth(u, p)
131
+ default_options[:digest_auth] = {username: u, password: p}
132
+ end
133
+
134
+ # Do not send rails style query strings.
135
+ # Specifically, don't use bracket notation when sending an array
136
+ #
137
+ # For a query:
138
+ # get '/', query: {selected_ids: [1,2,3]}
139
+ #
140
+ # The default query string looks like this:
141
+ # /?selected_ids[]=1&selected_ids[]=2&selected_ids[]=3
142
+ #
143
+ # Call `disable_rails_query_string_format` to transform the query string
144
+ # into:
145
+ # /?selected_ids=1&selected_ids=2&selected_ids=3
146
+ #
147
+ # @example
148
+ # class Foo
149
+ # include HTTParty
150
+ # disable_rails_query_string_format
151
+ # end
152
+ def disable_rails_query_string_format
153
+ query_string_normalizer Request::NON_RAILS_QUERY_STRING_NORMALIZER
154
+ end
155
+
156
+ # Allows setting default parameters to be appended to each request.
157
+ # Great for api keys and such.
158
+ #
159
+ # class Foo
160
+ # include HTTParty
161
+ # default_params api_key: 'secret', another: 'foo'
162
+ # end
163
+ def default_params(h = {})
164
+ raise ArgumentError, 'Default params must be an object which responds to #to_hash' unless h.respond_to?(:to_hash)
165
+ default_options[:default_params] ||= {}
166
+ default_options[:default_params].merge!(h)
167
+ end
168
+
169
+ # Allows setting a default timeout for all HTTP calls
170
+ # Timeout is specified in seconds.
171
+ #
172
+ # class Foo
173
+ # include HTTParty
174
+ # default_timeout 10
175
+ # end
176
+ def default_timeout(value)
177
+ validate_timeout_argument(__method__, value)
178
+ default_options[:timeout] = value
179
+ end
180
+
181
+ # Allows setting a default open_timeout for all HTTP calls in seconds
182
+ #
183
+ # class Foo
184
+ # include HTTParty
185
+ # open_timeout 10
186
+ # end
187
+ def open_timeout(value)
188
+ validate_timeout_argument(__method__, value)
189
+ default_options[:open_timeout] = value
190
+ end
191
+
192
+ # Allows setting a default read_timeout for all HTTP calls in seconds
193
+ #
194
+ # class Foo
195
+ # include HTTParty
196
+ # read_timeout 10
197
+ # end
198
+ def read_timeout(value)
199
+ validate_timeout_argument(__method__, value)
200
+ default_options[:read_timeout] = value
201
+ end
202
+
203
+ # Allows setting a default write_timeout for all HTTP calls in seconds
204
+ # Supported by Ruby > 2.6.0
205
+ #
206
+ # class Foo
207
+ # include HTTParty
208
+ # write_timeout 10
209
+ # end
210
+ def write_timeout(value)
211
+ validate_timeout_argument(__method__, value)
212
+ default_options[:write_timeout] = value
213
+ end
214
+
215
+
216
+ # Set an output stream for debugging, defaults to $stderr.
217
+ # The output stream is passed on to Net::HTTP#set_debug_output.
218
+ #
219
+ # class Foo
220
+ # include HTTParty
221
+ # debug_output $stderr
222
+ # end
223
+ def debug_output(stream = $stderr)
224
+ default_options[:debug_output] = stream
225
+ end
226
+
227
+ # Allows setting HTTP headers to be used for each request.
228
+ #
229
+ # class Foo
230
+ # include HTTParty
231
+ # headers 'Accept' => 'text/html'
232
+ # end
233
+ def headers(h = nil)
234
+ if h
235
+ raise ArgumentError, 'Headers must be an object which responds to #to_hash' unless h.respond_to?(:to_hash)
236
+ default_options[:headers] ||= {}
237
+ default_options[:headers].merge!(h.to_hash)
238
+ else
239
+ default_options[:headers] || {}
240
+ end
241
+ end
242
+
243
+ def cookies(h = {})
244
+ raise ArgumentError, 'Cookies must be an object which responds to #to_hash' unless h.respond_to?(:to_hash)
245
+ default_cookies.add_cookies(h)
246
+ end
247
+
248
+ # Proceed to the location header when an HTTP response dictates a redirect.
249
+ # Redirects are always followed by default.
250
+ #
251
+ # @example
252
+ # class Foo
253
+ # include HTTParty
254
+ # base_uri 'http://google.com'
255
+ # follow_redirects true
256
+ # end
257
+ def follow_redirects(value = true)
258
+ default_options[:follow_redirects] = value
259
+ end
260
+
261
+ # Allows setting the format with which to parse.
262
+ # Must be one of the allowed formats ie: json, xml
263
+ #
264
+ # class Foo
265
+ # include HTTParty
266
+ # format :json
267
+ # end
268
+ def format(f = nil)
269
+ if f.nil?
270
+ default_options[:format]
271
+ else
272
+ parser(Parser) if parser.nil?
273
+ default_options[:format] = f
274
+ validate_format
275
+ end
276
+ end
277
+
278
+ # Declare whether or not to follow redirects. When true, an
279
+ # {HTTParty::RedirectionTooDeep} error will raise upon encountering a
280
+ # redirect. You can then gain access to the response object via
281
+ # HTTParty::RedirectionTooDeep#response.
282
+ #
283
+ # @see HTTParty::ResponseError#response
284
+ #
285
+ # @example
286
+ # class Foo
287
+ # include HTTParty
288
+ # base_uri 'http://google.com'
289
+ # no_follow true
290
+ # end
291
+ #
292
+ # begin
293
+ # Foo.get('/')
294
+ # rescue HTTParty::RedirectionTooDeep => e
295
+ # puts e.response.body
296
+ # end
297
+ def no_follow(value = false)
298
+ default_options[:no_follow] = value
299
+ end
300
+
301
+ # Declare that you wish to maintain the chosen HTTP method across redirects.
302
+ # The default behavior is to follow redirects via the GET method, except
303
+ # if you are making a HEAD request, in which case the default is to
304
+ # follow all redirects with HEAD requests.
305
+ # If you wish to maintain the original method, you can set this option to true.
306
+ #
307
+ # @example
308
+ # class Foo
309
+ # include HTTParty
310
+ # base_uri 'http://google.com'
311
+ # maintain_method_across_redirects true
312
+ # end
313
+
314
+ def maintain_method_across_redirects(value = true)
315
+ default_options[:maintain_method_across_redirects] = value
316
+ end
317
+
318
+ # Declare that you wish to resend the full HTTP request across redirects,
319
+ # even on redirects that should logically become GET requests.
320
+ # A 303 redirect in HTTP signifies that the redirected url should normally
321
+ # retrieved using a GET request, for instance, it is the output of a previous
322
+ # POST. maintain_method_across_redirects respects this behavior, but you
323
+ # can force HTTParty to resend_on_redirect even on 303 responses.
324
+ #
325
+ # @example
326
+ # class Foo
327
+ # include HTTParty
328
+ # base_uri 'http://google.com'
329
+ # resend_on_redirect
330
+ # end
331
+
332
+ def resend_on_redirect(value = true)
333
+ default_options[:resend_on_redirect] = value
334
+ end
335
+
336
+ # Allows setting a PEM file to be used
337
+ #
338
+ # class Foo
339
+ # include HTTParty
340
+ # pem File.read('/home/user/my.pem'), "optional password"
341
+ # end
342
+ def pem(pem_contents, password = nil)
343
+ default_options[:pem] = pem_contents
344
+ default_options[:pem_password] = password
345
+ end
346
+
347
+ # Allows setting a PKCS12 file to be used
348
+ #
349
+ # class Foo
350
+ # include HTTParty
351
+ # pkcs12 File.read('/home/user/my.p12'), "password"
352
+ # end
353
+ def pkcs12(p12_contents, password)
354
+ default_options[:p12] = p12_contents
355
+ default_options[:p12_password] = password
356
+ end
357
+
358
+ # Override the way query strings are normalized.
359
+ # Helpful for overriding the default rails normalization of Array queries.
360
+ #
361
+ # For a query:
362
+ # get '/', query: {selected_ids: [1,2,3]}
363
+ #
364
+ # The default query string normalizer returns:
365
+ # /?selected_ids[]=1&selected_ids[]=2&selected_ids[]=3
366
+ #
367
+ # Let's change it to this:
368
+ # /?selected_ids=1&selected_ids=2&selected_ids=3
369
+ #
370
+ # Pass a Proc to the query normalizer which accepts the yielded query.
371
+ #
372
+ # @example Modifying Array query strings
373
+ # class ServiceWrapper
374
+ # include HTTParty
375
+ #
376
+ # query_string_normalizer proc { |query|
377
+ # query.map do |key, value|
378
+ # value.map {|v| "#{key}=#{v}"}
379
+ # end.join('&')
380
+ # }
381
+ # end
382
+ #
383
+ # @param [Proc] normalizer custom query string normalizer.
384
+ # @yield [Hash, String] query string
385
+ # @yieldreturn [Array] an array that will later be joined with '&'
386
+ def query_string_normalizer(normalizer)
387
+ default_options[:query_string_normalizer] = normalizer
388
+ end
389
+
390
+ # Allows setting of SSL version to use. This only works in Ruby 1.9+.
391
+ # You can get a list of valid versions from OpenSSL::SSL::SSLContext::METHODS.
392
+ #
393
+ # class Foo
394
+ # include HTTParty
395
+ # ssl_version :SSLv3
396
+ # end
397
+ def ssl_version(version)
398
+ default_options[:ssl_version] = version
399
+ end
400
+
401
+ # Allows setting of SSL ciphers to use. This only works in Ruby 1.9+.
402
+ # You can get a list of valid specific ciphers from OpenSSL::Cipher.ciphers.
403
+ # You also can specify a cipher suite here, listed here at openssl.org:
404
+ # http://www.openssl.org/docs/apps/ciphers.html#CIPHER_SUITE_NAMES
405
+ #
406
+ # class Foo
407
+ # include HTTParty
408
+ # ciphers "RC4-SHA"
409
+ # end
410
+ def ciphers(cipher_names)
411
+ default_options[:ciphers] = cipher_names
412
+ end
413
+
414
+ # Allows setting an OpenSSL certificate authority file. The file
415
+ # should contain one or more certificates in PEM format.
416
+ #
417
+ # Setting this option enables certificate verification. All
418
+ # certificates along a chain must be available in ssl_ca_file or
419
+ # ssl_ca_path for verification to succeed.
420
+ #
421
+ #
422
+ # class Foo
423
+ # include HTTParty
424
+ # ssl_ca_file '/etc/ssl/certs/ca-certificates.crt'
425
+ # end
426
+ def ssl_ca_file(path)
427
+ default_options[:ssl_ca_file] = path
428
+ end
429
+
430
+ # Allows setting an OpenSSL certificate authority path (directory).
431
+ #
432
+ # Setting this option enables certificate verification. All
433
+ # certificates along a chain must be available in ssl_ca_file or
434
+ # ssl_ca_path for verification to succeed.
435
+ #
436
+ # class Foo
437
+ # include HTTParty
438
+ # ssl_ca_path '/etc/ssl/certs/'
439
+ # end
440
+ def ssl_ca_path(path)
441
+ default_options[:ssl_ca_path] = path
442
+ end
443
+
444
+ # Allows setting a custom parser for the response.
445
+ #
446
+ # class Foo
447
+ # include HTTParty
448
+ # parser Proc.new {|data| ...}
449
+ # end
450
+ def parser(custom_parser = nil)
451
+ if custom_parser.nil?
452
+ default_options[:parser]
453
+ else
454
+ default_options[:parser] = custom_parser
455
+ validate_format
456
+ end
457
+ end
458
+
459
+ # Allows setting a custom URI adapter.
460
+ #
461
+ # class Foo
462
+ # include HTTParty
463
+ # uri_adapter Addressable::URI
464
+ # end
465
+ def uri_adapter(uri_adapter)
466
+ raise ArgumentError, 'The URI adapter should respond to #parse' unless uri_adapter.respond_to?(:parse)
467
+ default_options[:uri_adapter] = uri_adapter
468
+ end
469
+
470
+ # Allows setting a custom connection_adapter for the http connections
471
+ #
472
+ # @example
473
+ # class Foo
474
+ # include HTTParty
475
+ # connection_adapter Proc.new {|uri, options| ... }
476
+ # end
477
+ #
478
+ # @example provide optional configuration for your connection_adapter
479
+ # class Foo
480
+ # include HTTParty
481
+ # connection_adapter Proc.new {|uri, options| ... }, {foo: :bar}
482
+ # end
483
+ #
484
+ # @see HTTParty::ConnectionAdapter
485
+ def connection_adapter(custom_adapter = nil, options = nil)
486
+ if custom_adapter.nil?
487
+ default_options[:connection_adapter]
488
+ else
489
+ default_options[:connection_adapter] = custom_adapter
490
+ default_options[:connection_adapter_options] = options
491
+ end
492
+ end
493
+
494
+ # Allows making a get request to a url.
495
+ #
496
+ # class Foo
497
+ # include HTTParty
498
+ # end
499
+ #
500
+ # # Simple get with full url
501
+ # Foo.get('http://foo.com/resource.json')
502
+ #
503
+ # # Simple get with full url and query parameters
504
+ # # ie: http://foo.com/resource.json?limit=10
505
+ # Foo.get('http://foo.com/resource.json', query: {limit: 10})
506
+ def get(path, options = {}, &block)
507
+ perform_request Net::HTTP::Get, path, options, &block
508
+ end
509
+
510
+ # Allows making a post request to a url.
511
+ #
512
+ # class Foo
513
+ # include HTTParty
514
+ # end
515
+ #
516
+ # # Simple post with full url and setting the body
517
+ # Foo.post('http://foo.com/resources', body: {bar: 'baz'})
518
+ #
519
+ # # Simple post with full url using :query option,
520
+ # # which appends the parameters to the URI.
521
+ # Foo.post('http://foo.com/resources', query: {bar: 'baz'})
522
+ def post(path, options = {}, &block)
523
+ perform_request Net::HTTP::Post, path, options, &block
524
+ end
525
+
526
+ # Perform a PATCH request to a path
527
+ def patch(path, options = {}, &block)
528
+ perform_request Net::HTTP::Patch, path, options, &block
529
+ end
530
+
531
+ # Perform a PUT request to a path
532
+ def put(path, options = {}, &block)
533
+ perform_request Net::HTTP::Put, path, options, &block
534
+ end
535
+
536
+ # Perform a DELETE request to a path
537
+ def delete(path, options = {}, &block)
538
+ perform_request Net::HTTP::Delete, path, options, &block
539
+ end
540
+
541
+ # Perform a MOVE request to a path
542
+ def move(path, options = {}, &block)
543
+ perform_request Net::HTTP::Move, path, options, &block
544
+ end
545
+
546
+ # Perform a COPY request to a path
547
+ def copy(path, options = {}, &block)
548
+ perform_request Net::HTTP::Copy, path, options, &block
549
+ end
550
+
551
+ # Perform a HEAD request to a path
552
+ def head(path, options = {}, &block)
553
+ ensure_method_maintained_across_redirects options
554
+ perform_request Net::HTTP::Head, path, options, &block
555
+ end
556
+
557
+ # Perform an OPTIONS request to a path
558
+ def options(path, options = {}, &block)
559
+ perform_request Net::HTTP::Options, path, options, &block
560
+ end
561
+
562
+ # Perform a MKCOL request to a path
563
+ def mkcol(path, options = {}, &block)
564
+ perform_request Net::HTTP::Mkcol, path, options, &block
565
+ end
566
+
567
+ def lock(path, options = {}, &block)
568
+ perform_request Net::HTTP::Lock, path, options, &block
569
+ end
570
+
571
+ def unlock(path, options = {}, &block)
572
+ perform_request Net::HTTP::Unlock, path, options, &block
573
+ end
574
+
575
+ attr_reader :default_options
576
+
577
+ private
578
+
579
+ def validate_timeout_argument(timeout_type, value)
580
+ raise ArgumentError, "#{ timeout_type } must be an integer or float" unless value && (value.is_a?(Integer) || value.is_a?(Float))
581
+ end
582
+
583
+ def ensure_method_maintained_across_redirects(options)
584
+ unless options.key?(:maintain_method_across_redirects)
585
+ options[:maintain_method_across_redirects] = true
586
+ end
587
+ end
588
+
589
+ def perform_request(http_method, path, options, &block) #:nodoc:
590
+ options = ModuleInheritableAttributes.hash_deep_dup(default_options).merge(options)
591
+ process_headers(options)
592
+ process_cookies(options)
593
+ Request.new(http_method, path, options).perform(&block)
594
+ end
595
+
596
+ def process_headers(options)
597
+ if options[:headers]
598
+ if headers.any?
599
+ options[:headers] = headers.merge(options[:headers])
600
+ end
601
+
602
+ options[:headers] = Utils.stringify_keys(process_dynamic_headers(options[:headers]))
603
+ end
604
+ end
605
+
606
+ def process_dynamic_headers(headers)
607
+ headers.each_with_object({}) do |header, processed_headers|
608
+ key, value = header
609
+ processed_headers[key] = value.respond_to?(:call) ? value.call : value
610
+ end
611
+ end
612
+
613
+ def process_cookies(options) #:nodoc:
614
+ return unless options[:cookies] || default_cookies.any?
615
+ options[:headers] ||= headers.dup
616
+ options[:headers]["cookie"] = cookies.merge(options.delete(:cookies) || {}).to_cookie_string
617
+ end
618
+
619
+ def validate_format
620
+ if format && parser.respond_to?(:supports_format?) && !parser.supports_format?(format)
621
+ supported_format_names = parser.supported_formats.map(&:to_s).sort.join(', ')
622
+ raise UnsupportedFormat, "'#{format.inspect}' Must be one of: #{supported_format_names}"
623
+ end
624
+ end
625
+ end
626
+
627
+ def self.normalize_base_uri(url) #:nodoc:
628
+ normalized_url = url.dup
629
+ use_ssl = (normalized_url =~ /^https/) || (normalized_url =~ /:443\b/)
630
+ ends_with_slash = normalized_url =~ /\/$/
631
+
632
+ normalized_url.chop! if ends_with_slash
633
+ normalized_url.gsub!(/^https?:\/\//i, '')
634
+
635
+ "http#{'s' if use_ssl}://#{normalized_url}"
636
+ end
637
+
638
+ class Basement #:nodoc:
639
+ include HTTParty
640
+ end
641
+
642
+ def self.get(*args, &block)
643
+ Basement.get(*args, &block)
644
+ end
645
+
646
+ def self.post(*args, &block)
647
+ Basement.post(*args, &block)
648
+ end
649
+
650
+ def self.patch(*args, &block)
651
+ Basement.patch(*args, &block)
652
+ end
653
+
654
+ def self.put(*args, &block)
655
+ Basement.put(*args, &block)
656
+ end
657
+
658
+ def self.delete(*args, &block)
659
+ Basement.delete(*args, &block)
660
+ end
661
+
662
+ def self.move(*args, &block)
663
+ Basement.move(*args, &block)
664
+ end
665
+
666
+ def self.copy(*args, &block)
667
+ Basement.copy(*args, &block)
668
+ end
669
+
670
+ def self.head(*args, &block)
671
+ Basement.head(*args, &block)
672
+ end
673
+
674
+ def self.options(*args, &block)
675
+ Basement.options(*args, &block)
676
+ end
677
+ end
678
+
679
+ require 'httparty/hash_conversions'
680
+ require 'httparty/utils'
681
+ require 'httparty/exceptions'
682
+ require 'httparty/parser'
683
+ require 'httparty/request'
684
+ require 'httparty/response'