httparty 0.14.0 → 0.20.0

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 (101) hide show
  1. checksums.yaml +5 -5
  2. data/.editorconfig +18 -0
  3. data/.github/workflows/ci.yml +23 -0
  4. data/.gitignore +2 -0
  5. data/.rubocop_todo.yml +1 -1
  6. data/{History → Changelog.md} +216 -63
  7. data/Gemfile +6 -1
  8. data/README.md +8 -8
  9. data/bin/httparty +3 -1
  10. data/docs/README.md +108 -37
  11. data/examples/README.md +34 -12
  12. data/examples/aaws.rb +7 -3
  13. data/examples/body_stream.rb +14 -0
  14. data/examples/crack.rb +1 -1
  15. data/examples/custom_parsers.rb +5 -1
  16. data/examples/delicious.rb +4 -4
  17. data/examples/headers_and_user_agents.rb +7 -3
  18. data/examples/idn.rb +10 -0
  19. data/examples/logging.rb +4 -4
  20. data/examples/microsoft_graph.rb +52 -0
  21. data/examples/multipart.rb +22 -0
  22. data/examples/peer_cert.rb +9 -0
  23. data/examples/stackexchange.rb +1 -1
  24. data/examples/stream_download.rb +26 -0
  25. data/examples/tripit_sign_in.rb +1 -1
  26. data/examples/twitter.rb +2 -2
  27. data/examples/whoismyrep.rb +1 -1
  28. data/httparty.gemspec +7 -4
  29. data/lib/httparty/connection_adapter.rb +73 -16
  30. data/lib/httparty/cookie_hash.rb +10 -8
  31. data/lib/httparty/decompressor.rb +92 -0
  32. data/lib/httparty/exceptions.rb +4 -1
  33. data/lib/httparty/hash_conversions.rb +30 -12
  34. data/lib/httparty/headers_processor.rb +32 -0
  35. data/lib/httparty/logger/apache_formatter.rb +31 -6
  36. data/lib/httparty/logger/curl_formatter.rb +9 -7
  37. data/lib/httparty/logger/logger.rb +5 -1
  38. data/lib/httparty/logger/logstash_formatter.rb +61 -0
  39. data/lib/httparty/module_inheritable_attributes.rb +6 -4
  40. data/lib/httparty/net_digest_auth.rb +19 -19
  41. data/lib/httparty/parser.rb +25 -14
  42. data/lib/httparty/request/body.rb +98 -0
  43. data/lib/httparty/request/multipart_boundary.rb +13 -0
  44. data/lib/httparty/request.rb +137 -110
  45. data/lib/httparty/response/headers.rb +23 -19
  46. data/lib/httparty/response.rb +81 -22
  47. data/lib/httparty/response_fragment.rb +21 -0
  48. data/lib/httparty/text_encoder.rb +72 -0
  49. data/lib/httparty/utils.rb +13 -0
  50. data/lib/httparty/version.rb +3 -1
  51. data/lib/httparty.rb +79 -30
  52. data/website/css/common.css +1 -1
  53. metadata +37 -103
  54. data/.travis.yml +0 -9
  55. data/features/basic_authentication.feature +0 -20
  56. data/features/command_line.feature +0 -95
  57. data/features/deals_with_http_error_codes.feature +0 -26
  58. data/features/digest_authentication.feature +0 -30
  59. data/features/handles_compressed_responses.feature +0 -27
  60. data/features/handles_multiple_formats.feature +0 -57
  61. data/features/steps/env.rb +0 -27
  62. data/features/steps/httparty_response_steps.rb +0 -56
  63. data/features/steps/httparty_steps.rb +0 -43
  64. data/features/steps/mongrel_helper.rb +0 -127
  65. data/features/steps/remote_service_steps.rb +0 -92
  66. data/features/supports_read_timeout_option.feature +0 -13
  67. data/features/supports_redirection.feature +0 -22
  68. data/features/supports_timeout_option.feature +0 -13
  69. data/spec/fixtures/delicious.xml +0 -23
  70. data/spec/fixtures/empty.xml +0 -0
  71. data/spec/fixtures/google.html +0 -3
  72. data/spec/fixtures/ssl/generate.sh +0 -29
  73. data/spec/fixtures/ssl/generated/1fe462c2.0 +0 -16
  74. data/spec/fixtures/ssl/generated/bogushost.crt +0 -13
  75. data/spec/fixtures/ssl/generated/ca.crt +0 -16
  76. data/spec/fixtures/ssl/generated/ca.key +0 -15
  77. data/spec/fixtures/ssl/generated/selfsigned.crt +0 -14
  78. data/spec/fixtures/ssl/generated/server.crt +0 -13
  79. data/spec/fixtures/ssl/generated/server.key +0 -15
  80. data/spec/fixtures/ssl/openssl-exts.cnf +0 -9
  81. data/spec/fixtures/twitter.csv +0 -2
  82. data/spec/fixtures/twitter.json +0 -1
  83. data/spec/fixtures/twitter.xml +0 -403
  84. data/spec/fixtures/undefined_method_add_node_for_nil.xml +0 -2
  85. data/spec/httparty/connection_adapter_spec.rb +0 -495
  86. data/spec/httparty/cookie_hash_spec.rb +0 -100
  87. data/spec/httparty/exception_spec.rb +0 -45
  88. data/spec/httparty/hash_conversions_spec.rb +0 -49
  89. data/spec/httparty/logger/apache_formatter_spec.rb +0 -41
  90. data/spec/httparty/logger/curl_formatter_spec.rb +0 -119
  91. data/spec/httparty/logger/logger_spec.rb +0 -38
  92. data/spec/httparty/net_digest_auth_spec.rb +0 -240
  93. data/spec/httparty/parser_spec.rb +0 -173
  94. data/spec/httparty/request_spec.rb +0 -1183
  95. data/spec/httparty/response_spec.rb +0 -291
  96. data/spec/httparty/ssl_spec.rb +0 -74
  97. data/spec/httparty_spec.rb +0 -872
  98. data/spec/spec_helper.rb +0 -59
  99. data/spec/support/ssl_test_helper.rb +0 -47
  100. data/spec/support/ssl_test_server.rb +0 -80
  101. data/spec/support/stub_response.rb +0 -49
@@ -1,31 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'delegate'
4
+
1
5
  module HTTParty
2
6
  class Response #:nodoc:
3
- class Headers
7
+ class Headers < ::SimpleDelegator
4
8
  include ::Net::HTTPHeader
5
9
 
6
- def initialize(header = {})
7
- @header = header
10
+ def initialize(header_values = nil)
11
+ @header = {}
12
+ if header_values
13
+ header_values.each_pair do |k,v|
14
+ if v.is_a?(Array)
15
+ v.each do |sub_v|
16
+ add_field(k, sub_v)
17
+ end
18
+ else
19
+ add_field(k, v)
20
+ end
21
+ end
22
+ end
23
+ super(@header)
8
24
  end
9
25
 
10
26
  def ==(other)
11
- @header == other
12
- end
13
-
14
- def inspect
15
- @header.inspect
16
- end
17
-
18
- def method_missing(name, *args, &block)
19
- if @header.respond_to?(name)
20
- @header.send(name, *args, &block)
21
- else
22
- super
27
+ if other.is_a?(::Net::HTTPHeader)
28
+ @header == other.instance_variable_get(:@header)
29
+ elsif other.is_a?(Hash)
30
+ @header == other || @header == Headers.new(other).instance_variable_get(:@header)
23
31
  end
24
32
  end
25
-
26
- def respond_to?(method, include_all = false)
27
- super || @header.respond_to?(method, include_all)
28
- end
29
33
  end
30
34
  end
31
35
  end
@@ -1,9 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HTTParty
2
- class Response < BasicObject
4
+ class Response < Object
3
5
  def self.underscore(string)
4
6
  string.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z])([A-Z])/, '\1_\2').downcase
5
7
  end
6
8
 
9
+ def self._load(data)
10
+ req, resp, parsed_resp, resp_body = Marshal.load(data)
11
+
12
+ new(req, resp, -> { parsed_resp }, body: resp_body)
13
+ end
14
+
7
15
  attr_reader :request, :response, :body, :headers
8
16
 
9
17
  def initialize(request, response, parsed_block, options = {})
@@ -14,7 +22,11 @@ module HTTParty
14
22
  @headers = Headers.new(response.to_hash)
15
23
 
16
24
  if request.options[:logger]
17
- logger = ::HTTParty::Logger.build(request.options[:logger], request.options[:log_level], request.options[:log_format])
25
+ logger = ::HTTParty::Logger.build(
26
+ request.options[:logger],
27
+ request.options[:log_level],
28
+ request.options[:log_format]
29
+ )
18
30
  logger.format(request, self)
19
31
  end
20
32
 
@@ -25,53 +37,87 @@ module HTTParty
25
37
  @parsed_response ||= @parsed_block.call
26
38
  end
27
39
 
28
- def class
29
- Response
30
- end
31
-
32
- def is_a?(klass)
33
- self.class == klass || self.class < klass
34
- end
35
-
36
- alias_method :kind_of?, :is_a?
37
-
38
40
  def code
39
41
  response.code.to_i
40
42
  end
41
43
 
44
+ def http_version
45
+ response.http_version
46
+ end
47
+
42
48
  def tap
43
49
  yield self
44
50
  self
45
51
  end
46
52
 
47
53
  def inspect
48
- inspect_id = ::Kernel::format "%x", (object_id * 2)
54
+ inspect_id = ::Kernel::format '%x', (object_id * 2)
49
55
  %(#<#{self.class}:0x#{inspect_id} parsed_response=#{parsed_response.inspect}, @response=#{response.inspect}, @headers=#{headers.inspect}>)
50
56
  end
51
57
 
52
- RESPOND_TO_METHODS = [:request, :response, :parsed_response, :body, :headers]
53
-
54
58
  CODES_TO_OBJ = ::Net::HTTPResponse::CODE_CLASS_TO_OBJ.merge ::Net::HTTPResponse::CODE_TO_OBJ
55
59
 
56
60
  CODES_TO_OBJ.each do |response_code, klass|
57
- name = klass.name.sub("Net::HTTP", '')
61
+ name = klass.name.sub('Net::HTTP', '')
58
62
  name = "#{underscore(name)}?".to_sym
59
63
 
60
- RESPOND_TO_METHODS << name
61
-
62
64
  define_method(name) do
63
65
  klass === response
64
66
  end
65
67
  end
66
68
 
67
69
  # Support old multiple_choice? method from pre 2.0.0 era.
68
- if ::RUBY_VERSION >= "2.0.0" && ::RUBY_PLATFORM != "java"
70
+ if ::RUBY_VERSION >= '2.0.0' && ::RUBY_PLATFORM != 'java'
69
71
  alias_method :multiple_choice?, :multiple_choices?
70
72
  end
71
73
 
72
- def respond_to?(name, include_all = false)
73
- return true if RESPOND_TO_METHODS.include?(name)
74
- parsed_response.respond_to?(name, include_all) || response.respond_to?(name, include_all)
74
+ # Support old status codes method from pre 2.6.0 era.
75
+ if ::RUBY_VERSION >= '2.6.0' && ::RUBY_PLATFORM != 'java'
76
+ alias_method :gateway_time_out?, :gateway_timeout?
77
+ alias_method :request_entity_too_large?, :payload_too_large?
78
+ alias_method :request_time_out?, :request_timeout?
79
+ alias_method :request_uri_too_long?, :uri_too_long?
80
+ alias_method :requested_range_not_satisfiable?, :range_not_satisfiable?
81
+ end
82
+
83
+ def nil?
84
+ warn_about_nil_deprecation
85
+ response.nil? || response.body.nil? || response.body.empty?
86
+ end
87
+
88
+ def to_s
89
+ if !response.nil? && !response.body.nil? && response.body.respond_to?(:to_s)
90
+ response.body.to_s
91
+ else
92
+ inspect
93
+ end
94
+ end
95
+
96
+ def pretty_print(pp)
97
+ if !parsed_response.nil? && parsed_response.respond_to?(:pretty_print)
98
+ parsed_response.pretty_print(pp)
99
+ else
100
+ super
101
+ end
102
+ end
103
+
104
+ def display(port=$>)
105
+ if !parsed_response.nil? && parsed_response.respond_to?(:display)
106
+ parsed_response.display(port)
107
+ elsif !response.nil? && !response.body.nil? && response.body.respond_to?(:display)
108
+ response.body.display(port)
109
+ else
110
+ port.write(inspect)
111
+ end
112
+ end
113
+
114
+ def respond_to_missing?(name, *args)
115
+ return true if super
116
+ parsed_response.respond_to?(name) || response.respond_to?(name)
117
+ end
118
+
119
+ def _dump(_level)
120
+ Marshal.dump([request, response, parsed_response, body])
75
121
  end
76
122
 
77
123
  protected
@@ -91,6 +137,19 @@ module HTTParty
91
137
  ::Kernel.raise ::HTTParty::ResponseError.new(@response), "Code #{code} - #{body}"
92
138
  end
93
139
  end
140
+
141
+ private
142
+
143
+ def warn_about_nil_deprecation
144
+ trace_line = caller.reject { |line| line.include?('httparty') }.first
145
+ warning = "[DEPRECATION] HTTParty will no longer override `response#nil?`. " \
146
+ "This functionality will be removed in future versions. " \
147
+ "Please, add explicit check `response.body.nil? || response.body.empty?`. " \
148
+ "For more info refer to: https://github.com/jnunemaker/httparty/issues/568\n" \
149
+ "#{trace_line}"
150
+
151
+ warn(warning)
152
+ end
94
153
  end
95
154
  end
96
155
 
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'delegate'
4
+
5
+ module HTTParty
6
+ # Allow access to http_response and code by delegation on fragment
7
+ class ResponseFragment < SimpleDelegator
8
+ attr_reader :http_response, :connection
9
+
10
+ def code
11
+ @http_response.code.to_i
12
+ end
13
+
14
+ def initialize(fragment, http_response, connection)
15
+ @fragment = fragment
16
+ @http_response = http_response
17
+ @connection = connection
18
+ super fragment
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTParty
4
+ class TextEncoder
5
+ attr_reader :text, :content_type, :assume_utf16_is_big_endian
6
+
7
+ def initialize(text, assume_utf16_is_big_endian: true, content_type: nil)
8
+ @text = text.dup
9
+ @content_type = content_type
10
+ @assume_utf16_is_big_endian = assume_utf16_is_big_endian
11
+ end
12
+
13
+ def call
14
+ if can_encode?
15
+ encoded_text
16
+ else
17
+ text
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def can_encode?
24
+ ''.respond_to?(:encoding) && charset
25
+ end
26
+
27
+ def encoded_text
28
+ if 'utf-16'.casecmp(charset) == 0
29
+ encode_utf_16
30
+ else
31
+ encode_with_ruby_encoding
32
+ end
33
+ end
34
+
35
+ def encode_utf_16
36
+ if text.bytesize >= 2
37
+ if text.getbyte(0) == 0xFF && text.getbyte(1) == 0xFE
38
+ return text.force_encoding('UTF-16LE')
39
+ elsif text.getbyte(0) == 0xFE && text.getbyte(1) == 0xFF
40
+ return text.force_encoding('UTF-16BE')
41
+ end
42
+ end
43
+
44
+ if assume_utf16_is_big_endian # option
45
+ text.force_encoding('UTF-16BE')
46
+ else
47
+ text.force_encoding('UTF-16LE')
48
+ end
49
+ end
50
+
51
+ def encode_with_ruby_encoding
52
+ # NOTE: This will raise an argument error if the
53
+ # charset does not exist
54
+ encoding = Encoding.find(charset)
55
+ text.force_encoding(encoding.to_s)
56
+ rescue ArgumentError
57
+ text
58
+ end
59
+
60
+ def charset
61
+ return nil if content_type.nil?
62
+
63
+ if (matchdata = content_type.match(/;\s*charset\s*=\s*([^=,;"\s]+)/i))
64
+ return matchdata.captures.first
65
+ end
66
+
67
+ if (matchdata = content_type.match(/;\s*charset\s*=\s*"((\\.|[^\\"])+)"/i))
68
+ return matchdata.captures.first.gsub(/\\(.)/, '\1')
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTParty
4
+ module Utils
5
+ def self.stringify_keys(hash)
6
+ return hash.transform_keys(&:to_s) if hash.respond_to?(:transform_keys)
7
+
8
+ hash.each_with_object({}) do |(key, value), new_hash|
9
+ new_hash[key.to_s] = value
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HTTParty
2
- VERSION = "0.14.0"
4
+ VERSION = '0.20.0'
3
5
  end
data/lib/httparty.rb CHANGED
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
2
4
  require 'net/http'
3
5
  require 'net/https'
4
6
  require 'uri'
5
7
  require 'zlib'
6
8
  require 'multi_xml'
9
+ require 'mime/types'
7
10
  require 'json'
8
11
  require 'csv'
9
- require 'erb'
10
12
 
11
13
  require 'httparty/module_inheritable_attributes'
12
14
  require 'httparty/cookie_hash'
@@ -14,6 +16,11 @@ require 'httparty/net_digest_auth'
14
16
  require 'httparty/version'
15
17
  require 'httparty/connection_adapter'
16
18
  require 'httparty/logger/logger'
19
+ require 'httparty/request/body'
20
+ require 'httparty/response_fragment'
21
+ require 'httparty/decompressor'
22
+ require 'httparty/text_encoder'
23
+ require 'httparty/headers_processor'
17
24
 
18
25
  # @see HTTParty::ClassMethods
19
26
  module HTTParty
@@ -22,8 +29,8 @@ module HTTParty
22
29
  base.send :include, ModuleInheritableAttributes
23
30
  base.send(:mattr_inheritable, :default_options)
24
31
  base.send(:mattr_inheritable, :default_cookies)
25
- base.instance_variable_set("@default_options", {})
26
- base.instance_variable_set("@default_cookies", CookieHash.new)
32
+ base.instance_variable_set(:@default_options, {})
33
+ base.instance_variable_set(:@default_cookies, CookieHash.new)
27
34
  end
28
35
 
29
36
  # == Common Request Options
@@ -37,10 +44,11 @@ module HTTParty
37
44
  # [:+limit+:] Maximum number of redirects to follow. Takes precedences over :+no_follow+.
38
45
  # [:+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.
39
46
  # [:+timeout+:] Timeout for opening connection and reading data.
40
- # [:+local_host:] Local address to bind to before connecting.
41
- # [:+local_port:] Local port to bind to before connecting.
42
- # [:+body_steam:] Allow streaming to a REST server to specify a body_stream.
43
- # [:+stream_body:] Allow for streaming large files without loading them into memory.
47
+ # [:+local_host+:] Local address to bind to before connecting.
48
+ # [:+local_port+:] Local port to bind to before connecting.
49
+ # [:+body_stream+:] Allow streaming to a REST server to specify a body_stream.
50
+ # [:+stream_body+:] Allow for streaming large files without loading them into memory.
51
+ # [:+multipart+:] Force content-type to be multipart
44
52
  #
45
53
  # 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:
46
54
  # * :+base_uri+: see HTTParty::ClassMethods.base_uri.
@@ -128,7 +136,7 @@ module HTTParty
128
136
  end
129
137
 
130
138
  # Do not send rails style query strings.
131
- # Specically, don't use bracket notation when sending an array
139
+ # Specifically, don't use bracket notation when sending an array
132
140
  #
133
141
  # For a query:
134
142
  # get '/', query: {selected_ids: [1,2,3]}
@@ -169,9 +177,9 @@ module HTTParty
169
177
  # include HTTParty
170
178
  # default_timeout 10
171
179
  # end
172
- def default_timeout(t)
173
- raise ArgumentError, 'Timeout must be an integer or float' unless t && (t.is_a?(Integer) || t.is_a?(Float))
174
- default_options[:timeout] = t
180
+ def default_timeout(value)
181
+ validate_timeout_argument(__method__, value)
182
+ default_options[:timeout] = value
175
183
  end
176
184
 
177
185
  # Allows setting a default open_timeout for all HTTP calls in seconds
@@ -180,9 +188,9 @@ module HTTParty
180
188
  # include HTTParty
181
189
  # open_timeout 10
182
190
  # end
183
- def open_timeout(t)
184
- raise ArgumentError, 'open_timeout must be an integer or float' unless t && (t.is_a?(Integer) || t.is_a?(Float))
185
- default_options[:open_timeout] = t
191
+ def open_timeout(value)
192
+ validate_timeout_argument(__method__, value)
193
+ default_options[:open_timeout] = value
186
194
  end
187
195
 
188
196
  # Allows setting a default read_timeout for all HTTP calls in seconds
@@ -191,11 +199,24 @@ module HTTParty
191
199
  # include HTTParty
192
200
  # read_timeout 10
193
201
  # end
194
- def read_timeout(t)
195
- raise ArgumentError, 'read_timeout must be an integer or float' unless t && (t.is_a?(Integer) || t.is_a?(Float))
196
- default_options[:read_timeout] = t
202
+ def read_timeout(value)
203
+ validate_timeout_argument(__method__, value)
204
+ default_options[:read_timeout] = value
205
+ end
206
+
207
+ # Allows setting a default write_timeout for all HTTP calls in seconds
208
+ # Supported by Ruby > 2.6.0
209
+ #
210
+ # class Foo
211
+ # include HTTParty
212
+ # write_timeout 10
213
+ # end
214
+ def write_timeout(value)
215
+ validate_timeout_argument(__method__, value)
216
+ default_options[:write_timeout] = value
197
217
  end
198
218
 
219
+
199
220
  # Set an output stream for debugging, defaults to $stderr.
200
221
  # The output stream is passed on to Net::HTTP#set_debug_output.
201
222
  #
@@ -213,10 +234,14 @@ module HTTParty
213
234
  # include HTTParty
214
235
  # headers 'Accept' => 'text/html'
215
236
  # end
216
- def headers(h = {})
217
- raise ArgumentError, 'Headers must be an object which responds to #to_hash' unless h.respond_to?(:to_hash)
218
- default_options[:headers] ||= {}
219
- default_options[:headers].merge!(h.to_hash)
237
+ def headers(h = nil)
238
+ if h
239
+ raise ArgumentError, 'Headers must be an object which responds to #to_hash' unless h.respond_to?(:to_hash)
240
+ default_options[:headers] ||= {}
241
+ default_options[:headers].merge!(h.to_hash)
242
+ else
243
+ default_options[:headers] || {}
244
+ end
220
245
  end
221
246
 
222
247
  def cookies(h = {})
@@ -377,6 +402,22 @@ module HTTParty
377
402
  default_options[:ssl_version] = version
378
403
  end
379
404
 
405
+ # Deactivate automatic decompression of the response body.
406
+ # This will require you to explicitly handle body decompression
407
+ # by inspecting the Content-Encoding response header.
408
+ #
409
+ # Refer to docs/README.md "HTTP Compression" section for
410
+ # further details.
411
+ #
412
+ # @example
413
+ # class Foo
414
+ # include HTTParty
415
+ # skip_decompression
416
+ # end
417
+ def skip_decompression(value = true)
418
+ default_options[:skip_decompression] = !!value
419
+ end
420
+
380
421
  # Allows setting of SSL ciphers to use. This only works in Ruby 1.9+.
381
422
  # You can get a list of valid specific ciphers from OpenSSL::Cipher.ciphers.
382
423
  # You also can specify a cipher suite here, listed here at openssl.org:
@@ -543,10 +584,22 @@ module HTTParty
543
584
  perform_request Net::HTTP::Mkcol, path, options, &block
544
585
  end
545
586
 
587
+ def lock(path, options = {}, &block)
588
+ perform_request Net::HTTP::Lock, path, options, &block
589
+ end
590
+
591
+ def unlock(path, options = {}, &block)
592
+ perform_request Net::HTTP::Unlock, path, options, &block
593
+ end
594
+
546
595
  attr_reader :default_options
547
596
 
548
597
  private
549
598
 
599
+ def validate_timeout_argument(timeout_type, value)
600
+ raise ArgumentError, "#{ timeout_type } must be an integer or float" unless value && (value.is_a?(Integer) || value.is_a?(Float))
601
+ end
602
+
550
603
  def ensure_method_maintained_across_redirects(options)
551
604
  unless options.key?(:maintain_method_across_redirects)
552
605
  options[:maintain_method_across_redirects] = true
@@ -555,26 +608,21 @@ module HTTParty
555
608
 
556
609
  def perform_request(http_method, path, options, &block) #:nodoc:
557
610
  options = ModuleInheritableAttributes.hash_deep_dup(default_options).merge(options)
558
- process_headers(options)
611
+ HeadersProcessor.new(headers, options).call
559
612
  process_cookies(options)
560
613
  Request.new(http_method, path, options).perform(&block)
561
614
  end
562
615
 
563
- def process_headers(options)
564
- if options[:headers] && headers.any?
565
- options[:headers] = headers.merge(options[:headers])
566
- end
567
- end
568
-
569
616
  def process_cookies(options) #:nodoc:
570
617
  return unless options[:cookies] || default_cookies.any?
571
618
  options[:headers] ||= headers.dup
572
- options[:headers]["cookie"] = cookies.merge(options.delete(:cookies) || {}).to_cookie_string
619
+ options[:headers]['cookie'] = cookies.merge(options.delete(:cookies) || {}).to_cookie_string
573
620
  end
574
621
 
575
622
  def validate_format
576
623
  if format && parser.respond_to?(:supports_format?) && !parser.supports_format?(format)
577
- raise UnsupportedFormat, "'#{format.inspect}' Must be one of: #{parser.supported_formats.map(&:to_s).sort.join(', ')}"
624
+ supported_format_names = parser.supported_formats.map(&:to_s).sort.join(', ')
625
+ raise UnsupportedFormat, "'#{format.inspect}' Must be one of: #{supported_format_names}"
578
626
  end
579
627
  end
580
628
  end
@@ -632,6 +680,7 @@ module HTTParty
632
680
  end
633
681
 
634
682
  require 'httparty/hash_conversions'
683
+ require 'httparty/utils'
635
684
  require 'httparty/exceptions'
636
685
  require 'httparty/parser'
637
686
  require 'httparty/request'
@@ -8,7 +8,7 @@
8
8
  body {font:13px arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}table {font-size:inherit;font:100%;}select, input, textarea {font:99% arial,helvetica,clean,sans-serif;}pre, code {font:115% monospace;*font-size:100%;}body * {line-height:1.22em;}
9
9
  body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}/*ol,ul {list-style:none;}*/caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym {border:0;}
10
10
  /* end of yahoo reset and fonts */
11
-
11
+
12
12
  body {color:#333; background:#4b1a1a; line-height:1.3;}
13
13
  p {margin:0 0 20px;}
14
14
  a {color:#4b1a1a;}