httparty 0.16.2 → 0.16.3

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

Potentially problematic release.


This version of httparty might be problematic. Click here for more details.

Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +18 -0
  3. data/.gitignore +1 -0
  4. data/Changelog.md +11 -0
  5. data/README.md +1 -1
  6. data/examples/README.md +22 -11
  7. data/examples/body_stream.rb +14 -0
  8. data/examples/microsoft_graph.rb +52 -0
  9. data/examples/multipart.rb +22 -0
  10. data/features/steps/mongrel_helper.rb +3 -3
  11. data/httparty.gemspec +2 -1
  12. data/lib/httparty.rb +21 -1
  13. data/lib/httparty/connection_adapter.rb +11 -4
  14. data/lib/httparty/hash_conversions.rb +6 -2
  15. data/lib/httparty/logger/apache_formatter.rb +29 -6
  16. data/lib/httparty/logger/curl_formatter.rb +4 -4
  17. data/lib/httparty/logger/logger.rb +3 -1
  18. data/lib/httparty/logger/logstash_formatter.rb +59 -0
  19. data/lib/httparty/module_inheritable_attributes.rb +3 -3
  20. data/lib/httparty/net_digest_auth.rb +6 -5
  21. data/lib/httparty/request.rb +8 -1
  22. data/lib/httparty/request/body.rb +16 -5
  23. data/lib/httparty/response.rb +19 -5
  24. data/lib/httparty/response/headers.rb +2 -2
  25. data/lib/httparty/utils.rb +11 -0
  26. data/lib/httparty/version.rb +1 -1
  27. data/spec/httparty/connection_adapter_spec.rb +7 -3
  28. data/spec/httparty/cookie_hash_spec.rb +1 -1
  29. data/spec/httparty/exception_spec.rb +1 -1
  30. data/spec/httparty/hash_conversions_spec.rb +2 -0
  31. data/spec/httparty/logger/apache_formatter_spec.rb +1 -2
  32. data/spec/httparty/logger/curl_formatter_spec.rb +1 -1
  33. data/spec/httparty/logger/logger_spec.rb +6 -1
  34. data/spec/httparty/logger/logstash_formatter_spec.rb +44 -0
  35. data/spec/httparty/net_digest_auth_spec.rb +22 -22
  36. data/spec/httparty/parser_spec.rb +1 -1
  37. data/spec/httparty/request/body_spec.rb +57 -8
  38. data/spec/httparty/request_spec.rb +68 -13
  39. data/spec/httparty/response_spec.rb +32 -20
  40. data/spec/httparty/ssl_spec.rb +1 -1
  41. data/spec/httparty_spec.rb +28 -7
  42. data/website/css/common.css +1 -1
  43. metadata +25 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 255d54a6f0cad04486f09e887f8787725421fece
4
- data.tar.gz: d1b74c09b4ef625e5fc4ef791dc896c792a79e19
3
+ metadata.gz: d2efd166a0534991fe03c8f0ae6a72424c9e8c3d
4
+ data.tar.gz: 41ec81b8fbd9ae18ae51f8b93ce0a36e6b1174c8
5
5
  SHA512:
6
- metadata.gz: 6ba5c551dec574810d6e2fe84b639660d7f6c36b2ee667bcf91cae9eb978567d0a076eaff3d80886c0d8b9f225c018561d28f51a09ebbe7102b62fcff17ec8f1
7
- data.tar.gz: e5a1beb085744c890aff8cb42f238a1f2d5e041328d94cc2a5fafab75ca6f21385d4d4fa50a60c4033cedbcf611e10d4809c6337de2b98ce4a42fe32719773a4
6
+ metadata.gz: 53473b5f6b517e590cf7cd5937dee78c6493226ad6508865e9e57efe844b62218473e7137ea83a902de113221f53e0626f163eea39ac5d1094a65a7253e6a7ff
7
+ data.tar.gz: 4490aaf02f3bbf8eee7568bf62e37ea0c1d23caef64338b1dd09688efa8fe1b3b9047c3891d6e822f88b61b16ad9aa27618437d307b722d8b52e90f9016db8a9
@@ -0,0 +1,18 @@
1
+ ; This file is for unifying the coding style for different editors and IDEs.
2
+ ; More information at http://EditorConfig.org
3
+
4
+ root = true
5
+ [*]
6
+ end_of_line = lf
7
+ trim_trailing_whitespace = true
8
+
9
+ [**.rb]
10
+ indent_size = 2
11
+ indent_style = spaces
12
+ insert_final_newline = true
13
+
14
+ [**.xml]
15
+ trim_trailing_whitespace = false
16
+
17
+ [**.html]
18
+ trim_trailing_whitespace = false
data/.gitignore CHANGED
@@ -10,3 +10,4 @@ pkg/
10
10
  .rvmrc
11
11
  coverage
12
12
  *.gem
13
+ .idea
@@ -1,3 +1,14 @@
1
+
2
+ ## 0.16.3
3
+ * [Add Logstash-compatible formatter](https://github.com/jnunemaker/httparty/pull/612)
4
+ * [Add support for headers specified with symbols](https://github.com/jnunemaker/httparty/pull/622)
5
+ * [Fix response object marshalling](https://github.com/jnunemaker/httparty/pull/618)
6
+ * [Add ability to send multipart, without passing file](https://github.com/jnunemaker/httparty/pull/615)
7
+ * [Fix detection of content_type for multipart payload](https://github.com/jnunemaker/httparty/pull/616)
8
+ * [Process dynamic headers before making actual request](https://github.com/jnunemaker/httparty/pull/606)
9
+ * [Fix multipart uploads with ActionDispatch::Http::UploadedFile TempFile by using original_filename](https://github.com/jnunemaker/httparty/pull/598)
10
+ * [Added support for lock and unlock http requests](https://github.com/jnunemaker/httparty/pull/596)
11
+
1
12
  ## 0.16.2
2
13
 
3
14
  * [Support ActionDispatch::Http::UploadedFile again](https://github.com/jnunemaker/httparty/pull/585)
data/README.md CHANGED
@@ -64,7 +64,7 @@ httparty "https://api.stackexchange.com/2.2/questions?site=stackoverflow"
64
64
 
65
65
  * [Docs](https://github.com/jnunemaker/httparty/tree/master/docs)
66
66
  * https://groups.google.com/forum/#!forum/httparty-gem
67
- * http://rdoc.info/projects/jnunemaker/httparty
67
+ * https://www.rubydoc.info/github/jnunemaker/httparty
68
68
  * http://stackoverflow.com/questions/tagged/httparty
69
69
 
70
70
  ## Contributing
@@ -13,22 +13,22 @@
13
13
  * Creates a custom parser for XML using crack gem
14
14
  * Uses `get` request
15
15
 
16
- * [Create HTML Nokogiri parser](nokogiri_html_parser.rb)
16
+ * [Create HTML Nokogiri parser](nokogiri_html_parser.rb)
17
17
  * Adds Html as a format
18
18
  * passed the body of request to Nokogiri
19
-
19
+
20
20
  * [More Custom Parsers](custom_parsers.rb)
21
21
  * Create an additional parser for atom or make it the ONLY parser
22
-
22
+
23
23
  * [Basic Auth, Delicious](delicious.rb)
24
24
  * Basic Auth, shows how to merge those into options
25
25
  * Uses `get` requests
26
-
26
+
27
27
  * [Passing Headers, User Agent](headers_and_user_agents.rb)
28
28
  * Use the class method of Httparty
29
29
  * Pass the User-Agent in the headers
30
30
  * Uses `get` requests
31
-
31
+
32
32
  * [Basic Post Request](basic.rb)
33
33
  * Httparty included into poro class
34
34
  * Uses `post` requests
@@ -36,7 +36,7 @@
36
36
  * [Access Rubyurl Shortener](rubyurl.rb)
37
37
  * Httparty included into poro class
38
38
  * Uses `post` requests
39
-
39
+
40
40
  * [Add a custom log file](logging.rb)
41
41
  * create a log file and have httparty log requests
42
42
 
@@ -44,23 +44,23 @@
44
44
  * Httparty included into poro class
45
45
  * Creates methods for different endpoints
46
46
  * Uses `get` requests
47
-
47
+
48
48
  * [Accessing Tripit](tripit_sign_in.rb)
49
49
  * Httparty included into poro class
50
50
  * Example of using `debug_output` to see headers/urls passed
51
51
  * Getting and using Cookies
52
52
  * Uses `get` requests
53
-
53
+
54
54
  * [Accessing Twitter](twitter.rb)
55
55
  * Httparty included into poro class
56
56
  * Basic Auth
57
- * Loads settings from a config file
57
+ * Loads settings from a config file
58
58
  * Uses `get` requests
59
59
  * Uses `post` requests
60
-
60
+
61
61
  * [Accessing WhoIsMyRep](whoismyrep.rb)
62
62
  * Httparty included into poro class
63
- * Uses `get` requests
63
+ * Uses `get` requests
64
64
  * Two ways to pass params to get, inline on the url or in query hash
65
65
 
66
66
  * [Rescue Json Error](rescue_json.rb)
@@ -70,3 +70,14 @@
70
70
  * Uses `get` requests
71
71
  * Uses `stream_body` mode
72
72
  * Download file without using the memory
73
+
74
+ * [Microsoft graph](microsoft_graph.rb)
75
+ * Basic Auth
76
+ * Uses `post` requests
77
+ * Uses multipart
78
+
79
+ * [Multipart](multipart.rb)
80
+ * Multipart data upload _(with and without file)_
81
+
82
+ * [Uploading File](body_stream.rb)
83
+ * Uses `body_stream` to upload file
@@ -0,0 +1,14 @@
1
+ # To upload file to a server use :body_stream
2
+
3
+ HTTParty.put(
4
+ 'http://localhost:3000/train',
5
+ body_stream: File.open('sample_configs/config_train_server_md.yml', 'r')
6
+ )
7
+
8
+
9
+ # Actually, it works with any IO object
10
+
11
+ HTTParty.put(
12
+ 'http://localhost:3000/train',
13
+ body_stream: StringIO.new('foo')
14
+ )
@@ -0,0 +1,52 @@
1
+ require 'httparty'
2
+
3
+ class MicrosoftGraph
4
+ MS_BASE_URL = "https://login.microsoftonline.com".freeze
5
+ TOKEN_REQUEST_PATH = "oauth2/v2.0/token".freeze
6
+
7
+ def initialize(tenant_id)
8
+ @tenant_id = tenant_id
9
+ end
10
+
11
+ # Make a request to the Microsoft Graph API, for instance https://graph.microsoft.com/v1.0/users
12
+ def request(url)
13
+ return false unless (token = bearer_token)
14
+
15
+ response = HTTParty.get(
16
+ url,
17
+ headers: {
18
+ Authorization: "Bearer #{token}"
19
+ }
20
+ )
21
+
22
+ return false unless response.code == 200
23
+
24
+ return JSON.parse(response.body)
25
+ end
26
+
27
+ private
28
+
29
+ # A post to the Microsoft Graph to get a bearer token for the specified tenant. In this example
30
+ # our Rails application has already been given permission to request these tokens by the admin of
31
+ # the specified tenant_id.
32
+ #
33
+ # See here for more information https://developer.microsoft.com/en-us/graph/docs/concepts/auth_v2_service
34
+ #
35
+ # This request also makes use of the multipart/form-data post body.
36
+ def bearer_token
37
+ response = HTTParty.post(
38
+ "#{MS_BASE_URL}/#{@tenant_id}/#{TOKEN_REQUEST_PATH}",
39
+ multipart: true,
40
+ body: {
41
+ client_id: Rails.application.credentials[Rails.env.to_sym][:microsoft_client_id],
42
+ client_secret: Rails.application.credentials[Rails.env.to_sym][:microsoft_client_secret],
43
+ scope: 'https://graph.microsoft.com/.default',
44
+ grant_type: 'client_credentials'
45
+ }
46
+ )
47
+
48
+ return false unless response.code == 200
49
+
50
+ JSON.parse(response.body)['access_token']
51
+ end
52
+ end
@@ -0,0 +1,22 @@
1
+ # If you are uploading file in params, multipart will used as content-type automatically
2
+
3
+ HTTParty.post(
4
+ 'http://localhost:3000/user',
5
+ body: {
6
+ name: 'Foo Bar',
7
+ email: 'example@email.com',
8
+ avatar: File.open('/full/path/to/avatar.jpg')
9
+ }
10
+ )
11
+
12
+
13
+ # However, you can force it yourself
14
+
15
+ HTTParty.post(
16
+ 'http://localhost:3000/user',
17
+ multipart: true,
18
+ body: {
19
+ name: 'Foo Bar',
20
+ email: 'example@email.com'
21
+ }
22
+ )
@@ -95,7 +95,7 @@ module DigestAuthenticationUsingMD5Sess
95
95
  def self.extended(base)
96
96
  base.custom_headers["WWW-Authenticate"] = %(Digest realm="#{REALM}",qop="#{QOP}",algorithm="MD5-sess",nonce="#{NONCE}",opaque="opaque"')
97
97
  end
98
-
98
+
99
99
  def process(request, response)
100
100
  if authorized?(request)
101
101
  super
@@ -103,11 +103,11 @@ module DigestAuthenticationUsingMD5Sess
103
103
  reply_with(response, 401, "Incorrect. You have 20 seconds to comply.")
104
104
  end
105
105
  end
106
-
106
+
107
107
  def md5(str)
108
108
  Digest::MD5.hexdigest(str)
109
109
  end
110
-
110
+
111
111
  def authorized?(request)
112
112
  auth = request.params["HTTP_AUTHORIZATION"]
113
113
  params = {}
@@ -9,13 +9,14 @@ Gem::Specification.new do |s|
9
9
  s.licenses = ['MIT']
10
10
  s.authors = ["John Nunemaker", "Sandro Turriate"]
11
11
  s.email = ["nunemaker@gmail.com"]
12
- s.homepage = "http://jnunemaker.github.com/httparty"
12
+ s.homepage = "https://github.com/jnunemaker/httparty"
13
13
  s.summary = 'Makes http fun! Also, makes consuming restful web services dead easy.'
14
14
  s.description = 'Makes http fun! Also, makes consuming restful web services dead easy.'
15
15
 
16
16
  s.required_ruby_version = '>= 2.0.0'
17
17
 
18
18
  s.add_dependency 'multi_xml', ">= 0.5.2"
19
+ s.add_dependency('mime-types', "~> 3.0")
19
20
 
20
21
  # If this line is removed, all hard partying will cease.
21
22
  s.post_install_message = "When you HTTParty, you must party hard!"
@@ -4,6 +4,7 @@ require 'net/https'
4
4
  require 'uri'
5
5
  require 'zlib'
6
6
  require 'multi_xml'
7
+ require 'mime/types'
7
8
  require 'json'
8
9
  require 'csv'
9
10
 
@@ -40,6 +41,7 @@ module HTTParty
40
41
  # [:+local_port:] Local port to bind to before connecting.
41
42
  # [:+body_stream:] Allow streaming to a REST server to specify a body_stream.
42
43
  # [:+stream_body:] Allow for streaming large files without loading them into memory.
44
+ # [:+multipart:] Force content-type to be multipart
43
45
  #
44
46
  # 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:
45
47
  # * :+base_uri+: see HTTParty::ClassMethods.base_uri.
@@ -546,6 +548,14 @@ module HTTParty
546
548
  perform_request Net::HTTP::Mkcol, path, options, &block
547
549
  end
548
550
 
551
+ def lock(path, options = {}, &block)
552
+ perform_request Net::HTTP::Lock, path, options, &block
553
+ end
554
+
555
+ def unlock(path, options = {}, &block)
556
+ perform_request Net::HTTP::Unlock, path, options, &block
557
+ end
558
+
549
559
  attr_reader :default_options
550
560
 
551
561
  private
@@ -566,6 +576,14 @@ module HTTParty
566
576
  def process_headers(options)
567
577
  if options[:headers] && headers.any?
568
578
  options[:headers] = headers.merge(options[:headers])
579
+ options[:headers] = Utils.stringify_keys(process_dynamic_headers(options[:headers]))
580
+ end
581
+ end
582
+
583
+ def process_dynamic_headers(headers)
584
+ headers.each_with_object({}) do |header, processed_headers|
585
+ key, value = header
586
+ processed_headers[key] = value.respond_to?(:call) ? value.call : value
569
587
  end
570
588
  end
571
589
 
@@ -577,7 +595,8 @@ module HTTParty
577
595
 
578
596
  def validate_format
579
597
  if format && parser.respond_to?(:supports_format?) && !parser.supports_format?(format)
580
- raise UnsupportedFormat, "'#{format.inspect}' Must be one of: #{parser.supported_formats.map(&:to_s).sort.join(', ')}"
598
+ supported_format_names = parser.supported_formats.map(&:to_s).sort.join(', ')
599
+ raise UnsupportedFormat, "'#{format.inspect}' Must be one of: #{supported_format_names}"
581
600
  end
582
601
  end
583
602
  end
@@ -635,6 +654,7 @@ module HTTParty
635
654
  end
636
655
 
637
656
  require 'httparty/hash_conversions'
657
+ require 'httparty/utils'
638
658
  require 'httparty/exceptions'
639
659
  require 'httparty/parser'
640
660
  require 'httparty/request'
@@ -4,7 +4,7 @@ module HTTParty
4
4
  # == Custom Connection Factories
5
5
  #
6
6
  # If you like to implement your own connection adapter, subclassing
7
- # HTTPParty::ConnectionAdapter will make it easier. Just override
7
+ # HTTParty::ConnectionAdapter will make it easier. Just override
8
8
  # the #connection method. The uri and options attributes will have
9
9
  # all the info you need to construct your http connection. Whatever
10
10
  # you return from your connection method needs to adhere to the
@@ -38,12 +38,12 @@ module HTTParty
38
38
  # in the #options attribute. It is up to you to interpret them within your
39
39
  # connection adapter. Take a look at the implementation of
40
40
  # HTTParty::ConnectionAdapter#connection for examples of how they are used.
41
- # The keys used in options are
41
+ # The keys used in options are
42
42
  # * :+timeout+: timeout in seconds
43
43
  # * :+open_timeout+: http connection open_timeout in seconds, overrides timeout if set
44
44
  # * :+read_timeout+: http connection read_timeout in seconds, overrides timeout if set
45
45
  # * :+debug_output+: see HTTParty::ClassMethods.debug_output.
46
- # * :+cert_store+: contains certificate data. see method 'attach_ssl_certificates'
46
+ # * :+cert_store+: contains certificate data. see method 'attach_ssl_certificates'
47
47
  # * :+pem+: contains pem client certificate data. see method 'attach_ssl_certificates'
48
48
  # * :+p12+: contains PKCS12 client client certificate data. see method 'attach_ssl_certificates'
49
49
  # * :+verify+: verify the server’s certificate against the ca certificate.
@@ -91,7 +91,14 @@ module HTTParty
91
91
  host = clean_host(uri.host)
92
92
  port = uri.port || (uri.scheme == 'https' ? 443 : 80)
93
93
  if options.key?(:http_proxyaddr)
94
- http = Net::HTTP.new(host, port, options[:http_proxyaddr], options[:http_proxyport], options[:http_proxyuser], options[:http_proxypass])
94
+ http = Net::HTTP.new(
95
+ host,
96
+ port,
97
+ options[:http_proxyaddr],
98
+ options[:http_proxyport],
99
+ options[:http_proxyuser],
100
+ options[:http_proxypass]
101
+ )
95
102
  else
96
103
  http = Net::HTTP.new(host, port)
97
104
  end
@@ -39,7 +39,9 @@ module HTTParty
39
39
  if value.empty?
40
40
  normalized_keys << ["#{key}[]", '']
41
41
  else
42
- normalized_keys = value.to_ary.flat_map { |element| normalize_keys("#{key}[]", element) }
42
+ normalized_keys = value.to_ary.flat_map do |element|
43
+ normalize_keys("#{key}[]", element)
44
+ end
43
45
  end
44
46
  elsif value.respond_to?(:to_hash)
45
47
  stack << [key, value.to_hash]
@@ -52,7 +54,9 @@ module HTTParty
52
54
  if child_value.respond_to?(:to_hash)
53
55
  stack << ["#{parent}[#{child_key}]", child_value.to_hash]
54
56
  elsif child_value.respond_to?(:to_ary)
55
- child_value.to_ary.each { |v| normalized_keys << normalize_keys("#{parent}[#{child_key}][]", v).flatten }
57
+ child_value.to_ary.each do |v|
58
+ normalized_keys << normalize_keys("#{parent}[#{child_key}][]", v).flatten
59
+ end
56
60
  else
57
61
  normalized_keys << normalize_keys("#{parent}[#{child_key}]", child_value).flatten
58
62
  end
@@ -3,7 +3,7 @@ module HTTParty
3
3
  class ApacheFormatter #:nodoc:
4
4
  TAG_NAME = HTTParty.name
5
5
 
6
- attr_accessor :level, :logger, :current_time
6
+ attr_accessor :level, :logger
7
7
 
8
8
  def initialize(logger, level)
9
9
  @logger = logger
@@ -11,11 +11,34 @@ module HTTParty
11
11
  end
12
12
 
13
13
  def format(request, response)
14
- current_time = Time.now.strftime("%Y-%m-%d %H:%M:%S %z")
15
- http_method = request.http_method.name.split("::").last.upcase
16
- path = request.path.to_s
17
- content_length = response.respond_to?(:headers) ? response.headers['Content-Length'] : response['Content-Length']
18
- @logger.send @level, "[#{TAG_NAME}] [#{current_time}] #{response.code} \"#{http_method} #{path}\" #{content_length || '-'} "
14
+ @request = request
15
+ @response = response
16
+
17
+ logger.public_send level, message
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :request, :response
23
+
24
+ def message
25
+ "[#{TAG_NAME}] [#{current_time}] #{response.code} \"#{http_method} #{path}\" #{content_length || '-'} "
26
+ end
27
+
28
+ def current_time
29
+ Time.now.strftime("%Y-%m-%d %H:%M:%S %z")
30
+ end
31
+
32
+ def http_method
33
+ request.http_method.name.split("::").last.upcase
34
+ end
35
+
36
+ def path
37
+ request.path.to_s
38
+ end
39
+
40
+ def content_length
41
+ response.respond_to?(:headers) ? response.headers['Content-Length'] : response['Content-Length']
19
42
  end
20
43
  end
21
44
  end